稍微了解了下linux的framebuffer,这是一种很简单的显示接口,直接写入像素信息即可
配置好的内核,会有/dev/fbn 的接口,于是想能否提前生成一个文件,比如logo.fb,里面仅包含像素信息,从而可以直接送入framebuffer显示
搜索了一下,有不少文章介绍,如何解析bmp图片并送给framebuffer显示,但没有找到预处理工具,都是直接处理完就送入framebuffer
于是参考了一篇文章,改动了下代码,将直接送入framebuffer变成写到一个文件中。
原代码地址为
http://blog.csdn.net/xsckernel/article/details/49992315
测试得到的文件,是可以直接 cat logo.fb > /dev/fb0 进行显示的
注意:这个程序是给我那个24位的屏用的,如果是32位或者16位的话需要修改
#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <string.h> #include <linux/fb.h> #include <sys/mman.h> #include <sys/ioctl.h> #include <arpa/inet.h> #include <errno.h> //author:http://blog.csdn.net/xsckernel/article/details/49992315 //modify :zqb-all //14byte文件头 typedef struct { char cfType[2];//文件类型,"BM"(0x4D42) int cfSize;//文件大小(字节) int cfReserved;//保留,值为0 int cfoffBits;//数据区相对于文件头的偏移量(字节) }__attribute__((packed)) BITMAPFILEHEADER; //__attribute__((packed))的作用是告诉编译器取消结构在编译过程中的优化对齐 //40byte信息头 typedef struct { char ciSize[4];//BITMAPFILEHEADER所占的字节数 int ciWidth;//宽度 int ciHeight;//高度 char ciPlanes[2];//目标设备的位平面数,值为1 int ciBitCount;//每个像素的位数 char ciCompress[4];//压缩说明 char ciSizeImage[4];//用字节表示的图像大小,该数据必须是4的倍数 char ciXPelsPerMeter[4];//目标设备的水平像素数/米 char ciYPelsPerMeter[4];//目标设备的垂直像素数/米 char ciClrUsed[4]; //位图使用调色板的颜色数 char ciClrImportant[4]; //指定重要的颜色数,当该域的值等于颜色数时(或者等于0时),表示所有颜色都一样重要 }__attribute__((packed)) BITMAPINFOHEADER; typedef struct { unsigned char blue; unsigned char green; unsigned char red; unsigned char reserved; }__attribute__((packed)) PIXEL;//颜色模式RGB BITMAPFILEHEADER FileHead; BITMAPINFOHEADER InfoHead; static char *fbp = 0; static int xres = 0; static int yres = 0; static int bits_per_pixel = 0; int width, height; int show_bmp(); int fbfd = 0; static int cursor_bitmap_format_convert(char *dst,char *src) { int i ,j ; char *psrc = src ; char *pdst = dst; char *p = psrc; /* 由于bmp存储是从后面往前面,所以需要倒序进行转换 */ pdst += (width * height * 3); for(i=0;i<height;i++){ p = psrc + (i+1) * width * 3; for(j=0;j<width;j++){ pdst -= 3; p -= 3; pdst[0] = p[0]; pdst[1] = p[1]; pdst[2] = p[2]; } } return 0; } int show_bmp(char *path,char *fb_path) { int i; FILE *fp,*fb_file; int rc; int line_x, line_y; long int location = 0, BytesPerLine = 0; char *bmp_buf = NULL; char *bmp_buf_dst = NULL; char * buf = NULL; int flen = 0; int ret = -1; int total_length = 0; printf("into show_bmp function "); if(path == NULL || fb_path == NULL) { printf("path Error,return "); return -1; } printf("path = %s ", path); fp = fopen( path, "rb" ); if(fp == NULL){ printf("load cursor file open failed "); return -1; } printf("fb_path = %s ", fb_path); fb_file = fopen( fb_path, "wb" ); if(fp == NULL){ printf("load cursor file open failed "); return -1; } /* 求解文件长度 */ fseek(fp,0,SEEK_SET); fseek(fp,0,SEEK_END); flen = ftell(fp); printf("flen is %d ",flen); bmp_buf = (char*)calloc(1,flen - 54); if(bmp_buf == NULL){ printf("load > malloc bmp out of memory! "); return -1; } /* 再移位到文件头部 */ fseek(fp,0,SEEK_SET); rc = fread(&FileHead, sizeof(BITMAPFILEHEADER),1, fp); if ( rc != 1) { printf("read header error! "); fclose( fp ); return( -2 ); } //检测是否是bmp图像 if (memcmp(FileHead.cfType, "BM", 2) != 0) { printf("it's not a BMP file "); fclose( fp ); return( -3 ); } rc = fread( (char *)&InfoHead, sizeof(BITMAPINFOHEADER),1, fp ); if ( rc != 1) { printf("read infoheader error! "); fclose( fp ); return( -4 ); } width = InfoHead.ciWidth; height = InfoHead.ciHeight; printf("FileHead.cfSize =%d byte ",FileHead.cfSize); printf("flen = %d ", flen); printf("width = %d, height = %d ", width, height); total_length = width * height *3; printf("total_length = %d ", total_length); //跳转的数据区 fseek(fp, FileHead.cfoffBits, SEEK_SET); printf(" FileHead.cfoffBits = %d ", FileHead.cfoffBits); printf(" InfoHead.ciBitCount = %d ", InfoHead.ciBitCount); //每行字节数 buf = bmp_buf; while ((ret = fread(buf,1,total_length,fp)) >= 0) { if (ret == 0) { usleep(100); continue; } printf("ret = %d ", ret); buf = ((char*) buf) + ret; total_length = total_length - ret; if(total_length == 0) break; } ///重新计算,很重要!! total_length = width * height *3; bmp_buf_dst = (char*)calloc(1,total_length ); if(bmp_buf_dst == NULL){ printf("load > malloc bmp out of memory! "); return -1; } cursor_bitmap_format_convert(bmp_buf_dst, bmp_buf); fwrite(bmp_buf_dst,1,total_length,fb_file); free(bmp_buf); free(bmp_buf_dst); fclose(fp); fclose(fb_file); printf("show logo return 0 "); return 0; } int main() { show_bmp( "./logo.bmp","./logo.fb"); }
测试可用后,又想到,这是在我的主机上做的预处理,那完全可以不用c语言呀,搞点简洁些的,比如python
于是有了这个python版本
要安装PIL
sudo apt-get install python-imaging
PIL介绍就不多说了,我也是第一次用,大家搜一下很多介绍文章的,代码如下
#!/usr/bin/env python2 import struct from PIL import Image im = Image.open('logo.bmp') w, h = im.size print( "w:", w ,"h:", h) with open('logo.fb', 'wb') as f: for j in range(0,h): for i in range(0,w): r,g,b =im.getpixel((i,j)) rgb=struct.pack('BBB',b,g,r) f.write(rgb);
补充,Python版本的拓展:
请查看文章 python将图片转换为Framebuffer裸数据格式(终端显示图片) 或代码 https://github.com/zqb-all/convertfb
本文地址:http://www.cnblogs.com/zqb-all/p/6080429.html