您的位置:首页 > Web前端

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;
}

#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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: