分辨率
DWORD biClrUsed; //实际使用的颜色数目,通常为0,表示全部使用
DWORD biClrImportant; //重要的颜色数量,通常为0,表示全部重要
} BITMAPINFOHEADER, *PBITMAPINFOHEADER;
biBitCount可以取下列值:
1 – 双色位图(缺省情况下是黑色和白色。你可以自己定义这两种颜色)
4 - 16 色位图
8 - 256 色位图
16 - 16bit 高彩色位图,(用16位表示三种颜色,有555,565两种方式)
24 - 24bit 真彩色位图
32 - 32bit 增强型真彩色位图
biCompression可以取下列值:
0 - 不压缩 (使用BI_RGB表示)
1 - RLE 8-使用8位RLE压缩方式(用BI_RLE8表示)
2 - RLE 4-使用4位RLE压缩方式(用BI_RLE4表示)
3 - Bitfields-位域存放方式(用BI_BITFIELDS表示)
第三块就是调色板或者掩码部分。如果是1、4、8则存放调色板;24与32位位图则存放RGB颜色的掩码,有3个,这些掩码用DWORD大小来存放。16位有存放调色版的也有存放掩码的。调色板的结构如下:
typedef struct tagRGBQUAD {
BYTE rgbBlue; //蓝色分量
BYTE rgbGreen; //绿色分量
BYTE rgbRed; //红色分量
BYTE rgbReserved; //保留值,通常为0
} RGBQUAD;
对于有调色板位图,调色板数量的计算公式是: (pow(2,bmpInfoH.biBitCount)) 。但是如果biClrUsed不是0,调色板数目就是biClrUsed。
typedef struct bi_bitField{
DWORD redCode;
DWORD greenCode
DWORD blueCode;
} bitField;
bitField即颜色掩码其实没有什么用处。
第四块就是位图的数据实体。对与有调色板的位图,表示颜色及亮度的位图数据实体存放的实际是本位置应有的颜色值在调色板数组中的位置,即索引值。位图像素区是按行存放的,每行从左到右与显示出来的图像对应;但是上下确是倒置的,即显示在上边的像素存放在后边。值得注意的一个
问题是每行存放的字节数是4的整数倍。那么图像每行颜色与亮度信息存放的字节数storewidth是大于等于biWidth* biBitCount/8的最小4的整数倍。如果计算有误读入或者写入的图像将会是错位的。现在给出一个通用的公式: 4*((biWidth*biBitCount+31)/32);
有了上面的知识,现在给出一c++中读入位图的函数:
为了方便给出符合c++中结构体特性的位图五种结构的定义;
typedef struct bi_bitField
{
DWORD redCode;
DWORD greenCode;
DWORD blueCode;
const struct bi_bitField & operator = (const struct bi_bitField & F)
{
if (&F != this)
{
redCode = F.redCode;
greenCode = F.greenCode;
blueCode = F.blueCode;
}
return *this;
}
friend std::istream & operator>>(std::istream & is,struct bi_bitField & F)
{
is >> F.redCode >> F.greenCode >> F.blueCode ;
return is;
}
friend std::ostream & operator<<(std::ostream & os,const struct bi_bitField & F)
{
os << F.redCode << F.greenCode << F.blueCode ;
return os;
}
}bitField;
//RGB颜色结构
typedef bitField ColorRGB;
//位图文件头
typedef struct tagBmpFile
{
WORD bfType;
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits;
const struct tagBmpFile & operator = (const struct tagBmpFile & F)
{
if (&F != this)
{
bfType = F.bfType;
bfSize = F.bfSize;
bfReserved1 = F.bfReserved1;
bfReserved2 = F.bfReserved2;
bfOffBits = F.bfOffBits;
}
return *this;
}
friend std::istream & operator>>(std::istream & is,struct tagBmpFile & F)
{
is >> F.bfType >> F.bfSize >> F.bfReserved1 >> F.bfReserved2 >> F.bfOffBits;
return is;
}
friend std::ostream & operator<<(std::ostream & os,const struc