Framebuffer读取bmp格式转RGB565
发布时间
阅读量:
阅读量
(1)开发板挂载优盘方法:
ls /dev
mkdir /mnt/usb
mount /dev/sda1 /mnt/usb
cp /mnt/usb/......
umount /mnt/usb
(2)framebuffer程序: bpp像素深度,常见的有bpp24中rgb888和rgb666,一个像素三个字节;bpp16中rgb565,一个像素两个字节。rgb565,r.offset =11,g.offset=5,b.offset = 0; rgb666, r.offset = 16, g.offset = 8, b.offset = 0。
// 本文件用来解析BMP图片,并且显示到fb中
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <linux/fb.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
// 宏定义
//#define FBDEVICE "/dev/fb0"
// 开发板
//#define WIDTH 1024
//#define HEIGHT 768
//我们规定最大支持1920*1080这么大的图片,BPP最多24
#define BMP_MAX_RESOLUTION (1920*1080)
#define BMP_BUF_SIZE (BMP_MAX_RESOLUTION*3)
char rgb_buf[BMP_BUF_SIZE]; // 全局变量
unsigned char *pfb = NULL; // pfb指向framebuffer内存地址首地址
int fbfd = -1; // 打开fb后得到的fd
struct fb_fix_screeninfo finfo;
struct fb_var_screeninfo vinfo;
// 结构体用来封装一个图片的各种信息
typedef struct pic_info
{
char *pathname; // 图片在文件系统中的路径名+文件名
unsigned int width; // 图片分辨率之宽
unsigned int height; // 图片分辨率之高
unsigned int bpp; // 图片bpp
char *pData; // 指向图片有效数据存储的buf数据
}pic_info;
// BMP 文件头
typedef struct
{
// unsigned short bfType; // 2
unsigned long bfSize; // 4
unsigned short bfReserved1;
unsigned short bfReserved2;
unsigned long bfOffBits;
} ClBitMapFileHeader;
// BMP 信息头
typedef struct
{
unsigned long biSize;
long biWidth;
long biHeight;
unsigned short biPlanes;
unsigned short biBitCount;
unsigned long biCompression;
unsigned long biSizeImage;
long biXPelsPerMeter;
long biYPelsPerMeter;
unsigned long biClrUsed;
unsigned long biClrImportant;
} ClBitMapInfoHeader;
// 函数声明
void fb_close(void);
int display_bmp(const char *pathname);
void fb_draw_1024(const struct pic_info *pPic);
void fb_draw_800(const struct pic_info *pPic);
void fb_draw_1920(const struct pic_info *pPic);
int bmp_analyze(struct pic_info *pPic);
void fb_close(void)
{
close(fbfd);
}
// 判断一个图片文件是不是一个合法的bmp文件;返回值: 如果是则返回0,不是则返回-1
int is_bmp(const char *path)
{
int fd = -1;
unsigned char buf[2] = {0};
ssize_t ret = 0;
// 第一步: 打开bmp图片
fd = open(path, O_RDONLY);
if (fd < 0)
{
fprintf(stderr, "open %s error.\n", path);
return -1;
}
// 第二步: 读取文件头信息
ret = read(fd, buf, 2);
if (ret != 2)
{
fprintf(stderr, "read file header error.\n");
ret = -1;
goto close;
}
// 解析头
// 第三步: 判断是不是BMP图片
if ((buf[0] != 'B') || (buf[1] != 'M'))
{
//fprintf(stderr, "file %s is not a bmp picture.\n", path);
ret = -1;
goto close;
}
else
{
ret = 0;
printf("OK\n");
}
close:
close(fd);
return ret;
}
// 参数列表: path: 要解析的bmp图片的pathname
// 函数功能: 该函数解析path这个bmp图片,并且将解析出来的图片数据丢到邋rgb_buf中去
// 返回值 : 错误时返回-1,解析正确返回0
int bmp_analyze(struct pic_info *pPic)
{
int fd = -1;
ClBitMapFileHeader fHeader;
ClBitMapInfoHeader info;
unsigned short tmp;
unsigned long len;
// 第一步: 打开bmp图片
fd = open(pPic->pathname, O_RDONLY);
if (fd < 0)
{
fprintf(stderr, "open %s error.\n", pPic->pathname);
return -1;
}
// 第二步: 读取文件头信息
read(fd, &tmp, 2);
read(fd, &fHeader, sizeof(fHeader));
printf("bfSize = %ld.\n", fHeader.bfSize);
printf("bfOffBits = %ld.\n", fHeader.bfOffBits);
read(fd, &info, sizeof(info));
printf("picutre resolution: %ld x %ld.\n", info.biWidth, info.biHeight);
printf("picture bpp: %d.\n", info.biBitCount);
pPic->width = info.biWidth;
pPic->height = info.biHeight;
pPic->bpp = info.biBitCount; // 利用输出型参数
// 第三步: 读取图片有效信息
// 先把文件指针移动到有效信息的偏移量处
lseek(fd, fHeader.bfOffBits, SEEK_SET);
// 然后读出info.biWidth * info.biHeight * info.biBitCount / 3 这么多字节即可
len = info.biWidth * info.biHeight * info.biBitCount / 3;
read(fd, rgb_buf, len);
pPic->pData = rgb_buf;
// 第四步: 把内容丢到fb中去显示
//fb_draw_1024(pPic);
// 选择图片大小
if ( vinfo.bits_per_pixel == 16)
{
fb_draw_1024(pPic);
}
else if (vinfo.bits_per_pixel == 24 && pPic->width == 800)
{
fb_draw_800(pPic);
}
else if(vinfo.bits_per_pixel == 24)
{
fb_draw_1920(pPic);
}
else
{
printf("bpp is ooo\n");
}
printf("bmp_analyze success...\n");
// 最后关闭打开的文件
//close(fd);
return 0;
}
// 封装的一个对外使用的bmp显示函数
// 本函数对外只需要一个bmp图片的pathname即可,那些复杂的数据结构都是bmp显示模块内部处理的
// 正确显示图片返回0,显示过程中出错则返回-1
int display_bmp(const char *pathname)
{
int ret = -1;
struct pic_info picture;
// 第一步: 检测给的图片是不是bmp图片
ret = is_bmp(pathname);
if (ret != 0)
{
return -1;
}
// 第二步: 显示该图片
picture.pathname = pathname;
// picture.pData = rgb_buf;
bmp_analyze(&picture);
}
// rgb888转rgb565,1024*768并镜像显示
void fb_draw_1024(const struct pic_info *pPic)
{
printf("fb_draw_1024......\n");
char *pData = (char *)pPic->pData; // 指针指向图像数组
printf("image resolution: %d * %d, bpp=%d.\n", pPic->width, pPic->height, pPic->bpp);
unsigned int x = 0,y = 0,cnt = 0;
unsigned int a = pPic->height * pPic->width * 3-3;
unsigned int linebyte = pPic->width*2;
for (int i = 0;i < pPic->height; i++)
{
for (int j = 0;j <pPic->width*2;j+=2)
{
cnt = linebyte *i + j;
*(pfb + cnt + linebyte - 2*j - 2) = ((pData[a+0]&0xF8)>>3) | ((pData[a+1]&0XFC)<<3);
*(pfb +cnt + linebyte - 2*j -1) = ((pData[a+1]&0xE0)>>5) | ((pData[a+2]&0XF8));
a-=3;
}
}
/*
// 镜像
for(x = 0;x < pPic->height ; x++)
{
for (y = 0 ;y < pPic->width ; y+=2)
{
unsigned char p1,p2;
p1 = *(pfb + linebyte*x + y);
*(pfb + linebyte*x + y) = *(pfb + linebyte*x + linebyte-y-2);
*(pfb + linebyte*x +linebyte-y-2) = p1;
p2 = *(pfb + linebyte*x + y + 1) ;
*(pfb + linebyte*x + y + 1) = *(pfb + linebyte*x +linebyte-y-1);
*(pfb +linebyte*x +linebyte-y-1) = p2;
}
}
*/
}
/*
// 800X480 , rgb888转rgb666, bpp=24
void fb_draw_800(const struct pic_info *pPic)
{
printf("fb_draw_800......\n");
char *pData = (char *)pPic->pData; // 指针指向图像数组
printf("image resolution: %d * %d, bpp=%d.\n", pPic->width, pPic->height, pPic->bpp);
unsigned int cnt = 0;
unsigned int a = pPic->height * pPic->width * 3-4;
unsigned int linebytee = pPic->width*3*6/8;
for (int i = 0;i < pPic->height; i++)
{
for(int j = 0;j < linebytee;j+=3)
{
cnt = linebytee * i + j;
*(pfb + cnt + linebytee - 2*j - 2) = (pData[a+0]>>2) | ((pData[a+1]&0X0C)<<4);
*(pfb + cnt + linebytee - 2*j - 1) = ((pData[a+1]&0xF0)>>4) | ((pData[a+2]&0X3C)<<2);
*(pfb + cnt + linebytee - 2*j) = ((pData[a+2]&0xC0)>>6) | ((pData[a+3]&0XFC));
a -=4;
}
}
}
*/
// 800X480,rgb888转rgb666,bpp=24; red.offset =16; green.offset = 8; blue.offset = 0;
void fb_draw_800(const struct pic_info *pPic)
{
printf("fb_draw_800_bpp24......\n");
char *pData = (char *)pPic->pData; // 指针指向图像数组
printf("image resolution: %d * %d, bpp=%d.\n", pPic->width, pPic->height, pPic->bpp);
unsigned int cnt = 0;
unsigned int a = pPic->height * pPic->width * 3-3;
unsigned int linebytee = pPic->width*3;
for (int i = 0;i < pPic->height; i++)
{
for(int j = 0;j < linebytee;j+=3)
{
cnt = linebytee * i + j;
*(pfb + cnt + linebytee - 2*j - 2) = (pData[a+0]>>2);
*(pfb + cnt + linebytee - 2*j - 1) = (pData[a+1]>>2);
*(pfb + cnt + linebytee - 2*j) = (pData[a+2]>>2);
a -=3;
}
}
}
// 1920*1080 , rgb888直接输出
void fb_draw_1920(const struct pic_info *pPic)
{
printf("fb_draw_1920......\n");
char *pData = (char *)pPic->pData; // 指针指向图像数组
printf("image resolution: %d * %d, bpp=%d.\n", pPic->width, pPic->height, pPic->bpp);
unsigned int x = 0,y = 0,cnt = 0;
unsigned int a = pPic->height * pPic->width * 3-3;
unsigned int linebyte = pPic->width*3;
for (int i = 0;i < pPic->height; i++)
{
for (int j = 0;j <pPic->width*3;j+=3)
{
cnt = linebyte * i + j;
*(pfb + cnt + linebyte - 2*j - 2) = pData[a+0];
*(pfb + cnt + linebyte - 2*j - 1) = pData[a+1];
*(pfb + cnt + linebyte - 2*j ) = pData[a+2];
a -=3;
}
}
}
//************************************************************************************************************//
int main (int argc,char **argv)
{
int ret =-1,rett = -1,fbfd = -1;
// struct fb_fix_screeninfo finfo;
// struct fb_var_screeninfo vinfo;
if (argc != 3) {
printf("arg error, example:./a.out /dev/fb0 1024.bmp\n");
return 0;
}
// 第1步:打开设备
fbfd = open(argv[1], O_RDWR);
if (fbfd < 0)
{
perror("open error");
return -1;
}
printf("open %s success.\n", argv[1]);
// 第2步:获取设备的硬件信息
ret = ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo);
if (ret < 0)
{
perror("ioctl");
return -1;
}
printf("smem_start = 0x%lx, smem_len = %u.\n", finfo.smem_start, finfo.smem_len);
ret = ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo);
if (ret < 0)
{
perror("ioctl");
return -1;
}
printf("xres = %u, yres = %u.\n", vinfo.xres, vinfo.yres);
printf("xres_virtual = %u, yres_virtual = %u.\n", vinfo.xres_virtual, vinfo.yres_virtual);
printf("bpp = %u.\n", vinfo.bits_per_pixel);
// 第3步:进行mmap
unsigned long len = vinfo.xres_virtual * vinfo.yres_virtual * vinfo.bits_per_pixel / 8;
printf("len = %ld\n", len);
pfb = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0);
if (NULL == pfb)
{
perror("mmap error");
return -1;
}
printf("pfb = %p.\n", pfb);
// 第4步 :执行图片函数
display_bmp(argv[2]);
fb_close();
return 0;
}
实验平台:imx,1024 768LCD屏幕;rgb565已测;运行命令,./a.out /dev/fb *.bmp。
全部评论 (0)
还没有任何评论哟~
