C++語言基礎 例程 案例:bmp檔案格式剖析
阿新 • • 發佈:2019-01-24
用程式讀出BMP檔案資訊
//readbmp.h #ifndef READBMP_H_INCLUDED #define READBMP_H_INCLUDED typedef unsigned char BYTE; typedef unsigned short int UINT; typedef short int WORD; typedef int DWORD; typedef long LONG; typedef struct tagBITMAPFILEHEADER { UINT bfType; /*說明檔案的型別*/ DWORD bfSize; /*說明檔案的大小*/ UINT bfReserved1; /*保留,設定為0 */ UINT bfReserved2; /*保留,設定為0*/ DWORD bfOffBits; /*到影象資料的偏移量*/ } BITMAPFILEHEADER; typedef struct tagBITMAPINFOHEADER { DWORD biSize; /*BITMAPINFOHEADER結構所需要的位元組數*/ LONG biWidth; /*影象的寬度,以畫素為單位*/ LONG biHeight; /*影象的高度,以畫素為單位*/ WORD biPlanes; /*為目標裝置說明位面數,其值設定為1*/ WORD biBitCount; /*位數/畫素*/ DWORD biCompression; /*影象資料壓縮的型別:不壓縮,或4/8位RLE */ DWORD biSizeImage; /*影象的大小,以位元組為單位。*/ LONG biXPelsPerMeter; /*水平解析度,用畫素/米表示*/ LONG biYPelsPerMeter; /*垂直解析度,用畫素/米表示*/ DWORD biClrUsed; /*點陣圖使用的彩色表中的顏色索引數:2/16/256/224*/ DWORD biClrImportant; /*對影象顯示有重要影響的顏色索引的數目,如果是0,表示都重要*/ } BITMAPINFOHEADER; typedef struct tagRGBQUAD /* rgbq */ { BYTE rgbBlue; /*指定藍色強度*/ BYTE rgbGreen; /*指定綠色強度*/ BYTE rgbRed; /*指定紅色強度*/ BYTE rgbReserved; /*保留,設定為0 */ } RGBQUAD; typedef struct tagBITMAPINFO { BITMAPINFOHEADER bmiHeader; // 點陣圖資訊頭 RGBQUAD bmiColors[16]; // 顏色表 } BITMAPINFO; //畫素資訊 typedef unsigned char IMAGEDATA; #endif // READBMP_H_INCLUDED
//main.cpp #include "readbmp.h" #include <cstdlib> #include <cmath> #include <iomanip> #include <iostream> #include <fstream> using namespace std; //變數定義 BITMAPFILEHEADER bmpHeader; //檔案頭 BITMAPINFOHEADER bmpInfoHeader; //檔案資訊頭 RGBQUAD *colorTable; //彩色表 IMAGEDATA *bmpData; int main() { char bmpFileName[80]="bmp16bit.bmp";//bmp檔名 ifstream bmpFile(bmpFileName, ios::in|ios::binary); if(!bmpFile) { cerr<<"open error!"<<endl; exit(1);//退出程式 } /* 讀出點陣圖頭 */ //由於“記憶體對齊問題(這部分為14位元組),無法一次性讀入所有資訊,此處逐個取出成員 bmpFile.read((char*)&bmpHeader.bfType, sizeof(bmpHeader.bfType)); bmpFile.read((char*)&bmpHeader.bfSize, sizeof(bmpHeader.bfSize)); bmpFile.read((char*)&bmpHeader.bfReserved1, sizeof(bmpHeader.bfReserved1)); bmpFile.read((char*)&bmpHeader.bfReserved1, sizeof(bmpHeader.bfReserved2)); bmpFile.read((char*)&bmpHeader.bfOffBits, sizeof(bmpHeader.bfOffBits)); /* 顯示點陣圖頭 */ if(0x4d42!=bmpHeader.bfType) //前兩個字元BM,其ASCII碼合成0x4d42,應該是固定的 { cerr<<"not a bmp file!"<<endl; exit(1); } cout<<"點陣圖檔案頭:"<<endl; cout<<"檔案型別: BM"<<endl; cout<<"檔案大小:"<<hex<<bmpHeader.bfSize<<endl; //hex:用16進位制輸出 cout<<"保留字_1:"<<bmpHeader.bfReserved1<<endl; cout<<"保留字_2:"<<bmpHeader.bfReserved2<<endl; cout<<"實際點陣圖資料的偏移位元組數:"<<hex<<bmpHeader.bfOffBits<<endl<<endl; /* 讀出點陣圖資訊 */ bmpFile.read((char*)&bmpInfoHeader, sizeof(bmpInfoHeader)); /* 顯示點陣圖資訊 */ cout<<"點陣圖資訊頭:"<<endl; cout<<"結構體的長度:"<<bmpInfoHeader.biSize<<endl; cout<<"點陣圖寬:"<<bmpInfoHeader.biWidth<<endl; cout<<"點陣圖高:"<<bmpInfoHeader.biHeight<<endl; cout<<"biPlanes平面數:"<<bmpInfoHeader.biPlanes<<endl; cout<<"biBitCount採用顏色位數:"<<bmpInfoHeader.biBitCount<<endl; cout<<"壓縮方式:"<<bmpInfoHeader.biCompression<<endl; cout<<"biSizeImage實際點陣圖資料佔用的位元組數:"<<bmpInfoHeader.biSizeImage<<endl; cout<<"X方向解析度:"<<bmpInfoHeader.biXPelsPerMeter<<endl; cout<<"Y方向解析度:"<<bmpInfoHeader.biYPelsPerMeter<<endl; cout<<"使用的顏色數:"<<bmpInfoHeader.biClrUsed<<endl; cout<<"重要顏色數:"<<bmpInfoHeader.biClrImportant<<endl<<endl; /*biClrUsed指定本圖象實際用到的顏色數,如果該值為零,則用到的顏色數為2^biBitCount*/ int colorNum = bmpInfoHeader.biClrUsed; if(0==colorNum) { colorNum = pow(2, bmpInfoHeader.biBitCount); } colorTable = new RGBQUAD[colorNum]; /* 讀取彩色表並顯示 */ cout<<"所用顏色(R:G:B)"<<endl; int i; for(i=0; i<colorNum; i++) { bmpFile.read((char*)&colorTable[i].rgbBlue, 1); bmpFile.read((char*)&colorTable[i].rgbGreen, 1); bmpFile.read((char*)&colorTable[i].rgbRed, 1); bmpFile.read((char*)&colorTable[i].rgbReserved, 1); cout<<dec<<"["<<i<<"]="<<hex<<int(colorTable[i].rgbRed); cout<<":"<<int(colorTable[i].rgbGreen); cout<<":"<<int(colorTable[i].rgbBlue)<<endl; } cout<<endl; /*讀取畫素資訊*/ bmpData = new unsigned char[bmpInfoHeader.biSizeImage]; bmpFile.read((char*)bmpData, bmpInfoHeader.biSizeImage); /顯示畫素資訊:下面的顯示只提取了資料。BMP中的畫素資訊是從右上到左上儲存,在顯示影象時還需要要做處理*/ /*牽涉到每畫素幾位-bmpInfoHeader.biBitCount-的問題,下面的程式碼,有點小繞*/ int w, h; cout<<"下面是畫素資訊:"<<endl; for(h=0; h<bmpInfoHeader.biHeight; ++h) { cout<<"["<<setw(2)<<h<<"]: "; for(w=0; w < bmpInfoHeader.biSizeImage / bmpInfoHeader.biHeight; ++w) { cout<<setw(2)<<int(*(bmpData+h*bmpInfoHeader.biHeight*bmpInfoHeader.biBitCount/8+w))<<" "; } cout<<endl; } /*本程式只讀出了點陣圖資訊,要顯示出來,需要呼叫輸出裝置的功能了,此處略過*/ delete[] bmpData; delete[] colorTable; return 0; }