BMP图像读取 您所在的位置:网站首页 centos65查看硬盘分区 BMP图像读取

BMP图像读取

2023-06-27 19:30| 来源: 网络整理| 查看: 265

0. BMP格式介绍

根据百度百科对BMP的定义,我们知道BMP是Bitmap(位图)的简称,是Windows操作系统中的标准图像文件格式。其特点是由于几乎不进行压缩,所以包含的图像信息较丰富,但同时也到之占用的磁盘空间较大。

1 文件格式

位图文件由4个部分组成:

位图头文件(bitmap-file header)位图信息头(bitmap-information header)颜色表(color table):使用索引来表示图像,此时颜色表就是索引与其对应的颜色之间的映射表(即通过索引值,结合颜色表,找到对应的像素信息)位图数据(data bits)

上述不同的部分,有不同的数据结构,下面分别介绍前面3个部分的数据结构。

数据段名称    对应的Windows结构体定义大小(Byte)bmp文件头   BITMAPFILEHEADER       14bmp信息头        BITMAPINFOHEADER        40颜色表由颜色索引数决定bmp数据由图像尺寸决定 2 位图头文件

 本文,以上图来分析BMP图像的文件格式。在分析图像数据之前,需要强调的是BMP文件中,数据的存储方式为小端方式(little endian),即假设一个数据需要多个字节来表示,那么数据的存放字节的顺序为“低地址存放地位数据,高地址存放高位数据”。在十六进制中,一个数字占4位,因此每个字节可以存储2个十六进制数字。

因此,对于数据0x1756在内存中的存储顺序为:

 位图头文件的结构体定义如下:

typedef struct tagBITMAPFILEHEADER  {   UINT16 bfType;    // 19778,必须是BM字符串,对应的十六进制为0x4d42,十进制为19778,否则不是bmp格式文件 DWORD bfSize; // 文件大小 以字节为单位(2-5字节) UINT16 bfReserved1; // 保留,必须设置为0 (6-7字节) UINT16 bfReserved2; // 保留,必须设置为0 (8-9字节) DWORD bfOffBits; // 从文件头到像素数据的偏移 (10-13字节) } BITMAPFILEHEADER;

 在VScode中,可以通过安装hexdump插件来以二进制的形式查看BMP图像数据。

 对照结构体和文件数据可以看到:

0-1 : 0x4d42='BM',表示这是Windows支持的位图格式

2-5 : 0x000088EA表示文件大小

6-9 : 保留段,为0

A-D : 0x00000436=1078,表示从文件头到位图数据需要偏移1078个字节

【注意】利用fopen打开文件,得到文件句柄读取相应的数据时,存在一个问题就是结构体内存对齐。这个会使得后续数据的读取出现错误。

何为内存对齐具体可以参考文章:结构体成员在内存中的对齐方式

上述问题的具体表现可以通过如下的代码进行实现:

#include typedef struct tagBITMAPFILEHEADER { unsigned short bfType; // 19778,必须是BM字符串,对应的十六进制为0x4d42,十进制为19778,否则不是bmp格式文件(0-4) int bfSize; // 文件大小 以字节为单位(2-5字节) (4-8) unsigned short bfReserved1; // 保留,必须设置为0 (6-7字节) (8-10) unsigned short bfReserved2; // 保留,必须设置为0 (8-9字节) (10-12) int bfOffBits; // 从文件头到像素数据的偏移 (10-13字节) (12-16) } BITMAPFILEHEADER; int main(int argc, char* argv[]) { printf("sizeof(BITMAPFILEHEADER) = %lu\n", sizeof(BITMAPFILEHEADER)); return 0; } // sizeof(BITMAPFILEHEADER) = 16

那么如何关闭结构体的内存对齐 ,有两种方式:添加预处理指令 #pragma pack(1) 或者 __attribute__ ((packed))。这两种方式的区别在于:

#pragma pack(1)预处理指令,是关闭整个文件的内存对齐模式__attribute__ ((packed))指令,则是针对指定的结构体 #include // #pragma pack(1) typedef struct tagBITMAPFILEHEADER { unsigned short bfType; // 19778,必须是BM字符串,对应的十六进制为0x4d42,十进制为19778,否则不是bmp格式文件(0-4) int bfSize; // 文件大小 以字节为单位(2-5字节) (4-8) unsigned short bfReserved1; // 保留,必须设置为0 (6-7字节) (8-10) unsigned short bfReserved2; // 保留,必须设置为0 (8-9字节) (10-12) int bfOffBits; // 从文件头到像素数据的偏移 (10-13字节) (12-16) }__attribute__ ((packed)) BITMAPFILEHEADER; int main(int argc, char* argv[]) { printf("sizeof(BITMAPFILEHEADER) = %lu\n", sizeof(BITMAPFILEHEADER)); return 0; } // sizeof(BITMAPFILEHEADER) = 14 3 位图信息头

位图信息头的结构体定义如下:

typedef struct tagBITMAPINFOHEADER { unsigned int biSize; // 此结构体的大小 (14-17字节) long biWidth; // 图像的宽 (18-21字节) long biHeight; // 图像的高 (22-25字节) unsigned short biPlanes; // 表示bmp图片的平面属,显然显示器只有一个平面,所以恒等于1 (26-27字节) unsigned short biBitCount; // 一像素所占的位数,一般为24 (28-29字节) unsigned int biCompression; // 说明图象数据压缩的类型,0为不压缩。 (30-33字节) unsigned int biSizeImage; // 像素数据所占大小, 这个值应该等于上面文件头结构中bfSize-bfOffBits (34-37字节) long biXPelsPerMeter; // 说明水平分辨率,用象素/米表示。一般为0 (38-41字节) long biYPelsPerMeter; // 说明垂直分辨率,用象素/米表示。一般为0 (42-45字节) unsigned int biClrUsed; // 说明位图实际使用的彩色表中的颜色索引数(设为0的话,则说明使用所有调色板项)。 (46-49字节) unsigned int biClrImportant; // 说明对图象显示有重要影响的颜色索引的数目,如果是0,表示都重要。(50-53字节) } BITMAPINFOHEADER;  4 颜色表

颜色表本质上是一个查询表,通过颜色序号来查询对应的颜色。在文件中的布局类似一个二维数组palette[N][4]. 其中4个元素分别表示对应的B,G,R和Alpha的值,每个分量占一个字节。N一般等于256。

一共有256种颜色,每个颜色占用4个字节,就是一共1024个字节,再加上前面的文件信息头和位图信息头的54个字节加起来一共是1078个字节。

5. 位图数据

位图数据中,每个像素占一个字节,以该字节的数作为颜色索引去颜色表查询相应的颜色,并将其显示出来即可。

6. 参考链接

C实现BMP转JPG 附源码_等jzy的博客-CSDN博客_c语言bmp转jpg

用c、cpp实现位图(BMP)读入写出的思路及细节 - et3_tsy - 博客园 (cnblogs.com)

C语言实现BMP图像的读写功能_C 语言_脚本之家 (jb51.net)

利用C语言读取BMP文件 - 知乎 (zhihu.com)

BMP文件格式详解(BMP file format) - 姚伟峰 - 博客园 (cnblogs.com)

结构体成员在内存中的对齐方式 – My Code



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有