BMP文件处理
文章目录
BITMAP位图
在进行BITMAP图片进行处理的时候,首先要先对BITMAP的数据结构进行分析。
BITMAP位图的结构分为四个部分
文件头 BITMAPFILEHEADER
typedef struct tagBITMAPFILEHEADER{
WORD bfType; //文件类型,必须是“BM”
DWORD bfSize; //文件大小,包含文件头的大小
WORD bfReserved1; //保留字
WORD bfReserved2; //保留字
DWORD bfOffBits; //从文件头到实际位图数据的偏移字节数
} BITMAPFILEHEADER;
sizeof(BITMAPFILEHEADER) = 14
信息头 BITMAPINFOHEADER
typedef struct tagBITMAPINFOHEADER{
DWORD biSize; //该结构的长度,为40
LONG biWidth; //图像宽度
LONG biHeight; //图像高度
WORD biPlanes; //位平面数,必须为1
WORD biBitCount; //颜色位数,
DWORD biCompression; //是否压缩
DWORD biSizeImage; //实际位图数据占用的字节数
LONG biXPelsPerMeter;//目标设备水平分辨率
LONG biYPelsPerMeter;//目标设备垂直分辨率
DWORD biClrUsed;//实际使用的颜色数
DWORD biClrImportant;//图像中重要的颜色数
} BITMAPINFOHEADER;
sizeof(BITMAPINFOHEADER) = 40
在这当中,若biClrUsed为0,则说明用到的颜色为2的biBitCount次方(也就无需用到调色板了)
在这当中,biSizeImage为实际的字节数,其中,要求
b i S i z e I m a g e = ( ( b i W i d t h ∗ ( b i B i t C o u n t / 8 ) + 3 ) / 4 ∗ 4 ) ∗ b i H e i g h t biSizeImage = ((biWidth * (biBitCount / 8) + 3) / 4 * 4 ) * biHeight biSizeImage=((biWidth∗(biBitCount/8)+3)/4∗4)∗biHeight
也就是说,在位图当中的宽的字节数一定要是4的倍数,不是4的倍数将要对其中的字节进行补齐
举个例子,假如当前的图片是一个24位的宽度为13的图片,那么此时一行的存储模型应该是
13 ∗ ( B G R ) + 1 ∗ B Y T E 13 * (BGR) + 1 * BYTE 13∗(BGR)+1∗BYTE
也就是在末尾补了一个字节,从而达到了一行40字节(4的倍数)的目的。
调色板 RGBQUAD(内容可为空)
typedef struct tagRGBQUAD{
BYTE rgbBlue; //该颜色的蓝色分量
BYTE rgbGreen; //该颜色的绿色分量
BYTE rgbRed; //该颜色的红色分量
BYTE rgbReserved; //保留值
} RGBQUAD;
sizeof(RGBQUAD) = 4
调色板是BITMAP当中的可选项,只有需要的时候才会出现,而在有调色板的场合中,一共有biBitCount项 (RGBQUAD[biBitCount])
实际位图信息
在这里存放的是实际的位图的数据,其中数据量在BITMAPINFOHEADER有记录,在这里记录的一般是颜色的信息(比如RGB信息)又或者是有调色板的时候,记录调色板的索引值。
当然值得一提的是,这里的行的字节数一定是要4的倍数的
24位图像对R,G,B三个分量进行分离,产生3幅新的图像
在基本了解了BITMAP的内存结构之后,就可以根据其中的信息去读取图片,并分理出其中的RGB分量了。值得注意的在于,若图片的宽度不是4的倍数的时候,读取的时候要跳过行末尾的无意义的字节,否则读取出来的rgb值是错误的,而写入成新的图片的时候,同样的,要手动对行末尾进行补齐
具体实现
//用于存储RGB
typedef struct
{
BYTE b;
BYTE g;
BYTE r;
}RGB;
void bitmapTo3SignalColorBitmap()
{
BITMAPFILEHEADER fileHeader;
BITMAPINFOHEADER infoHeader;
FILE * pfin = fopen("bitmap/n4x.bmp", "rb");
FILE * pfoutR = fopen("bitmap/r.bmp", "wb");
FILE * pfoutG = fopen("bitmap/g.bmp", "wb")