良许Linux教程网 干货合集 C语言结构体描述BMP的文件格式

C语言结构体描述BMP的文件格式

BMP文件的结构非常简单,主要由两个结构体和一个可选的调色板以及位图数据组成。

第一个结构体是BITMAPFILEHEADER,它存储了位图文件的头信息。

第二个结构体是BITMAPINFOHEADER,它存储了位图的详细信息。

可选的调色板是一个RGBQUAD数组,用于存储位图的颜色信息。

最后是位图数据,包含了实际的像素信息。

第一个结构体

接下来,我们将详细介绍第一个结构体——位图文件头结构BITMAPFILEHEADER。

下面是代码原型:

typedef struct tagBITMAPFILEHEADER
{
        WORD        bfType;
        DWORD       bfSize;
        WORD        bfReserved1;
        WORD        bfReserved2;
        DWORD       bfOffBits;
} BITMAPFILEHEADER, *PBITMAPFILEHEADER;

其中:

bfType:文件的标识,值必须是0x4D42(也就是“BM”两个字符,注意是Little-Endian

bfSize:是整个文件的大小

bfReserved1和bfReserved2必须是0.

bfOffBits:是位图数据在文件中的偏移。

第二个结构体

位图信息头:BITMAPINFOHEADER

typedef struct tagBITMAPINFOHEADER
{
        DWORD       biSize;
        LONG        biWidth;
        LONG        biHeight;
        WORD        biPlanes;
        WORD        biBitCount;
        DWORD       biCompression;
        DWORD       biSizeImage;
        LONG        biXPelsPerMeter;
        LONG        biYPelsPerMeter;
        DWORD       biClrUsed;
        DWORD       biClrImportant;
} BITMAPINFOHEADER, *PBITMAPINFOHEADER;

biSize:

BITMAPINFOHEADER这个结构体的大小。必须为40(字节)。

biWidth:

BMP位图的宽度。

biHeight:

BMP位图的宽度。

这里需要说明一下的是,BMP位图数据有两种存储方式,通常是“底到上型”,也就是BMP位图数据的第一行其实是这个图片的最后一行。一种是“顶到下型”,BMP位图数据的第一行就是图片的第一行。

如果位图是“顶到下型”,那么biHeight的值是负的,位图的实际高度其实是(-biHeight),也就是它的相反数。

只有“底到上型”位图支持压缩。“底到上型”是目前最常见的位图类型。

PhotoShop在保存位图文件的时候,你可以设置让它输出“底到上型”或“顶到下型”。“顶到下型”就是“逆行序”。

biPlanes:

位图的“位面数”。这个值必须为1.

biBitCount:

位图的“颜色位数”。表示位图数据中,几个二进制位表示一个像素。

颜色位数为1表示单色(其实是“双色”,通常是黑白,也可以是别的两个颜色。)

为2表示四色,也就是四种颜色。为4表示16种颜色。为8表示有256种颜色。

在表示256色以内的颜色数量的时候,这个BMP文件其实是作为使用调色板颜色的图像,因此在BITMAPINFOHEADER结构体的后面还有个调色板。

所谓调色板其实就是RGBQUAD结构体的数组。它的元素个数就是颜色数。

biCompression:

位图的压缩格式,值可以是BI_RGB(未压缩),BI_RLE8(8位RLE压缩),BI_RLE4(4位RLE压缩),BI_BITFIELDS(表示颜色表中,每个像素有3个DWORD的屏蔽位数据来指示红绿蓝成分。16位和32位位图可以使用这个。),BI_JPEG(位图数据其实是JPG格式的),BI_PNG(位图数据其实是PNG格式的)

当biCompression值为BI_RLE8的时候,biBitCount必须为8,表示这是个8位的256色索引颜色位图(有256个调色板),位图数据按照如下算法压缩:

·位图数据是每两个字节组成一个元素,这样的元素组成了一个数组。

·每个元素,第一个字节表示重复的像素的数量,第二个字节是8位的调色板颜色索引。

·如果元素的第一个字节为0,那么第二个字节有特殊的含义:

0:这行已经结束了。

1:这个位图已经结束了。

2:设置下一个像素的位置,后面的两个无符号字节分别指定了下一个像素的X、Y偏移。注意是无符号字节,意思是说,偏移只能是往后。

3到0xFF:表示后面有一段没有压缩的数据的长度,也就是连续的8位像素颜色索引数据的长度。但是数据必须是2字节对齐的。biCompression值为BI_RLE4的时候,biBitCount必须为4,表示这是个4位的16色索引颜色位图(有16个调色板)。

和BI_RLE8的区别只是每个元素的第二个字节如果表示颜色索引,它表示的是两个像素的颜色索引。第一个字节表示重复的数量,第二个字节表示两个像素的颜色。

举个例,假设调色板第0号色是黑色,第1号色是白色,元素的值是0x05,0x01,那么它表示“黑白黑白黑白黑白黑白”共10个像素出现在1行。

biSizeImage:

位图数据块的大小。以字节为单位。如果你的位图没有经过压缩,这个值可以是0.

biXPelsPerMeter:

表示横向的每米的像素数。可以为0.

biYPelsPerMeter:

表示纵向的每米的像素数。可以为0.

biClrUsed:

位图实际使用过的调色板的颜色数。如果这个值为0,表示这个位图使用了整个调色板。只有8位以及8位以下的索引颜色位图才需要考虑这个值。对于16位以及16位以上的位图,无视这个值。biClrImportant表示重要的颜色数。如果为0,表示颜色都重要。通常它的值等于biClrUsed,或者等于0.

如果位图是8位以及8位以下的位图,后面是位图的调色板数据。否则没有调色板数据。

调色板就是简单的RGBQUAD数组。

后面就是位图数据了。如果位图是没有经过压缩的,那么位图数据的存储就是一行一行的,每行都是每XX个字节一个像素,取决于位图的位数(biBitCount),每一行都是4字节对齐的!多出来的部分用0补齐。这里必须注意。

因此,每行占用的字节数要按照以下公式计算:(其中的biBitCount指的是位图的位数,也就是BITMAPINFOHEADER的成员)

每行字节数 = ((图像宽度 – 1) * biBitCount / 32 + 1) * 4;

如果你是用VB编写读取位图的话,是这样写的:

每行字节数 = ((图像宽度 – 1) * biBitCount \ 32 + 1) * 4

这里还要注意的是“底到上型”位图和“顶到下型”位图,如果BITMAPINFOHEADER的biHeight成员大于零,那么这个位图就是“底到上型”,否则就是“顶到下型”。“底到上型”的位图,它的行序是从下到上排列的,也就是逆行序。“顶到下型”位图行序是从上到下排列的。

嵌入式专栏

3

位图颜色表

位图颜色表就比较简单了:

typedef struct tagRGBQUAD
{
        BYTE        rgbBlue;
        BYTE        rgbGreen;
        BYTE        rgbRed;
        BYTE        rgbReserved;
} RGBQUAD;

红禄蓝三种颜色,然后还有保留一个字节。

最后,还有位图数据,这里就不描述了。

以上就是良许教程网为各位朋友分享的Linu系统相关内容。想要了解更多Linux相关知识记得关注公众号“良许Linux”,或扫描下方二维码进行关注,更多干货等着你 !

137e00002230ad9f26e78-265x300
本文由 良许Linux教程网 发布,可自由转载、引用,但需署名作者且注明文章出处。如转载至微信公众号,请在文末添加作者公众号二维码。
良许

作者: 良许

良许,世界500强企业Linux开发工程师,公众号【良许Linux】的作者,全网拥有超30W粉丝。个人标签:创业者,CSDN学院讲师,副业达人,流量玩家,摄影爱好者。
上一篇
下一篇

发表评论

联系我们

联系我们

公众号:良许Linux

在线咨询: QQ交谈

邮箱: yychuyu@163.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

关注微博
返回顶部