framebuffer显示bmp文件,考虑填补问题

因为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


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值