Advertisement

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)

还没有任何评论哟~