利用C语言读取BMP文件

利用C语言读取BMP文件文章目录什么是 bmp 文件 1 文件头信息块 2 图像描述信息块 3 颜色表 4 图像数据区编写代码 C 文件 h 头文件存储算法什么是 bmp 文件 BMP 是 bitmap 的缩写形式 bitmap 顾名思义 就是位图也即 Windows 位图 它一般由 4 部分组成 文件头信息块 图像描述信息块 颜色表 在真彩色模式无颜色表 和图像数据区组成 在系统中以 BMP 为扩展名保存 打开 Windows 的画图程序 在保存图像时 可以

什么是bmp文件

1.文件头信息块

文件信息头 (14字节)存储着文件类型,文件大小等信息

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

2.图像描述信息块

图片信息头 (40字节)存储着图像的尺寸,颜色索引,位平面数等信息

 //图像信息头结构体 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; 

3.颜色表

调色板 (由颜色索引数决定)【可以没有此信息】

//24位图像素信息结构体,即调色板 typedef struct _PixelInfo { 
    unsigned char rgbBlue; //该颜色的蓝色分量 (值范围为0-255) unsigned char rgbGreen; //该颜色的绿色分量 (值范围为0-255) unsigned char rgbRed; //该颜色的红色分量 (值范围为0-255) unsigned char rgbReserved;// 保留,必须为0 } PixelInfo; 

4.图像数据区

位图数据 (由图像尺寸决定)每一个像素的信息在这里存储

颜色表接下来位为位图文件的图像数据区,在此部分记录着每点像素对应的颜色号,其记录方式也随颜色模式而定,既2色图像每点占1位(8位为1字节);16色图像每点占4位(半字节);256色图像每点占8位(1字节);真彩色图像每点占24位(3字节)。所以,整个数据区的大小也会随之变化。究其规律而言,可的出如下计算公式:图像数据信息大小=(图像宽度图像高度记录像素的位数)/8。

在这里插入图片描述
可以用这个文件中读到以下信息。

unsigned short bfType = 0x4D42 = 19778 unsigned int bfSize = 0x41EA2 = 字节=/1024=263kb unsigned short bfReserved1 = 00 00 unsigned short bfReserved2 = 00 00 unsigned int bfOffBits = 0X00000036 = 0x36 = 54字节 unsigned int biSize = 0x00000028 = 0x28 = 40字节 int biWidth = 0x0001f6 = 0x1f6 = 502像素; int biHeight = 0x000000B3 = 0xB3 = 179像素 ; unsigned short biPlanes = 0x0001 0x1 = 1; unsigned short biBitCount = 0x0018 = 0x18 = 24; unsigned int biCompression = 0x00000000 = 0; unsigned int biSizeImage = 0x00000000 = 0; int biXPelsPerMeter = 0x00001273 = 0x1273 = 4723; int biYPelsPerMeter = 0x00001273 = 0x1273 = 4723; unsigned int biClrUsed = 0x00000000 = 0; unsigned int biClrImportant = 0x00000000 = 0; unsigned char rgbBlue = 0x 其中R:0X64 G:0X68 B:0X49 ; //该颜色的蓝色分量 (值范围为0-255) unsigned char rgbGreen = 0x4A6965 其中R:0X65 G:0X69 B:0X4A ; //该颜色的绿色分量 (值范围为0-255) unsigned char rgbRed = 0x 其中R:0X63 G:0X66 B:0X49 ; //该颜色的红色分量 (值范围为0-255) unsigned char rgbReserved; // 保留,必须为0 

编写代码

接下就是要用C语言来读取bmp文件,来具体看一下我们从二进制文本中读到的信息是否和调试的一样。

  • 这里你应该了解过C语言的结构体和文件指针。否则这么简单地代码,你可能也看不懂。
    下面的两段代码你可以直接复制到你的工程,注意这是C环境,不是c++环境。

C文件

# ifndef BMP_H # define BMP_H /* BMP格式 这种格式内的数据分为三到四个部分,依次是: 文件信息头 (14字节)存储着文件类型,文件大小等信息 图片信息头 (40字节)存储着图像的尺寸,颜色索引,位平面数等信息 调色板 (由颜色索引数决定)【可以没有此信息】 位图数据 (由图像尺寸决定)每一个像素的信息在这里存储 一般的bmp图像都是24位,也就是真彩。每8位为一字节,24位也就是使用三字节来存储每一个像素的信息,三个字节对应存放r,g,b三原色的数据, 每个字节的存贮范围都是0-255。那么以此类推,32位图即每像素存储r,g,b,a(Alpha通道,存储透明度)四种数据。8位图就是只有灰度这一种信息, 还有二值图,它只有两种颜色,黑或者白。 */ // 文件信息头结构体 typedef struct tagBITMAPFILEHEADER { 
    //unsigned short bfType; // 19778,必须是BM字符串,对应的十六进制为0x4d42,十进制为19778,否则不是bmp格式文件 unsigned int bfSize; // 文件大小 以字节为单位(2-5字节) unsigned short bfReserved1; // 保留,必须设置为0 (6-7字节) unsigned short bfReserved2; // 保留,必须设置为0 (8-9字节) unsigned int bfOffBits; // 从文件头到像素数据的偏移 (10-13字节) } BITMAPFILEHEADER; //图像信息头结构体 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; //24位图像素信息结构体,即调色板 typedef struct _PixelInfo { 
    unsigned char rgbBlue; //该颜色的蓝色分量 (值范围为0-255) unsigned char rgbGreen; //该颜色的绿色分量 (值范围为0-255) unsigned char rgbRed; //该颜色的红色分量 (值范围为0-255) unsigned char rgbReserved;// 保留,必须为0 } PixelInfo; #endif 

h头文件

#include  
     #include  
     #include "BmpFormat.h" BITMAPFILEHEADER fileHeader; BITMAPINFOHEADER infoHeader; void showBmpHead(BITMAPFILEHEADER pBmpHead) { 
    //定义显示信息的函数,传入文件头结构体 printf("BMP文件大小:%dkb\n", fileHeader.bfSize/1024); printf("保留字必须为0:%d\n", fileHeader.bfReserved1); printf("保留字必须为0:%d\n", fileHeader.bfReserved2); printf("实际位图数据的偏移字节数: %d\n", fileHeader.bfOffBits); } void showBmpInfoHead(BITMAPINFOHEADER pBmpinfoHead) { 
   //定义显示信息的函数,传入的是信息头结构体 printf("位图信息头:\n" ); printf("信息头的大小:%d\n" ,infoHeader.biSize); printf("位图宽度:%d\n" ,infoHeader.biWidth); printf("位图高度:%d\n" ,infoHeader.biHeight); printf("图像的位面数(位面数是调色板的数量,默认为1个调色板):%d\n" ,infoHeader.biPlanes); printf("每个像素的位数:%d\n" ,infoHeader.biBitCount); printf("压缩方式:%d\n" ,infoHeader.biCompression); printf("图像的大小:%d\n" ,infoHeader.biSizeImage); printf("水平方向分辨率:%d\n" ,infoHeader.biXPelsPerMeter); printf("垂直方向分辨率:%d\n" ,infoHeader.biYPelsPerMeter); printf("使用的颜色数:%d\n" ,infoHeader.biClrUsed); printf("重要颜色数:%d\n" ,infoHeader.biClrImportant); } int main() { 
    FILE* fp; fp = fopen("1.bmp", "rb");//读取同目录下的image.bmp文件。 if(fp == NULL) { 
    printf("打开'image.bmp'失败!\n"); return -1; } //如果不先读取bifType,根据C语言结构体Sizeof运算规则——整体大于部分之和,从而导致读文件错位 unsigned short fileType; fread(&fileType,1,sizeof (unsigned short), fp); if (fileType = 0x4d42) { 
    printf("文件类型标识正确!" ); printf("\n文件标识符:%d\n", fileType); fread(&fileHeader, 1, sizeof(BITMAPFILEHEADER), fp); showBmpHead(fileHeader); fread(&infoHeader, 1, sizeof(BITMAPINFOHEADER), fp); showBmpInfoHead(infoHeader); fclose(fp); } } 

记住bmp文件的文件名是1.bmp,这是我的文件名。当然你可以随便设置。而且要把图片和你的代码文件放到同一文件夹。
接下来就进行代码调试。
我这里用的是vscode调试的代码的。其他的编译器也可以,如果你也想安装vscode请看:10分钟搭建VScode的C/C++开发环境
将代码编写完成后就可以按F5,进行调试。
在这里插入图片描述
可以看到这些信息都是正确的,说明我们的程序是没有错误的,至此我们的通过C语言来实现bmp文件的读取就完成了,接下来我们就要实现bmp文件的读取和保存,具体看我的其他文章。










存储算法

BMP 文件通常是不压缩的,所以它们通常比同一幅图像的压缩图像文件格式要大很多。例如,一个 800×600 的 24位几乎占据 1.4MB 空间。因此它们通常不适合在因特网或者其它低速或者有容量限制的媒介上进行传输。 根据颜色深度的不同,图像上的一个像素可以用一个或者多个字节表示,它由 n/8 所确定(n 是位深度,1 字节包含 8 个数据位)。图片浏览器等基于字节的 ASCII 值计算像素的颜色,然后从调色板中读出相应的值。更为详细的信息请参阅下面关于位图文件的部分。 N 位 2n 种颜色的位图近似字节数可以用下面的公式计算: BMP 文件大小约等于 54+42 的 n 次方+(wh*n)/8,其中高度和宽度都是像素数。 需要注意的是上面公式中的 54 是位图文件的文件头,是彩色调色板的大小。另外需要注意的是这是一个近似值,对于 n 位的位图图像来说,尽管可能有最多 2n 中颜色,一个特定的图像可能并不会使用这些所有的颜色。由于彩色调色板仅仅定义了图像所用的颜色,所以实际的彩色调色板将小于。 如果想知道这些值是如何得到的,请参考下面文件格式的部分。 由于存储算法本身决定的因素,根据几个图像参数的不同计算出的大小与实际的文件大小将会有一些细小的差别。

利用C语言读取BMP文件

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/204776.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月19日 下午7:33
下一篇 2026年3月19日 下午7:34


相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号