BMP图片格式处理

https://mp.weixin.qq.com/s/pwA0JxF7LM4YyzWHittmtA

平常接触的图像格式有很多种,其中BMP是windows系统的标准图像格式,BMP没有像jpeg那样的压缩比,因此他通常很臃肿,不适合用在网络间传输,但他是微软的亲生子,因此在计算机世界也大行其道,颇有影响力。

宽泛来说,BMP图像是支持压缩的,他甚至支持jpeg压缩算法,但更一般的情况是,BMP用来存储所谓的真彩色影像,即24位的BitMap(位图),本文并不想刨BMP的祖坟,将它所有的细节抽丝剥茧一一展现,本文只想针对其最常见 的存储模式做个总结,备忘。

先来看BMP格式图像的文件总体结构:

从上到下,分别是三个结构体,代码表示如下(重要的成员已标注为红色):
struct header
{
int16_t type;
int32_t size; // 图像文件大小
int16_t reserved1;
int16_t reserved2;
int32_t offbits; // bmp图像数据偏移量
}__attribute__((packed));

struct info
{
int32_t size; // 本结构大小
int32_t width; // 图像宽度(单位像素)
int32_t height; // 图像高度(单位像素)
int16_t planes; // 总为零

int16_t bit_count; // 色深
int32_t compression; // 是否压缩
int32_t size_img;
int32_t X_pel;
int32_t Y_pel;
int32_t clrused;
int32_t clrImportant;
}__attribute__((packed));

struct quad
{
int8_t blue;
int8_t green;
int8_t red;
int8_t reserved;
}__attribute__((packed));

看代码总是很无聊的,尤其是看不懂的代码!但是如果真要处理BMP图像数据,那就必须搞清楚以上代码了,挑几个重点说一下:

第一,定义了这三个结构体之后,一定要使用__attribute__((packed));来去除系统的地址对齐,否则读到的格式头会发生错误。

第二,header.size就是图像文件的大小(即文件总大小减去格式头大小)。

第三,header.offbits就是格式头的大小(可能是前两个结构体,也可能是三个结构体,因为第三个结构体quad可能有也可能没有)

第四,info.compression决定了格式头中是否含有quad结构体。

最后,要正确处理BMP图像还必须牢记在心的几个要点:
1,图像每一行所包含的字节数,必须是4的倍数,如果不够则会凑齐补足到够为止。比如某BMP图像色深为24bits,宽度为65像素,算下来一行的字节数是65乘以3等于195个字节,那在文件中将会增加一个额外的字节凑够196个字节来表示一行的数据量。

2,最后一行数据是图像的第一行,换句话说BMP是反着存储的。因此在读取BMP图像时一般从最后一行开始读取,然后读倒数第二行,以此类推,然后将读取到的数据依次刷新到显存,这样才能正确显示图像,否则图片看起来是反的。

附一张刷BMP图的代码:

参数:
1,bmpfile是需要显示的BMP图片名称
2,FB是显存指针
3,vinfo是LCD参数结构信息
4,xoffset和yoffet是图片要显示的位置坐标

你可能感兴趣的:(BMP图片格式处理)