BMP是英文Bitmap(位图)的简写,它是Windows操作系统中的标准图像文件格式,能够被多种Windows应用程序所支持。随着Windows操作系统的流行与丰富的Windows应用程序的开发,BMP位图格式理所当然地被广泛应用。这种格式的特点是包含的图像信息较丰富,几乎不进行压缩,但由此导致了它与生俱来的缺点–占用磁盘空间过大。所以,目前BMP在单机上比较流行。
-- 摘自百度百科
- 单色图像,图像中每一个像素只需要一个 bit 存储,其值为0或1,0代表黑,1代表白。
- 灰度图像,一般有256级灰度,每个像素 8 bit。
- 伪彩色图像,每个像素由一个字节组成,有 256 种颜色,对应关系一般通过图像颜色表来映射。
- 24位真彩色图像,每个像素由3个字节表示,发表表示红,绿,蓝3个分量,取值为0~255.
位图文件可看成由4个部分组成:
- 位图文件头(bitmap-file header)
// 位图文件头结构
typedef struct tagBITMAPFILEHEADER {
WORD bfType; // 位图文件类型,是0x4D42
DWORD bfSize; // 文件占用几字节
WORD bfReserved1; // 保留字, 必须是0
WORD bfReserved2; // 0
DWORD bfOffBits; // 位图数据起始位置,相对位图文件头偏移量
} BITMAPFILEHEADER;
- 位图信息头(bitmap-information header)
// 位图信息头结构
typedef struct tagBITMAPINFOHEADER {
DWORD biSize; // 本结构占用字节数
LONG biWidth; // 位图宽度
LONG biHeight; // 位图高度
WORD biPlanes; // 目标设备级别, 一定是1
WORD biBitCount; // 单个像素需要位数,1-双色,4-16色,8-256色,24-真彩色
DWORD biCompression; // 压缩类型 0-不压缩 1-BI_RLE8, 2-BI_RLE4
DWORD biSizeImage; // 位图大小,字节
LONG biXPelsPerMeter; // 水平分辨率,每米像素数
LONG biYPelsPerMeter; // 垂直分辨率
DWORD biClrUsed; // 位图实际使用颜色表中的颜色数
DWORD biClrImportant; // 说明对图象显示有重要影响的颜色索引的数目,如果是0,表示都重要。
} BITMAPINFOHEADER;
- 彩色表(color table)
// 位图颜色表项
typedef struct tagRGBQUAD {
BYTE rgbBlue; // 蓝色亮度 0~255
BYTE rgbGreen;
BYTE rgbRed;
BYTE rgbReserved; // 固定为0
} RGBQUAD;
- 定义位图的字节(位图数据,即图像数据,Data Bits)阵列
// 位图颜色表项
typedef struct tagRGBQUAD {
BYTE rgbBlue; // 蓝色亮度 0~255
BYTE rgbGreen;
BYTE rgbRed;
BYTE rgbReserved; // 固定为0
} RGBQUAD;
接下来定义整体结构
class CDib {
public:
CDib();
~CDib();
bool Load( const char * filename); // 打开 BMP 文件
bool Save( const char * filename); // 保存 BMP 文件
bool Create( int nWidth, int nHeight, int nColor); // 建立默认 BMP 结构
void Circle(); // 画圆
private:
void SetPixelColor(int i, int j); // 画圆时设置像素点颜色
int GetNumOfColors(); // 获取颜色表表项数目
void SetColor(RGBQUAD *rgb, BYTE r, BYTE g, BYTE b); // 设置一个颜色表表项
BITMAPFILEHEADER m_BitMapFileHeader;
BITMAPINFOHEADER *m_pBitMapInfoHeader;
RGBQUAD *m_pRgbQuad; // 指向颜色表
BYTE *m_pData; // 像素阵列
BYTE *pDib;
};
Load 函数从文件中读取结构
bool CDib::Load(const char *filename) {
::std::ifstream ifs(filename, ::std::ios::binary);
ifs.seekg(0, ::std::ios