Linux framebuffer显示bmp图片
2017-09-22 14:15
507 查看
制器参数。比如图形硬件上实际的帧缓存空间的大小、能否硬件加速等信息。
应用程序中通常要用到struct fb_var_screeninfo的下面这几个字段:
xres、yres、bits_per_pixel,分别表示x轴的分辨率、y轴的分辨率以及每像素的颜色深度(颜色深度的单位为bit/pixel),其类型定义都是无符号32位整型数。
这里我们是使用qemu模拟的,否则用主机会打乱工作环境! 首先按照我以前博文:
linux内核调试环境搭建搭建起来一个最小linux环境。
注意到在编译内核的时候要加入一个内核配置选项,不然内核不支持 qemu 显卡设备,也就无法创建/dev/fb0 设备文件。
配置位置:
qemu启动命令行参数如下:
启动qemu之后,打开上面代码编译的应用程序可见bmp文件被完整的显示出来:
上面代码中调用函数 cursor_bitmap_format_convert 是由于bmp图象是从下至上存储的,所以我们不能进行直接顺序读取。详细的说,bmp图象存储区数据是从1078偏移字节开始。文件内第一个图象点实际上是对应图象(320*200)第200行的最左边的第一个点,而从1078开始的320个点则是图象最下面一行对应的点,之后的321个点是图象倒数第二行最左边的第一个点。这样,bmp文件最后一个字节对应的点是第一行最后边的点了。
关于bmp文件格式这里就不分析了,相对于jpeg等压缩格式,这个格式十分简单网上很多资料
注意:上面的程序只在framebuffer上显示图片,却没有删除刷新屏幕,可以使用下面的命令恢复屏幕
保存屏幕信息:dd if=/dev/fb0 of=fbfile 或: cp /dev/fb0 fbfile
恢复屏幕信息:dd if=fbfile of=/dev/fb0 或: cat fbfile > /dev/fb0
bmp 位图文件:
drop上的文件,似乎这几天ss很难用,过几天再放上原图
就是一个PC bitmap, Windows 3.x format, 1024 x 768 x 24 位图文件。
应用程序中通常要用到struct fb_var_screeninfo的下面这几个字段:
xres、yres、bits_per_pixel,分别表示x轴的分辨率、y轴的分辨率以及每像素的颜色深度(颜色深度的单位为bit/pixel),其类型定义都是无符号32位整型数。
#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> //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 void fb_update(struct fb_var_screeninfo *vi) //将要渲染的图形缓冲区的内容绘制到设备显示屏来 { vi->yoffset = 1; ioctl(fbfd, FBIOPUT_VSCREENINFO, vi); vi->yoffset = 0; ioctl(fbfd, FBIOPUT_VSCREENINFO, vi); } 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) { int i; FILE *fp; 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\n"); if(path == NULL) { printf("path Error,return\n"); return -1; } printf("path = %s\n", path); fp = fopen( path, "rb" ); if(fp == NULL){ printf("load cursor file open failed\n"); return -1; } /* 求解文件长度 */ fseek(fp,0,SEEK_SET); fseek(fp,0,SEEK_END); flen = ftell(fp); printf("flen is %d\n",flen); bmp_buf = (char*)calloc(1,flen - 54); if(bmp_buf == NULL){ printf("load > malloc bmp out of memory!\n"); return -1; } /* 再移位到文件头部 */ fseek(fp,0,SEEK_SET); rc = fread(&FileHead, sizeof(BITMAPFILEHEADER),1, fp); if ( rc != 1) { printf("read header error!\n"); fclose( fp ); return( -2 ); } //检测是否是bmp图像 if (memcmp(FileHead.cfType, "BM", 2) != 0) { printf("it's not a BMP file\n"); fclose( fp ); return( -3 ); } rc = fread( (char *)&InfoHead, sizeof(BITMAPINFOHEADER),1, fp ); if ( rc != 1) { printf("read infoheader error!\n"); fclose( fp ); return( -4 ); } width = InfoHead.ciWidth; height = InfoHead.ciHeight; printf("FileHead.cfSize =%d byte\n",FileHead.cfSize); printf("flen = %d\n", flen); printf("width = %d, height = %d\n", width, height); total_length = width * height *3; printf("total_length = %d\n", total_length); //跳转的数据区 fseek(fp, FileHead.cfoffBits, SEEK_SET); printf(" FileHead.cfoffBits = %d\n", FileHead.cfoffBits); printf(" InfoHead.ciBitCount = %d\n", InfoHead.ciBitCount); //每行字节数 buf = bmp_buf; while ((ret = fread(buf,1,total_length,fp)) >= 0) { if (ret == 0) { usleep(100); continue; } printf("ret = %d\n", 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!\n"); return -1; } cursor_bitmap_format_convert(bmp_buf_dst, bmp_buf); memcpy(fbp,bmp_buf_dst,total_length); free(bmp_buf); free(bmp_buf_dst); fclose(fp); printf("show logo return 0\n"); return 0; } int show_picture(int fd, char *path) { struct fb_var_screeninfo vinfo; struct fb_fix_screeninfo finfo; long int screensize = 0; struct fb_bitfield red; struct fb_bitfield green; struct fb_bitfield blue; //打开显示设备 fbfd = fd; //open("/dev/graphics/fb0", O_RDWR); printf("fbfd = %d\n", fbfd); if (fbfd == -1) { //printf("Error opening frame buffer errno=%d (%s)\n",errno, strerror(errno)); return -1; } if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo)) { //printf("Error:reading fixed information.\n"); return -1; } if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)) { //printf("Error: reading variable information.\n"); return -1; } //printf("R:%x ;G:%d ;B:%d \n", (int)vinfo.red, vinfo.green, vinfo.blue ); //printf("%dx%d, %dbpp\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel ); xres = vinfo.xres; yres = vinfo.yres; bits_per_pixel = vinfo.bits_per_pixel; //计算屏幕的总大小(字节) screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8; printf("screensize=%ld byte\n",screensize); //对象映射 fbp = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0); if (fbp == (char *)-1) { printf("Error: failed to map framebuffer device to memory.\n"); return -1; } printf("sizeof file header=%ld\n", sizeof(BITMAPFILEHEADER)); //显示图像 show_bmp(path); ///在屏幕上显示多久 sleep(100); fb_update(&vinfo); //删除对象映射 munmap(fbp, screensize); return 0; } int main() { int fbfd = 0; fbfd = open("/dev/fb0", O_RDWR); if (!fbfd) { printf("Error: cannot open framebuffer device.\n"); exit(1); } show_picture(fbfd, "./girl.bmp"); close(fbfd); }
这里我们是使用qemu模拟的,否则用主机会打乱工作环境! 首先按照我以前博文:
linux内核调试环境搭建搭建起来一个最小linux环境。
注意到在编译内核的时候要加入一个内核配置选项,不然内核不支持 qemu 显卡设备,也就无法创建/dev/fb0 设备文件。
CONFIG_DRM_CIRRUS_QEMU=y
config DRM_CIRRUS_QEMU tristate "Cirrus driver for QEMU emulated device" depends on DRM && PCI select FB_SYS_FILLRECT select FB_SYS_COPYAREA select FB_SYS_IMAGEBLIT select DRM_KMS_HELPER select DRM_KMS_FB_HELPER select DRM_TTM help This is a KMS driver for emulated cirrus device in qemu. It is *NOT* intended for real cirrus devices. This requires the modesetting userspace X.org driver.
配置位置:
Device Drivers ---> Graphics support ---> Direct Rendering Manager ---> Direct Rendering Manager (XFree86 4.1.0 and higher DRI support) ---> <*> Cirrus driver for QEMU emulated device
qemu启动命令行参数如下:
qemu -m 512 -kernel bzImage -append "root=/dev/sda rw" -boot c -hda busybox.img -k en-us -vga cirrus -net nic -net tap,ifname=tap0,script=no
启动qemu之后,打开上面代码编译的应用程序可见bmp文件被完整的显示出来:
上面代码中调用函数 cursor_bitmap_format_convert 是由于bmp图象是从下至上存储的,所以我们不能进行直接顺序读取。详细的说,bmp图象存储区数据是从1078偏移字节开始。文件内第一个图象点实际上是对应图象(320*200)第200行的最左边的第一个点,而从1078开始的320个点则是图象最下面一行对应的点,之后的321个点是图象倒数第二行最左边的第一个点。这样,bmp文件最后一个字节对应的点是第一行最后边的点了。
关于bmp文件格式这里就不分析了,相对于jpeg等压缩格式,这个格式十分简单网上很多资料
注意:上面的程序只在framebuffer上显示图片,却没有删除刷新屏幕,可以使用下面的命令恢复屏幕
保存屏幕信息:dd if=/dev/fb0 of=fbfile 或: cp /dev/fb0 fbfile
恢复屏幕信息:dd if=fbfile of=/dev/fb0 或: cat fbfile > /dev/fb0
bmp 位图文件:
drop上的文件,似乎这几天ss很难用,过几天再放上原图
就是一个PC bitmap, Windows 3.x format, 1024 x 768 x 24 位图文件。
相关文章推荐
- linux framebuffer 显示bmp图片
- linux framebuffer 显示bmp图片
- Linux framebuffer显示bmp图片【转】
- Linux framebuffer显示bmp图片
- Linux framebuffer显示bmp图片
- Linux framebuffer显示bmp图片
- Linux framebuffer显示bmp图片
- Linux framebuffer显示bmp图片
- 嵌入式linux------SDL移植(am335x下显示bmp图片)
- Linux framebuffer显示bmp图片
- Linux framebuffer显示bmp图片
- Linux framebuffer显示bmp图片
- linux 下使用opengl的glut库显示和旋转BMP图片
- frameburrer显示bmp图片( 程序)
- 嵌入式linux------SDL移植(am335x下显示bmp图片) 分类: TI-AM335X ffmpeg-SDL-VLC-Live555 2015-07-28 15:51 131人阅读 评论(0) 收藏
- Linux framebuffer显示bmp图片
- 嵌入式linux------SDL移植(am335x下显示bmp图片)
- Linux framebuffer显示bmp图片
- Linux: Framebuffer显示bmp图片
- 嵌入式linux------SDL移植(am335x下显示bmp图片)