一、什么是BMP格式?
BMP,(全称Bitmap)是Windows操作系统中的标准图像文件格式,可以分成两类:设备相关位图(DDB)和设备无关位图(DIB),使用非常广。它采用位映射存储格式,除了图像深度可选以外,不采用其他任何压缩,因此,BMP 文件所占用的空间很大。BMP文件的图像深度可选1bit、4bit、8bit及24bit。BMP 文件存储数据时,图像的扫描方式是按从左到右、从下到上的顺序。由于BMP文件格式是Windows环境中交换与图有关的数据的一种标准,因此在Windows环境中运行的图形图像软件都支持BMP图像格式。二、怎么计算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"
unsigned char **ReadBMP(char *filename) {
int i;
FILE *f = fopen(filename, "rb");
if (f == NULL) {
printf("\n\n%s NOT FOUND\n\n", filename);
exit(1);
}
unsigned char HeaderInfo[54];
fread(HeaderInfo, sizeof(unsigned char), 54, f); // read the 54-byte header
// extract image height and width from header
int width = *(int *) &HeaderInfo[18];
int height = *(int *) &HeaderInfo[22];
//copy header for re-use
for (i = 0; i < 54; i++) { ip.HeaderInfo[i] = HeaderInfo[i]; } ip.Vpixels = height; ip.Hpixels = width; int RowBytes = (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); unsigned char tmp; unsigned char **TheImage = (unsigned char **) malloc(height * sizeof(unsigned char *)); for (i = 0; i < height; i++) { TheImage[i] = (unsigned char *) malloc(RowBytes * sizeof(unsigned char)); } for (i = 0; i < height; i++) { fread(TheImage[i], sizeof(unsigned char), RowBytes, f); } fclose(f); return TheImage; // remember to free() it in caller!
四、怎么写入bmp格式的图片
void WriteBMP(unsigned char **img, char *filename) {
FILE *f = fopen(filename, "wb");
if (f == NULL) {
printf("\n\nFILE CREATION ERROR: %s\n\n", filename);
exit(1);
}
unsigned long int x, y;
char temp;
//write header
for (x = 0; x < 54; x++) { fputc(ip.HeaderInfo[x], f); } //write data for (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
#include
#include
struct ImgProp {
int Hpixels;
int Vpixels;
unsigned char HeaderInfo[54];
unsigned long int Hbytes;
};
struct Pixel {
unsigned char R;
unsigned char G;
unsigned char B;
};
unsigned char **ReadBMP(char *);
void WriteBMP(unsigned char **, char *);
extern struct ImgProp ip;
备注:
点击下面链接,进入奥比中光开发者社区,了解更多3D视觉技术信息:
https://developer.orbbec.com.cn/
或扫描下方二维码,进入奥比中光开发者社区: