BMP是位图BitMaP的缩写,是一种常见的图像文件格式。其通常由四个部分组成:
typedef struct tagBITMAPFILEHEADER { WORD bfType; DWORD bfSize; WORD bfReserved1; WORD bfReserved2; DWORD bfOffBits; } BITMAPFILEHEADER;
typedef struct tagBITMAPINFOHEADER { DWORD biSize; // the size of this header(40 bytes) LONG biWidth; // the bitmap width in pixels LONG biHeight; // the bitmap height in pixels WORD biPlanes; // the number of color planes.Must be 1 WORD biBitCount; // the number of bits per pixel DWORD biCompression; // the compression method being used DWORD biSizeImage; // the size of the raw bitmap data LONG biXPelsPerMeter; // the horizontal resolution. (pixel per meter, signed integer) LONG biYPelsPerMeter; // the vertical resolution. (pixel per meter, signed integer) DWORD biClrUsed; // the number of colors in the color palette DWORD biClrImportant; // the number of important colors used, generally ignored. }BITMAPINFOHEADER;一些比较重要的字段:
typedef struct tagRGBQUAD { BYTE rgbBlue; BYTE rgbGreen; BYTE rgbRed; BYTE rgbReserved; }RGBQUAD;最后一个字段为保留字段,一般不用。
存储位图的信息,若有调色板,则存储颜色的索引值,否则(24位真彩色)存储每个像素的颜色值(一次为B、G、R)。
1、定义相关结构和重载输入输出操作符,以方便以后的操作:
// image data typedef unsigned char* PixelArray; // stream operator overload, convinient for read and write ifstream& operator >> (ifstream&, BITMAPFILEHEADER&); ofstream& operator << (ofstream&, BITMAPFILEHEADER&); ifstream& operator >> (ifstream&, BITMAPINFOHEADER&); ofstream& operator << (ofstream&, BITMAPINFOHEADER&); ifstream& operator >> (ifstream&, RGBQUAD&); ofstream& operator << (ofstream&, RGBQUAD&);
void IOHandle::ReadBMP(BMPBasic& bmpFile) { // read file ifstream readHandle(bmpFile.fileName.c_str(), ios::in | ios::binary); if (!readHandle) { cerr << "error: can't open file " << bmpFile.fileName << endl; exit(EXIT_FAILURE); } readHandle >> bmpFile.fileHeader; readHandle >> bmpFile.infoHeader; if (bmpFile.infoHeader.biBitCount != 24) { // read color palette bmpFile.colorTableNum = static_cast<unsigned long>(pow(2.0, static_cast<double>(bmpFile.infoHeader.biBitCount))); bmpFile.colorPalette.resize(bmpFile.colorTableNum); for (unsigned long i = 0; i != bmpFile.colorTableNum; ++i) { readHandle >> bmpFile.colorPalette[i]; } } bmpFile.pixelArray = new unsigned char[bmpFile.infoHeader.biSizeImage]; readHandle.read(reinterpret_cast<char*> (bmpFile.pixelArray), (bmpFile.infoHeader.biSizeImage) * sizeof (unsigned char)); bmpFile.pixelNum = bmpFile.infoHeader.biWidth * bmpFile.infoHeader.biHeight; bmpFile.SetBytePerLine((bmpFile.infoHeader.biWidth * bmpFile.infoHeader.biBitCount / 8 + 3) / 4 * 4); }
void IOHandle::GenBMP(BMPBasic& bmpFile, const string& genFileName) const { // write bmp file ofstream writeHandle(genFileName.c_str(), ios::out | ios::binary); if (!writeHandle) { cerr << "error: can't open file " << genFileName << endl; exit(EXIT_FAILURE); } writeHandle << bmpFile.fileHeader; writeHandle << bmpFile.infoHeader; for (unsigned short i = 0; i != bmpFile.colorTableNum; ++i) { writeHandle << bmpFile.colorPalette[i]; } writeHandle.write(reinterpret_cast<char*> (bmpFile.pixelArray), bmpFile.fileHeader.bfSize * sizeof (unsigned char)); }
void BMPBasic::ShowInformation() { // output some infomation cout << "type(bfType): " << hex << fileHeader.bfType << dec << "\nfile size(bfSize): " << fileHeader.bfSize << endl; cout << "bitcount(biBitCount): " << infoHeader.biBitCount << " " << "\nwidth: " << infoHeader.biWidth << "\nheight: " << infoHeader.biHeight << "\nimage data size(biSizeImage): " << infoHeader.biSizeImage << endl; cout << "size per line: " << bytePerLine << endl; cout << "bfOffBits: " << fileHeader.bfOffBits << endl; }