framebuffer显示bmp文件,考虑填补问题
2017-11-03 09:43
281 查看
因为bmp文件的宽度如果不是4的倍数,就会自动填充。因为这个问题掉到坑里了,导致图片是黑白的,下面这个代码考虑填充的问题,关键在下面的skip代码。我的机器显示屏是24位的,bmp文件也是24位的,测试代码如下
/*************************
*bmp.c文件
*************************/
#include "bmp.h"
/*************************
*fbp,映射内存起始地址
*scrinfo,屏幕信息结构体
*bmpname,.bmp位图文件名
*************************/
int show_photo(char *fbp, struct fb_var_screeninfo *scrinfo, const char *bmpname)
{
if(NULL == fbp || NULL == scrinfo || NULL == bmpname)
return -1;
int line_x = 0, line_y = 0;
unsigned long tmp = 0;
int xres = scrinfo->xres_virtual;//屏幕宽(虚拟)
int bits_per_pixel = scrinfo->bits_per_pixel;//屏幕位数
BitMapFileHeader FileHead;
BitMapInfoHeader InfoHead;
RgbQuad rgb;
unsigned long location = 0;
//打开.bmp文件
FILE *fb = fopen(bmpname, "rb");
if (fb == NULL)
{
printf("fopen bmp error\r\n");
return -1;
}
//读文件信息
if (1 != fread( &FileHead, sizeof(BitMapFileHeader),1, fb))
{
printf("read BitMapFileHeader error!\n");
fclose(fb);
return -1;
}
if (memcmp(FileHead.bfType, "BM", 2) != 0)
{
printf("it's not a BMP file\n");
fclose(fb);
return -1;
}
//读位图信息
if (1 != fread( (char *)&InfoHead, sizeof(BitMapInfoHeader),1, fb))
{
printf("read BitMapInfoHeader error!\n");
fclose(fb);
return -1;
}
printf("bfOffBits:%d\n", FileHead.bfOffBits);
//跳转至数据区
fseek(fb, FileHead.bfOffBits, SEEK_SET);
printf("biBitCount:%d\n", InfoHead.biBitCount);
int len = InfoHead.biBitCount / 8; //原图一个像素占几字节
int bits_len = bits_per_pixel / 8; //屏幕一个像素占几字节//循环显示
int icount = 2;
long ibytescount = 0;
int skip = 4-((InfoHead.biWidth*InfoHead.biBitCount)>>3)&3;
printf("skip:%d\n", skip);
while(!feof(fb))
{
tmp = 0;
if (len != fread((char *)&rgb, 1, len, fb))
break;
ibytescount += len;
//计算该像素在映射内存起始地址的偏移量
location = line_x * bits_len + (InfoHead.biHeight - line_y - 1) * xres * bits_len;
if ((line_x == 0 || line_x == 1) && icount > 0)
{
printf("red:%0x\n", rgb.Red);
printf("Green:%0x\n", rgb.Green);
printf("Blue:%0x\n", rgb.Blue);
icount--;
}
if (line_y == InfoHead.biHeight-1 && line_x == InfoHead.biWidth-1)
{
printf("end\n");
printf("red:%0x\n", rgb.Red);
printf("Green:%0x\n", rgb.Green);
printf("Blue:%0x\n", rgb.Blue);
}
*(fbp + location) = rgb.Blue; //蓝色的色深
*(fbp + location + 1) = rgb.Green; //绿色的色深
*(fbp + location + 2) = rgb.Red; //红色的色深
line_x++;
if (line_x == InfoHead.biWidth )
{
char tmp[3] = {0};
if (skip != fread(tmp, 1, skip, fb))
{
break;
}
line_x = 0;
line_y++;
if(line_y == InfoHead.biHeight)
break;
}
}
printf("show ibytescount:%d\n", ibytescount);
fclose(fb);
return 0;
}
参考文章
http://blog.csdn.net/u012877472/article/details/50272771
/*************************
*bmp.c文件
*************************/
#include "bmp.h"
/*************************
*fbp,映射内存起始地址
*scrinfo,屏幕信息结构体
*bmpname,.bmp位图文件名
*************************/
int show_photo(char *fbp, struct fb_var_screeninfo *scrinfo, const char *bmpname)
{
if(NULL == fbp || NULL == scrinfo || NULL == bmpname)
return -1;
int line_x = 0, line_y = 0;
unsigned long tmp = 0;
int xres = scrinfo->xres_virtual;//屏幕宽(虚拟)
int bits_per_pixel = scrinfo->bits_per_pixel;//屏幕位数
BitMapFileHeader FileHead;
BitMapInfoHeader InfoHead;
RgbQuad rgb;
unsigned long location = 0;
//打开.bmp文件
FILE *fb = fopen(bmpname, "rb");
if (fb == NULL)
{
printf("fopen bmp error\r\n");
return -1;
}
//读文件信息
if (1 != fread( &FileHead, sizeof(BitMapFileHeader),1, fb))
{
printf("read BitMapFileHeader error!\n");
fclose(fb);
return -1;
}
if (memcmp(FileHead.bfType, "BM", 2) != 0)
{
printf("it's not a BMP file\n");
fclose(fb);
return -1;
}
//读位图信息
if (1 != fread( (char *)&InfoHead, sizeof(BitMapInfoHeader),1, fb))
{
printf("read BitMapInfoHeader error!\n");
fclose(fb);
return -1;
}
printf("bfOffBits:%d\n", FileHead.bfOffBits);
//跳转至数据区
fseek(fb, FileHead.bfOffBits, SEEK_SET);
printf("biBitCount:%d\n", InfoHead.biBitCount);
int len = InfoHead.biBitCount / 8; //原图一个像素占几字节
int bits_len = bits_per_pixel / 8; //屏幕一个像素占几字节//循环显示
int icount = 2;
long ibytescount = 0;
int skip = 4-((InfoHead.biWidth*InfoHead.biBitCount)>>3)&3;
printf("skip:%d\n", skip);
while(!feof(fb))
{
tmp = 0;
if (len != fread((char *)&rgb, 1, len, fb))
break;
ibytescount += len;
//计算该像素在映射内存起始地址的偏移量
location = line_x * bits_len + (InfoHead.biHeight - line_y - 1) * xres * bits_len;
if ((line_x == 0 || line_x == 1) && icount > 0)
{
printf("red:%0x\n", rgb.Red);
printf("Green:%0x\n", rgb.Green);
printf("Blue:%0x\n", rgb.Blue);
icount--;
}
if (line_y == InfoHead.biHeight-1 && line_x == InfoHead.biWidth-1)
{
printf("end\n");
printf("red:%0x\n", rgb.Red);
printf("Green:%0x\n", rgb.Green);
printf("Blue:%0x\n", rgb.Blue);
}
*(fbp + location) = rgb.Blue; //蓝色的色深
*(fbp + location + 1) = rgb.Green; //绿色的色深
*(fbp + location + 2) = rgb.Red; //红色的色深
line_x++;
if (line_x == InfoHead.biWidth )
{
char tmp[3] = {0};
if (skip != fread(tmp, 1, skip, fb))
{
break;
}
line_x = 0;
line_y++;
if(line_y == InfoHead.biHeight)
break;
}
}
printf("show ibytescount:%d\n", ibytescount);
fclose(fb);
return 0;
}
#include "bmp.h" struct fb_var_screeninfo vinfo; struct fb_fix_screeninfo finfo; //打印fb驱动中fix结构信息,注:在fb驱动加载后,fix结构不可被修改。 void printFixedInfo () { printf ("Fixed screen info:\n" "\tid: %s\n" "\tsmem_start:0x%lx\n" "\tsmem_len:%d\n" "\ttype:%d\n" "\ttype_aux:%d\n" "\tvisual:%d\n" "\txpanstep:%d\n" "\typanstep:%d\n" "\tywrapstep:%d\n" "\tline_length: %d\n" "\tmmio_start:0x%lx\n" "\tmmio_len:%d\n" "\taccel:%d\n" "\n", finfo.id, finfo.smem_start, finfo.smem_len, finfo.type, finfo.type_aux, finfo.visual, finfo.xpanstep, finfo.ypanstep, finfo.ywrapstep, finfo.line_length, finfo.mmio_start, finfo.mmio_len, finfo.accel); } //打印fb驱动中var结构信息,注:fb驱动加载后,var结构可根据实际需要被重置 void printVariableInfo () { printf ("Variable screen info:\n" "\txres:%d\n" "\tyres:%d\n" "\txres_virtual:%d\n" "\tyres_virtual:%d\n" "\tyoffset:%d\n" "\txoffset:%d\n" "\tbits_per_pixel:%d\n" "\tgrayscale:%d\n" "\tred: offset:%2d, length: %2d, msb_right: %2d\n" "\tgreen: offset:%2d, length: %2d, msb_right: %2d\n" "\tblue: offset:%2d, length: %2d, msb_right: %2d\n" "\ttransp: offset:%2d, length: %2d, msb_right: %2d\n" "\tnonstd:%d\n" "\tactivate:%d\n" "\theight:%d\n" "\twidth:%d\n" "\taccel_flags:0x%x\n" "\tpixclock:%d\n" "\tleft_margin:%d\n" "\tright_margin: %d\n" "\tupper_margin:%d\n" "\tlower_margin:%d\n" "\thsync_len:%d\n" "\tvsync_len:%d\n" "\tsync:%d\n" "\tvmode:%d\n" "\n", vinfo.xres, vinfo.yres, vinfo.xres_virtual, vinfo.yres_virtual, vinfo.xoffset, vinfo.yoffset, vinfo.bits_per_pixel, vinfo.grayscale, vinfo.red.offset, vinfo.red.length, vinfo.red.msb_right,vinfo.green.offset, vinfo.green.length, vinfo.green.msb_right, vinfo.blue.offset, vinfo.blue.length, vinfo.blue.msb_right, vinfo.transp.offset, vinfo.transp.length, vinfo.transp.msb_right, vinfo.nonstd, vinfo.activate, vinfo.height, vinfo.width, vinfo.accel_flags, vinfo.pixclock, vinfo.left_margin, vinfo.right_margin, vinfo.upper_margin, vinfo.lower_margin, vinfo.hsync_len, vinfo.vsync_len, vinfo.sync, vinfo.vmode); } int main() { int devfb, filefb; unsigned long screensize; char *fbp ; char bmpname[20] = {0}; //打开设备文件 devfb = open("/dev/fb0", O_RDWR); if(!devfb) { printf("devfb open error!\r\n"); return -1; } //获取finfo信息并显示 if (ioctl (devfb, FBIOGET_FSCREENINFO, &finfo) == -1) { perror ("Error reading fixed information"); exit (2); } printFixedInfo (); //获取vinfo信息并显示 if (ioctl (devfb, FBIOGET_VSCREENINFO, &vinfo) == -1) { perror ("Error reading variable information"); exit (3); } printVariableInfo (); if(24 != vinfo.bits_per_pixel)//32 { printf("screen infomation.bits error!\r\n"); return -1; } printf("sizeof(BitMapFileHeader):%d\n", sizeof(BitMapFileHeader)); printf("sizeof(BitMapInfoHeader):%d\n", sizeof(BitMapInfoHeader)); //计算需要的映射内存大小 screensize = vinfo.xres_virtual * vinfo.yres_virtual * vinfo.bits_per_pixel / 8; //内存映射 fbp = (char *)mmap(NULL, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, devfb, 0); if(-1 == (int)fbp) { printf("mmap error!\r\n"); return -1; } memcpy(bmpname, "niu.bmp", strlen("niu.bmp")); //显示图片 show_photo(fbp, &vinfo, bmpname); //取消映射,关闭文件 munmap(fbp, screensize); close(devfb); return 0; }
参考文章
http://blog.csdn.net/u012877472/article/details/50272771
相关文章推荐
- 【Qt】在其他机器上显示不了jpg等图片,考虑库文件问题
- ubuntu12.10 32位系统使用framebuffer显示24深度bmp文件
- 解决 qtcreator编辑*.ui文件时右键菜单不能正常显示但的问题
- Office 2010 中打开多个Excel文件只能在同一窗口中显示的问题
- 关于CHM文件无法显示的问题
- NET上传大文件出现网页无法显示的问题 默认的上传文件大小是4M
- 解决gdb 调试 core 文件函数名显示为问号的问题
- 安装 .Net Framework 3.5 后 中文VS2008中无法显示MVC文件模板的问题
- bmp文件动态加载显示
- Ubuntu 9.10 实现用framebuffer显示bmp图片
- python中写入csv,excel显示、pandas读取csv文件的编码问题
- 问题解决:Sublime 乱码显示GBK编码文件解决
- 解决CHM文件打开无法显示网页的问题
- 解决FlashFXP5 不能下载中文文件名文件的问题(显示文件名中文正常下载文件名是乱码)
- 解决nginx打开php文件总是显示下载框的问题
- pdf文件中的汉字无法显示(问题解决)
- 解决JSP引入JS文件后,JS文件中字符在页面上显示为乱码问题
- Ubuntu 12.04 LTS中文txt文件显示乱码问题
- 基于framebuffer显示图片(bmp && png)和汉字
- iText7 生成 PDF 文件,解决各种操作系统中文问题,控制指定位置显示图片、文字、图文混排