如何读写BMP图像



由于BMP格式的图像简单,读写BMP图的实现也相对容易,所以在构建自己的图像处理库的时候,都是使用BMP作为测试图像。首先说一BMP图像相关的知识。


BMP图像的组成

BMP图像由4个部分组成:

  1. 文件头:BITMAPFILEHEADER(14字节)
  2. 信息头:BITMAPINFOHEADER(40字节)
  3. 颜色表:RGBQUAD(8位的为1024字节)(小于24位的图有,24位没有)
  4. 图像数据

文件头 BITMAPFILEHEADER

typedef struct tagBITMAPFILEHEADER 
{ 
WORD  bfType; //位图文件的类型,该值必需是0x4D42,也就是字符'BM'。 
DWORD bfSize; //位图文件大小:文件头+信息头+颜色表+数据部分
WORD  bfReserved1; //保留字,为0,留做扩展,对实际的解码格式没有影响。
WORD  bfReserved2; //同上 
DWORD bfOffBits; //位图文件头到图像数据的偏移量,以字节为单位
} BITMAPFILEHEADER;
这个结构的长度是固定的,为14个字节(WORD为无符号16位整数,DWORD为无符号32位整数)。该结果体作为文件存储的时候用。

结构体的定义参考Windows.h

信息头BITMAPINFOHEADER

这部分告诉应用程序图像的详细信息,在屏幕上显示图像将会使用这些信息,它从文件的第15个字节开始。
typedef struct tagBITMAPINFOHEADER 
{
DWORD biSize; //BITMAPINFOHEADER结构大小,字节为单位 
LONG biWidth; //宽度(以像素为单位,不是每行字节数!!)
LONG biHeight; //高度(以像素为单位)
WORD biPlanes; //目标设备的级别,必须为1 
WORD biBitCount; //颜色深度,每个像素所需要的位数
DWORD biCompression; //位图的压缩类型
DWORD biSizeImage; //位图数据部分的大小,以字节为单位(4字节对齐)
LONG biXPelsPerMeter; //位图水平分辨率,每米像素数
LONG biYPelsPerMeter; //位图垂直分辨率,每米像素数
DWORD biClrUsed; //位图实际使用的颜色表中的颜色数
DWORD biClrImportant; //位图显示过程中重要的颜色数
} BITMAPINFOHEADER;

该结构体大小为40字节。

颜色表RGBQUAD

BMP只能存储单色(1位),16色(4位),256色(8位),和真彩色(24位)4种格式的数据,只有真彩色没有调色板(颜色表)。

8位的BMP中,每个像素的数值就是颜色表数组的下标。而24位的BMP图,每个像素的数值就是表示实际的像素值。

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

图像数据

在8位BMP中,每个像素8位,存放的是颜色表的索引,24位每个像素24位,存放的是实际颜色的值,分为三个通道BGR。

要注意两点:

(1) 每一行的字节数必须是4的整倍数,如果不是,则需要补齐。也就是4字节对齐。
(2) bmp文件的数据从下到上,从左到右的。也就是说,从文件中最先读到的是图象最下面一行的左边第一个像素,然后是左边第二个像素……接下来是倒数第二行左边第一个像素,左边第二个像素……依次类推 ,最后得到的是最上面一行的最右一个像素。


具体实现

Github:https://github.com/qianqing13579/QQImageProcess
其中的Bmp.h和Bmp.cpp包含了读写BMP图像的具体实现
可以先执行ImageProcessTest类中的TestReadAndWrite()测试用例,看一下使用方法

2017-1-10 18:35:33


非常感谢您的阅读,如果您觉得这篇文章对您有帮助,欢迎扫码进行赞赏。
这里写图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章