BMP格式图像的显示
? 使用多文檔編程 也可以使用單文檔編程
建立一個DIB圖像的顯示類 ImageDib
成員變量:
4個指針:
LPBYTE m_lpDib;??????//指向DIB的指針
LPBITMAPINFOHEADER m_lpBmpInfoHead; ?//圖像信息頭指針
LPRGBQUAD m_lpColorTable; ????//圖像顏色表指針
unsigned char * m_pImgData; ????//圖像數據指針
4個普通變量(存放圖像的參數):
??? int m_imgWidth;???????//圖像的寬,像素為單位
? ? int m_imgHeight; ??????//圖像的高,像素為單位
int m_nBitCount;??????//每像素占的位數
? int m_nColorTableLength; ?????//顏色表長度(多少個表項)
1個句柄:
???? HPALETTE m_hPalette;?????//邏輯調色板句柄
成員函數:
帶參數構造函數 ImageDib(CSize size, int nBitCount, LPRGBQUAD lpColorTable,?unsigned char *pImgData);?????????? //帶參數的構造函數
View Code ImageDib::ImageDib(CSize size, int nBitCount, LPRGBQUAD lpColorTable,unsigned char *pImgData) {//如果沒有位圖數據傳入,我們認為是空的DIB,此時不分配DIB內存if(pImgData==NULL){m_lpDib=NULL;m_lpColorTable=NULL;m_pImgData=NULL; // 圖像數據m_lpBmpInfoHead=NULL; // 圖像信息頭m_hPalette = NULL;}else{//如果有位圖數據傳入//可以通過調用ReplaceDib()來實現 代碼一樣的//ReplaceDib(size,nBitCount,lpColorTable,pImgData);//圖像的寬、高、每像素位數等成員變量賦值m_imgWidth=size.cx;m_imgHeight=size.cy;m_nBitCount=nBitCount;//根據每像素位數,計算顏色表長度m_nColorTableLength=ComputeColorTabalLength(nBitCount);//每行像素所占字節數,必須擴展成4的倍數int lineByte=(m_imgWidth*nBitCount/8+3)/4*4;//位圖數據緩沖區的大小(圖像大小)int imgBufSize=m_imgHeight*lineByte;//為m_lpDib一次性分配內存,生成DIB結構m_lpDib=new BYTE [sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableLength+imgBufSize];//填寫BITMAPINFOHEADER結構m_lpBmpInfoHead = (LPBITMAPINFOHEADER) m_lpDib;m_lpBmpInfoHead->biSize = sizeof(BITMAPINFOHEADER);m_lpBmpInfoHead->biWidth = m_imgWidth;m_lpBmpInfoHead->biHeight = m_imgHeight;m_lpBmpInfoHead->biPlanes = 1;m_lpBmpInfoHead->biBitCount = m_nBitCount;m_lpBmpInfoHead->biCompression = BI_RGB;m_lpBmpInfoHead->biSizeImage = 0;m_lpBmpInfoHead->biXPelsPerMeter = 0;m_lpBmpInfoHead->biYPelsPerMeter = 0;m_lpBmpInfoHead->biClrUsed = m_nColorTableLength;m_lpBmpInfoHead->biClrImportant = m_nColorTableLength;//調色板句柄初始化為空,有顏色表時,MakePalette()函數要生成新的調色板m_hPalette = NULL;//如果有顏色表,則將顏色表拷貝進DIB的顏色表位置if(m_nColorTableLength!=0){//m_lpColorTable指向DIB顏色表的起始位置m_lpColorTable=(LPRGBQUAD)(m_lpDib+sizeof(BITMAPINFOHEADER));//顏色表拷貝memcpy(m_lpColorTable,lpColorTable,sizeof(RGBQUAD) * m_nColorTableLength);//創建邏輯調色板 MakePalette();}//m_pImgData指向DIB位圖數據起始位置m_pImgData = (LPBYTE)m_lpDib+sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD) * m_nColorTableLength;//拷貝圖像數據進DIB位圖數據區 memcpy(m_pImgData,pImgData,imgBufSize);}}?
讀文件: ? BOOL Read(LPCTSTR lpszPathName); ??//DIB讀函數
View Code BOOL ImageDib::Read(LPCTSTR lpszPathName) {//讀模式打開圖像文件 CFile file;if (!file.Open(lpszPathName, CFile::modeRead | CFile::shareDenyWrite))return FALSE;BITMAPFILEHEADER bmfh;//讀取BITMAPFILEHEADER結構到變量bmfh中int nCount=file.Read((LPVOID) &bmfh, sizeof(BITMAPFILEHEADER));//為m_lpDib分配空間,讀取DIB進內存if(m_lpDib!=NULL) delete []m_lpDib;m_lpDib=new BYTE[file.GetLength() -sizeof(BITMAPFILEHEADER)];file.Read(m_lpDib, file.GetLength() -sizeof(BITMAPFILEHEADER));//m_lpBmpInfoHead位置為m_lpDib起始位置m_lpBmpInfoHead = (LPBITMAPINFOHEADER)m_lpDib;//為成員變量賦值m_imgWidth=m_lpBmpInfoHead->biWidth;m_imgHeight=m_lpBmpInfoHead->biHeight;m_nBitCount=m_lpBmpInfoHead->biBitCount; //計算顏色表長度m_nColorTableLength= ComputeColorTabalLength(m_lpBmpInfoHead->biBitCount);//如果有顏色表,則創建邏輯調色板m_hPalette = NULL;if(m_nColorTableLength!=0){m_lpColorTable=(LPRGBQUAD)(m_lpDib+sizeof(BITMAPINFOHEADER));MakePalette();}//m_pImgData指向DIB的位圖數據起始位置m_pImgData = (LPBYTE)m_lpDib+sizeof(BITMAPINFOHEADER) +sizeof(RGBQUAD) * m_nColorTableLength;return TRUE; }?
??????寫文件: BOOL Write(LPCTSTR lpszPathName);?????? //DIB寫函數
?
計算顏色表長度:? int ComputeColorTabalLength(int nBitCount);?//計算顏色表的長度
?
創建邏輯調色板:? void MakePalette();??????//創建邏輯調色板
?
讀取圖像維數: CSize GetDimensions();?????//讀取圖像維數
?
圖像繪制: ??? BOOL Draw(CDC* pDC, CPoint origin, CSize size); //圖像繪制
?
用新的數據替代DIB:void ReplaceDib(CSize size, int nBitCount, LPRGBQUAD lpColorTable,?unsigned char *pImgData);????????????? ?//用新的數據替換DIB
?
清理空間函數: void Empty();???????????????????????? ?//清理空間
View Code void ImageDib::Empty() {//釋放DIB內存緩沖區if(m_lpDib != NULL) {delete [] m_lpDib;m_lpDib=NULL;m_lpColorTable=NULL;m_pImgData=NULL; m_lpBmpInfoHead=NULL;}//釋放邏輯調色板緩沖區if(m_hPalette != NULL){::DeleteObject(m_hPalette);m_hPalette = NULL;} }?
默認構造函數:
View Code ImageDib::ImageDib() {m_lpDib=NULL;//初始化m_lpDib為空。m_lpColorTable=NULL; //顏色表指針為空m_pImgData=NULL; //圖像數據指針為空m_lpBmpInfoHead=NULL; //圖像信息頭指針為空m_hPalette = NULL; //調色板為空 }默認析構函數:
View Code ImageDib::~ImageDib() {//釋放m_lpDib所指向的內存緩沖區if(m_lpDib != NULL) delete [] m_lpDib; //如果有調色板,釋放調色板緩沖區if(m_hPalette != NULL)::DeleteObject(m_hPalette); }? 編寫好ImageDib類后,在doc文件類中添加一個ImageDib類的指針,在構造函數中new出來,在析構函數中delete,然后重寫OnOpenDocument()函數 在其中調用讀函數打開圖像 在View類的OnDraw()中調用ImageDib類的繪制函數 將圖像繪制在打開的新文件中
總結:編程的關鍵在于幾個指針的賦值,指向DIB的指針的分配空間,位圖信息頭等結構的賦值等等。
只要記住:
BMP文件=位圖頭文件+位圖信息頭+顏色表+數據塊 (等號后邊的內容按順序寫的)
DIB=位圖信息頭+顏色表+數據塊
位圖信息=位圖信息頭+顏色表
這些圖像文件的存儲組成及順序,萬事OK!
???????
轉載于:https://www.cnblogs.com/Anidot/archive/2012/04/23/2466495.html
總結
以上是生活随笔為你收集整理的BMP格式图像的显示的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 老黄良心了!RTX 4070满血不阉割
- 下一篇: 储量高、成本低 美专家:钙离子电池取代锂