☰
【数字图像处理】数字图像处理:关于BMP格式图像的理解和读写(c++)
2026/10/23 1:38:46 网站建设 项目流程

一、什么是BMP格式? 它与我们常见的其他图片格式(jpeg, jpg, png, tif)有什么区别?

1、JPEG

JPEG是Joint Photographic Experts Group(联合图像专家小组)的缩写,是第一个国际图像压缩标准。JPEG图像压缩算法能够在提供良好的压缩性能的同时,具有比较好的重建质量,被广泛应用于图像、视频处理领域。人们日常碰到的“.jpeg”、‘’.jpg“等指代的是图像数据经压缩编码后在媒体上的封存形式,不能与JPEG压缩标准混为一谈。

2、BMP

BMP,(全称Bitmap)是Windows操作系统中的标准图像文件格式,可以分成两类:设备相关位图(DDB)和设备无关位图(DIB),使用非常广。它采用位映射存储格式,除了图像深度可选以外,不采用其他任何压缩,因此,BMP 文件所占用的空间很大。BMP文件的图像深度可选1bit、4bit、8bit及24bit。BMP 文件存储数据时,图像的扫描方式是按从左到右、从下到上的顺序。由于BMP文件格式是Windows环境中交换与图有关的数据的一种标准,因此在Windows环境中运行的图形图像软件都支持BMP图像格式。

3、TIF

TIF,正确的是TIFF,标签图像文件格式(Tagged Image File Format,简写为TIFF)是一种灵活的位图格式,主要用来存储包括照片和艺术图在内的图像。它最初由Aldus公司与微软公司一起为PostScript打印开发。TIFF与JPEG和PNG一起成为流行的高位彩色图像格式。TIFF格式在业界得到了广泛的支持,如Adobe公司的Photoshop、The GIMP Team的GIMP、Ulead PhotoImpact 和Paint Shop Pro等图像处理应用、QuarkXPress 和Adobe InDesign 这样的桌面印刷和页面排版应用,扫描、传真、文字处理、光学字符识别和其它一些应用等都支持这种格式。

4、PNG

PNG,图像文件存储格式,其设计目的是试图替代GIF和TIFF文件格式,同时增加一些GIF文件格式所不具备的特性。PNG的名称来源于“可移植网络图形格式(Portable Network Graphic Format,PNG)”,也有一个非官方解释“PNG’s Not GIF”,是一种位图文件(bitmap file)存储格式,读作“ping”。PNG用来存储灰度图像时,灰度图像的深度可多到16位,存储彩色图像时,彩色图像的深度可多到48位,并且还可存储多到16位的α通道数据。PNG使用从LZ77派生的无损数据压缩算法,一般应用于JAVA程序、网页或S60程序中,原因是它压缩比高,生成文件体积小。

二、怎么计算BMP的大小

BMP是一种不压缩的图像文件,我们怎么计算bmp图像的大小呢?

BMP的类别及存储方式

1.BMP的常见类型

通常我们最常见的就是24位图,所谓的24位图,就是说一个像素的颜色信息用24位来表示,也就是说,对于三原色BRG,每一个颜色都用以字节(8)位来表示。除了24位图,还有1位(单色),2位(4色,CGA),4位(16色,VGA),8位(256色),16位(增强色),24位(真彩色)和32位等。

2. BMP的文件头:

BMP文件头(bmp file header):共14字节

0-1:bfType,表示文件类型,BMP格式的文件这两个字节是0x4D42,10进制就是19778,字符显示就是‘BM’;
2-5:bfSize,表示文件的大小,检查文件信息,验证正确;
6-7:bfReserved1,保留位,必须设置为0;
8-9:bfReserved2,保留位,必须设置为0;
a-d:bfOffBits,4字节的偏移,表示从文件头到位图数据的偏移;

位图信息头(bitmap information):共40字节;

0e-11:4字节的biSize, 信息头的大小,即40;
12-15:4字节的biWidth,用像素表示图像的宽度,查看文件信息验证正确;
16-19:4字节的biHeight,以像素为单位说明图像的高度,同时如果为正,说明位图倒立(即数据表示从图像的左下角到右上角),如果为负说明正向;(这两个信息在程序要在内存分配的时候使用)
1a-1b:2字节的biPlanes,为目标设备说明颜色平面数,总被设置为1;
1c-1d:2字节的biBitCount,说明比特数/像素数,值有1、2、4、8、16、24、32;
1e-21:4字节的biCompression,说明图像的压缩类型,最常用的就是0(BI_RGB),表示不压缩;
22-25:4字节的biSizeImage,说明位图数据的大小,当用BI_RGB格式时,可以设置为0;
26-29:4字节的biXPelsPerMeter,表示水平分辨率,单位是像素/米,有符号整数;
2a-2d:4字节的biYPelsPerMeter,表示垂直分辨率,单位是像素/米,有符号整数;
2e-31:4字节的biClrUsed,说明位图使用的调色板中的颜色索引数,为0说明使用所有;
32-35:4字节的biClrImportant,说明对图像显示有重要影响的颜色索引数,为0说明都重要;

所以,总的BMP格式从头到尾的顺序应该是:
a. bmp文件头(bmp file header):共14字节;
b. 位图信息头(bitmap information):共40字节;
c. 调色板(color palette):可选;
d. 位图数据;

计算大小

假设我们获取的是每个像素是24位的bmp图像,即每个像素占用三个字节(按照R、G、B的顺序,每个分量占一个字节),此外,这种格式还需要54个额外的字节来存储“头”信息,可以根据以下公式确定BMP文件大小:

Hbytes=(Hpixels*3+3) & (11.......00) 24b RGB BMP文件大小= 54 + Hbytes*Vpixels

其中Vpixels和Hpixels是图像的高度和宽度,(这里V是指vertical,H是指horizon,与一般width和high表示方式要区别开,如果是640×480的图片,就是对应Vpixels=480, Hpixels=640),则图片大小为

54+3×640×480=921654 bytes。

但是看公式,可以知道Hbytes必须舍入为下一个可以被4整除的整数,以确保BMP图像大小是4的倍数。

为什么要确保BMP图像大小是4的倍数?

1.首先普及一个概念,什么是32位系统、64位系统?

32位和64位操作系统是指:CPU一次处理数据的能力是32位还是64位。现在市场上的CPU一般都是64位的,但是这些CPU并不是真正意义上的64 位CPU,里面依然保留了大部分32位的技术,只是进行了部分64位的改进。32位和64位的区别还涉及了内存的寻址方面,32位系统的最大寻址空间是2 的32次方= 4294967296(bit)= 4(GB)左右,而64位系统的最大寻址空间的寻址空间则达到了2的64次方= 4294967296(bit)的32次方=数值大于1亿GB。换而言之,就是说32位系统的处理器最大只支持到4G内存,而64位系统最大支持的内存高达亿位数。

2.网上最多的解释

位图数据记录了位图的每一个像素值,记录顺序是在扫描行内是左到右,扫描行之间是从下到上。位图的一个像素值所占的字节数:
当biBitCount(每个像素所需的位数)=1时,8个像素占1个字节;
当biBitCount=4时,2个像素占1个字节;
当biBitCount=8时,1个像素占1个字节;
当biBitCount=24时,1个像素占3个字节;
Windows规定一个扫描行所占的字节数必须是4的倍数(即以long为单位),不足的以0填充。

3.举个例子

如果是24位1024×1024的BMP文件需要的存储空间为:

54+1024*1024*3 = 3145782字节

如果是24位321×1024的BMP文件需要的存储空间为:

54+(321*3+1)*127 = 122482字节

相当于需要每行要浪费一个字节,总共需要浪费127个字节。

三、怎么读取bmp格式的图片

#include"ImageStuff.h"unsignedchar**ReadBMP(char*filename){inti;FILE*f=fopen(filename,"rb");if(f==NULL){printf("\n\n%s NOT FOUND\n\n",filename);exit(1);}unsignedcharHeaderInfo[54];fread(HeaderInfo,sizeof(unsignedchar),54,f);// read the 54-byte header// extract image height and width from headerintwidth=*(int*)&HeaderInfo[18];intheight=*(int*)&HeaderInfo[22];//copy header for re-usefor(i=0;i<54;i++){ip.HeaderInfo[i]=HeaderInfo[i];}ip.Vpixels=height;ip.Hpixels=width;intRowBytes=(width*3+3)&(~3);//Be careful with this!ip.Hbytes=RowBytes;printf("\n Input BMP File name: %20s (%u x %u)",filename,ip.Hpixels,ip.Vpixels);unsignedchartmp;unsignedchar**TheImage=(unsignedchar**)malloc(height*sizeof(unsignedchar*));for(i=0;i<height;i++){TheImage[i]=(unsignedchar*)malloc(RowBytes*sizeof(unsignedchar));}for(i=0;i<height;i++){fread(TheImage[i],sizeof(unsignedchar),RowBytes,f);}fclose(f);returnTheImage;// remember to free() it in caller!}

四、怎么写入bmp格式的图片

voidWriteBMP(unsignedchar**img,char*filename){FILE*f=fopen(filename,"wb");if(f==NULL){printf("\n\nFILE CREATION ERROR: %s\n\n",filename);exit(1);}unsignedlongintx,y;chartemp;//write headerfor(x=0;x<54;x++){fputc(ip.HeaderInfo[x],f);}//write datafor(x=0;x<ip.Vpixels;x++){for(y=0;y<ip.Hbytes;y++){temp=img[x][y];fputc(temp,f);}}printf("\n Output BMP File name: %20s (%u x %u)",filename,ip.Hpixels,ip.Vpixels);fclose(f);}

对应的头文件 ImageStuff.h:

#include<stdlib.h>#include<stdio.h>#include<time.h>structImgProp{intHpixels;intVpixels;unsignedcharHeaderInfo[54];unsignedlongintHbytes;};structPixel{unsignedcharR;unsignedcharG;unsignedcharB;};unsignedchar**ReadBMP(char*);voidWriteBMP(unsignedchar**,char*);externstructImgPropip;

参考地址:
https://blog.csdn.net/u012877472/article/details/50272771

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询