Linux 显示 bmp 错位(宽度不能被4整除问题)

发布时间 2023-09-05 17:08:19作者: FBshark

主要参考文章:《gec6818_液晶屏显示bmp图片》

辅助参考文章:《关于bmp图片倾斜的解决方法》

 

24位bmp格式图片的编码特点:

  1. 每个像素点占3个字节存放的BGR数据  B蓝色  G绿色  R红色。(不是RGB)
  2. 图片的宽度占用的字节数如果不能被4整除,window系统会给每一行尾端填充垃圾数凑够4字节整除。

                           

如示例图中一张750*450的bmp图片,每一行的数据应该是750x3 = 2250字节,但2250不能被4整除,所以系统会自动在每一行后面补齐2个字节数据,达到2252字节,这样图片的长就被拉长了,就会出现倾斜现象。

 

那么如何解决这个问题呢,原博这样解决:

//判断宽度是否能被4整除
	if(width%4==0){
		//被4整除,一下子读完
		read(bmpfd,bmpbuf,width*height*3);
	}else{
		//不被4整除,一行一行读
		//每行读到最后(width),设置当前往后偏移(宽%4的余数)
		for(i=0;i<height;i++){
			read(bmpfd,bmpbuf+i*width*3,width*3);
			lseek(bmpfd,width%4,SEEK_CUR); //跳过垃圾数据
		}
	}

 是通过 lseek(bmpfd,width%4,SEEK_CUR); 跳过垃圾数据实现的。

 

原博的程序不太严谨,仅仅考虑了 width(图片宽度),而没算进去 byte_depth(图片颜色深度),因此我小小修改如下:

//检查图片宽度字节数是否能被4整除
div4_mod = (pic_w * byte_depth)%4;  //算进去 byte_depth(图片颜色深度)
printf("div4_mod = %d\n", div4_mod);

//读bmp一行的数据,读取的字节数为pic_w*byte_depth
if(div4_mod == 0) //如果图片宽度字节不为4整除,那么用 lseek() 跳过补充字节
{
    if(pic_w*byte_depth != read(fpic, line_buf, pic_w*byte_depth))
    {
        perror("read failed!");
        exit(-1);
    }
}else
{
    if(pic_w*byte_depth != read(fpic, line_buf, pic_w*byte_depth))
    {
        perror("read failed!");
        exit(-1);
    }
    lseek(fpic, div4_mod, SEEK_CUR);//lseek() 跳过补充字节
}