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成员大于零,那么这个位图就是“底到上型”,否则就是“顶到下型”。“底到上型”的位图,它的行序是从下到上排列的,也就是逆行序。“顶到下型”位图行序是从上到下排列的。

位图颜色表

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

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

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

声明:

本文于网络整理,版权归原作者所有,如来源信息有误或侵犯权益,请联系我们删除或授权事宜。

C语言结构体描述BMP的文件格式相关推荐

  1. 顺序表的c语言结构体描述,顺序表的基本方法实现C语言版

    顺序表--------------线性表的第一个儿子 这个儿子的结构体定义: typedef int ElemType;//取别名 typedef struct link{ ElemType * he ...

  2. 关于c语言结构体偏移的一点思考

    注:此处只是利用了编译器的特性来计算结构体偏移 这句话就一笔带过,说得有点牵强附会.以后有时间自己再详细了解一下编译器的特性... more exceptional c++ 中文版 26页 https ...

  3. c++ new一个结构体_C语言结构体,又一个纸老虎,纯干货讲解(附代码)

    来源:网络,排版整理:晓宇 微信公众号:芯片之家(ID:chiphome-dy)结构体的定义结构体(struct)是由一系列具有相同类型或不同类型的数据构成的数据集合,也叫结构.结构体和其他类型基础数 ...

  4. C语言-结构体-计算两点距离(Problem 3591)

    C语言-结构体-计算两点距离 题目描述 大家高中肯定都计算过空间几何中点与点之间的距离,现在要求编写程序计算出两个点之间的距离.给出代码 如下,提交时只需提交你编写的代码 #include <s ...

  5. C语言结构体详解(结构体定义,使用,结构体大小等)

    c语言结构体详解 1.c语言结构体 1.1 结构体基础知识 1.2 结构体声明 1.3 结构体特殊声明 1.4 结构体的自引用 1.5 结构体的大小的计算 1.5.1了解结构体大小计算规则 1.5.2 ...

  6. linux中c语言结构体详解,Linux C语言结构体-学习笔记

    Linux C语言结构体简介 前面学习了c语言的基本语法特性,本节进行更深入的学习. 预处理程序. 编译指令: 预处理, 宏定义, 建立自己的数据类型:结构体,联合体,动态数据结构 c语言表达式工具 ...

  7. python展开 c函数中的宏预处理_Linux C语言结构体-学习笔记

    Linux C语言结构体简介 前面学习了c语言的基本语法特性,本节进行更深入的学习. 预处理程序. 编译指令: 预处理, 宏定义, 建立自己的数据类型:结构体,联合体,动态数据结构 c语言表达式工具 ...

  8. 阵列c语言,C语言结构体阵列的定义

    C语言结构体阵列的定义以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! C语言结构体阵列的定义 1.C语言结构体阵列的定义 ...

  9. 深度剖析C语言结构体

    深度剖析C语言结构体 1.什么是结构 2.结构体的声明 3.结构体变量的定义 4.结构成员变量的访问: 5.结构体变量的初始化: 6.嵌套的结构体: 7.结构体数组: 8.typedef 9.结构的自 ...

最新文章

  1. 计算机视觉测试数据集 dataset
  2. php文件包含绕过,文件包含漏洞(绕过姿势) | nmask's Blog
  3. C语言struct关键字详解—结构体
  4. 分析一周后终于明白,为什么说不注重数据的企业会被时代淘汰?
  5. php生成excel到服务器,yii phpexcel自动生成文件保存到服务器上
  6. iPhone 13贴膜渲染图曝光:近几代外观最大升级
  7. python常胜将军问题_Python中最常见的10个问题(列表)
  8. Linux 命令(104)—— crontab 命令
  9. ROM存储1/4周期正弦信号构造DDS
  10. Java第十一章总结
  11. 新型的Hbb项目目录结构
  12. 面试官:说说如何打破或违反双亲委派!
  13. 渗透测试之---xss-labs闯关【1-14关】
  14. Redis - 消息发布订阅机制
  15. Javaweb核心响应对象
  16. python语句--条件语句
  17. 一个很简单的基于栈式过程虚拟机的实现,它运行目标平台【x86】的原生代码。
  18. 基于weka的数据挖掘开发技术分析研究
  19. 工程伦理--3.2 解决伦理困境的基本理论及方法
  20. 使用mysql的mycli插件

热门文章

  1. lucene 增加相关性_事务性Lucene
  2. Java命令行界面(第20部分):JSAP
  3. java更好的语言_Java,如果这是一个更好的世界
  4. 提升您的Hibernate引擎
  5. resteasy_Tomcat 7上具有RESTeasy JAX-RS的RESTful Web服务– Eclipse和Maven项目
  6. Spring项目中的Netflix Archaius属性
  7. 在Java中确定文件类型
  8. 重新设计Hamcrest
  9. Apache Cassandra和Java入门(第一部分)
  10. 关于Java泛型和擦除