?? dibapi.cpp
字號:
} else { // 象素的大小 DWORD dwBmBitsSize; // 大小為Width * Height dwBmBitsSize = WIDTHBYTES((lpBI->biWidth)*((DWORD)lpBI->biBitCount)) * lpBI->biHeight; // 計算出DIB真正的大小 dwDIBSize += dwBmBitsSize; // 更新biSizeImage(很多BMP文件頭中biSizeImage的值是錯誤的) lpBI->biSizeImage = dwBmBitsSize; } // 計算文件大?。篋IB大小+BITMAPFILEHEADER結構大小 bmfHdr.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER); // 兩個保留字 bmfHdr.bfReserved1 = 0; bmfHdr.bfReserved2 = 0; // 計算偏移量bfOffBits,它的大小為Bitmap文件頭大小+DIB頭大?。伾泶笮?/span> bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + lpBI->biSize + PaletteSize((LPSTR)lpBI); // 嘗試寫文件 TRY { // 寫文件頭 file.Write((LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER)); // 寫DIB頭和象素 file.WriteHuge(lpBI, dwDIBSize); } CATCH (CFileException, e) { // 解除鎖定 ::GlobalUnlock((HGLOBAL) hDib); // 拋出異常 THROW_LAST(); } END_CATCH // 解除鎖定 ::GlobalUnlock((HGLOBAL) hDib); // 返回TRUE return TRUE;}/************************************************************************* * * 函數名稱: * ReadDIBFile() * * 參數: * CFile& file - 要讀取得文件文件CFile * * 返回值: * HDIB - 成功返回DIB的句柄,否則返回NULL。 * * 說明: * 該函數將指定的文件中的DIB對象讀到指定的內存區域中。除BITMAPFILEHEADER * 外的內容都將被讀入內存。 * *************************************************************************/HDIB WINAPI ReadDIBFile(CFile& file){ BITMAPFILEHEADER bmfHeader; DWORD dwBitsSize; HDIB hDIB; LPSTR pDIB; // 獲取DIB(文件)長度(字節) dwBitsSize = file.GetLength(); // 嘗試讀取DIB文件頭 if (file.Read((LPSTR)&bmfHeader, sizeof(bmfHeader)) != sizeof(bmfHeader)) { // 大小不對,返回NULL。 return NULL; } // 判斷是否是DIB對象,檢查頭兩個字節是否是"BM" if (bmfHeader.bfType != DIB_HEADER_MARKER) { // 非DIB對象,返回NULL。 return NULL; } // 為DIB分配內存 hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwBitsSize); if (hDIB == 0) { // 內存分配失敗,返回NULL。 return NULL; } // 鎖定 pDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB); // 讀象素 if (file.ReadHuge(pDIB, dwBitsSize - sizeof(BITMAPFILEHEADER)) != dwBitsSize - sizeof(BITMAPFILEHEADER) ) { // 大小不對。 // 解除鎖定 ::GlobalUnlock((HGLOBAL) hDIB); // 釋放內存 ::GlobalFree((HGLOBAL) hDIB); // 返回NULL。 return NULL; } // 解除鎖定 ::GlobalUnlock((HGLOBAL) hDIB); // 返回DIB句柄 return hDIB;}/************************************************************************* * * 函數名稱: * DIBToPCX256() * * 參數: * LPSTR lpDIB - 指向DIB對象的指針 * CFile& file - 要保存的文件 * * 返回值: * BOOL - 成功返回True,否則返回False。 * * 說明: * 該函數將指定的256色DIB對象保存為256色PCX文件。 * *************************************************************************/BOOL WINAPI DIBToPCX256(LPSTR lpDIB, CFile& file){ // 循環變量 LONG i; LONG j; // DIB高度 WORD wHeight; // DIB寬度 WORD wWidth; // 中間變量 BYTE bChar1; BYTE bChar2; // 指向源圖像象素的指針 BYTE * lpSrc; // 指向編碼后圖像數據的指針 BYTE * lpDst; // 圖像每行的字節數 LONG lLineBytes; // 重復像素計數 int iCount; // 緩沖區已使用的字節數 DWORD dwBuffUsed; // 指向DIB象素指針 LPSTR lpDIBBits; // 獲取DIB高度 wHeight = (WORD) DIBHeight(lpDIB); // 獲取DIB寬度 wWidth = (WORD) DIBWidth(lpDIB); // 找到DIB圖像象素起始位置 lpDIBBits = FindDIBBits(lpDIB); // 計算圖像每行的字節數 lLineBytes = WIDTHBYTES(wWidth * 8); //************************************************************************* // PCX文件頭 PCXHEADER pcxHdr; // 給文件頭賦值 // PCX標識碼 pcxHdr.bManufacturer = 0x0A; // PCX版本號 pcxHdr.bVersion = 5; // PCX編碼方式(1表示RLE編碼) pcxHdr.bEncoding = 1; // 像素位數(256色為8位) pcxHdr.bBpp = 8; // 圖像相對于屏幕的左上角X坐標(以像素為單位) pcxHdr.wLeft = 0; // 圖像相對于屏幕的左上角Y坐標(以像素為單位) pcxHdr.wTop = 0; // 圖像相對于屏幕的右下角X坐標(以像素為單位) pcxHdr.wRight = wWidth - 1; // 圖像相對于屏幕的右下角Y坐標(以像素為單位) pcxHdr.wBottom = wHeight - 1; // 圖像的水平分辨率 pcxHdr.wXResolution = wWidth; // 圖像的垂直分辨率 pcxHdr.wYResolution = wHeight; // 調色板數據(對于256色PCX無意義,直接賦值為0) for (i = 0; i < 48; i ++) { pcxHdr.bPalette[i] = 0; } // 保留域,設定為0。 pcxHdr.bReserved = 0; // 圖像色彩平面數目(對于256色PCX設定為1)。 pcxHdr.bPlanes = 1; // 圖像的寬度(字節為單位),必須為偶數。// if ((wWidth & 1) == 0)// { pcxHdr.wLineBytes = wWidth;// }// else// {// pcxHdr.wLineBytes = wWidth + 1;// } // 圖像調色板的類型,1表示彩色或者單色圖像,2表示圖像是灰度圖。 pcxHdr.wPaletteType = 1; // 制作該圖像的屏幕寬度(像素為單位) pcxHdr.wSrcWidth = 0; // 制作該圖像的屏幕高度(像素為單位) pcxHdr.wSrcDepth = 0; // 保留域,取值設定為0。 for (i = 0; i < 54; i ++) { pcxHdr.bFiller[i] = 0; } // 寫入文件頭 file.Write((LPSTR)&pcxHdr, sizeof(PCXHEADER)); //******************************************************************************* // 開始編碼 // 開辟一片緩沖區(2被原始圖像大小)以保存編碼結果 lpDst = new BYTE[wHeight * wWidth * 2]; // 指明當前已經用了多少緩沖區(字節數) dwBuffUsed = 0; // 每行 for (i = 0; i < wHeight; i++) { // 指向DIB第i行,第0個象素的指針 lpSrc = (BYTE *)lpDIBBits + lLineBytes * (wHeight - 1 - i); // 給bChar1賦值 bChar1 = *lpSrc; // 設置iCount為1 iCount = 1; // 剩余列 for (j = 1; j < wWidth; j ++) { // 指向DIB第i行,第j個象素的指針 lpSrc++; // 讀取下一個像素 bChar2 = *lpSrc; // 判斷是否和bChar1相同并且iCount < 63 if ((bChar1 == bChar2) && (iCount < 63)) { // 相同,計數加1 iCount ++; // 繼續讀下一個 } else { // 不同,或者iCount = 63 // 寫入緩沖區 if ((iCount > 1) || (bChar1 >= 0xC0)) { // 保存碼長信息 lpDst[dwBuffUsed] = iCount | 0xC0; // 保存bChar1 lpDst[dwBuffUsed + 1] = bChar1; // 更新dwBuffUsed dwBuffUsed += 2; } else { // 直接保存該值 lpDst[dwBuffUsed] = bChar1; // 更新dwBuffUsed dwBuffUsed ++; } // 重新給bChar1賦值 bChar1 = bChar2; // 設置iCount為1 iCount = 1; } } // 保存每行最后一部分編碼 if ((iCount > 1) || (bChar1 >= 0xC0)) { // 保存碼長信息 lpDst[dwBuffUsed] = iCount | 0xC0; // 保存bChar1 lpDst[dwBuffUsed + 1] = bChar1; // 更新dwBuffUsed dwBuffUsed += 2; } else { // 直接保存該值 lpDst[dwBuffUsed] = bChar1; // 更新dwBuffUsed dwBuffUsed ++; } } // 寫入編碼結果 file.WriteHuge((LPSTR)lpDst, dwBuffUsed); // 釋放內存 delete lpDst; //************************************************************************** // 寫入調色板信息 // 指向BITMAPINFO結構的指針(Win3.0) LPBITMAPINFO lpbmi; // 指向BITMAPCOREINFO結構的指針 LPBITMAPCOREINFO lpbmc; // 表明是否是Win3.0 DIB的標記 BOOL bWinStyleDIB; // 開辟一片緩沖區以保存調色板 lpDst = new BYTE[769]; // 調色板起始字節 * lpDst = 0x0C; // 獲取指向BITMAPINFO結構的指針(Win3.0) lpbmi = (LPBITMAPINFO)lpDIB; // 獲取指向BITMAPCOREINFO結構的指針 lpbmc = (LPBITMAPCOREINFO)lpDIB; // 判斷是否是WIN3.0的DIB bWinStyleDIB = IS_WIN30_DIB(lpDIB); // 讀取當前DIB調色板 for (i = 0; i < 256; i ++) { if (bWinStyleDIB) { // 讀取DIB調色板紅色分量 lpDst[i * 3 + 1] = lpbmi->bmiColors[i].rgbRed; // 讀取DIB調色板綠色分量 lpDst[i * 3 + 2] = lpbmi->bmiColors[i].rgbGreen; // 讀取DIB調色板藍色分量 lpDst[i * 3 + 3] = lpbmi->bmiColors[i].rgbBlue; } else { // 讀取DIB調色板紅色分量 lpDst[i * 3 + 1] = lpbmc->bmciColors[i].rgbtRed; // 讀取DIB調色板綠色分量 lpDst[i * 3 + 2] = lpbmc->bmciColors[i].rgbtGreen; // 讀取DIB調色板藍色分量 lpDst[i * 3 + 3] = lpbmc->bmciColors[i].rgbtBlue; } } // 寫入調色板信息 file.Write((LPSTR)lpDst, 769); // 返回 return TRUE;}/************************************************************************* * * 函數名稱: * ReadPCX256() * * 參數: * CFile& file - 要讀取的文件 * * 返回值: * HDIB - 成功返回DIB的句柄,否則返回NULL。 * * 說明: * 該函數將讀取指定的256色PCX文件。將讀取的結果保存在一個未壓縮 * 編碼的DIB對象中。 * *************************************************************************/HDIB WINAPI ReadPCX256(CFile& file){ // PCX文件頭 PCXHEADER pcxHdr; // DIB大?。ㄗ止潝担?/span> DWORD dwDIBSize; // DIB句柄 HDIB hDIB; // DIB指針 LPSTR pDIB; // 循環變量 LONG i; LONG j; // 重復像素計數 int iCount; // DIB高度 WORD wHeight; // DIB寬度 WORD wWidth; // 圖像每行的字節數 LONG lLineBytes; // 中間變量 BYTE bChar; // 指向源圖像象素的指針 BYTE * lpSrc; // 指向編碼后圖像數據的指針 BYTE * lpDst; // 臨時指針 BYTE * lpTemp; // 嘗試讀取PCX文件頭 if (file.Read((LPSTR)&pcxHdr, sizeof(PCXHEADER)) != sizeof(PCXHEADER)) { // 大小不對,返回NULL。 return NULL; } // 判斷是否是256色PCX文件,檢查第一個字節是否是0x0A, if ((pcxHdr.bManufacturer != 0x0A) || (pcxHdr.bBpp != 8) || (pcxHdr.bPlanes != 1)) { // 非256色PCX文件,返回NULL。 return NULL; } // 獲取圖像高度 wHeight = pcxHdr.wBottom - pcxHdr.wTop + 1; // 獲取圖像寬度 wWidth = pcxHdr.wRight - pcxHdr.wLeft + 1; // 計算圖像每行的字節數 lLineBytes = WIDTHBYTES(wWidth * 8); // 計算DIB長度(字節) dwDIBSize = sizeof(BITMAPINFOHEADER) + 1024 + wHeight * lLineBytes; // 為DIB分配內存 hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwDIBSize); if (hDIB == 0) { // 內存分配失敗,返回NULL。 return NULL; } // 鎖定 pDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB); // 指向BITMAPINFOHEADER的指針 LPBITMAPINFOHEADER lpBI; // 賦值 lpBI = (LPBITMAPINFOHEADER) pDIB; // 給lpBI成員賦值 lpBI->biSize = 40; lpBI->biWidth = wWidth; lpBI->biHeight = wHeight; lpBI->biPlanes = 1; lpBI->biBitCount = 8; lpBI->biCompression = BI_RGB; lpBI->biSizeImage = wHeight * lLineBytes; lpBI->biXPelsPerMeter = pcxHdr.wXResolution; lpBI->biYPelsPerMeter = pcxHdr.wYResolution; lpBI->biClrUsed = 0; lpBI->biClrImportant = 0; // 分配內存以讀取編碼后的象素 lpSrc = new BYTE[file.GetLength() - sizeof(PCXHEADER) - 769]; lpTemp = lpSrc; // 讀取編碼后的象素 if (file.ReadHuge(lpSrc, file.GetLength() - sizeof(PCXHEADER) - 769) != file.GetLength() - sizeof(PCXHEADER) - 769 ) { // 大小不對。 // 解除鎖定 ::GlobalUnlock((HGLOBAL) hDIB); // 釋放內存 ::GlobalFree((HGLOBAL) hDIB); // 返回NULL。 return NULL; } // 計算DIB中像素位置 lpDst = (BYTE *) FindDIBBits(pDIB); // 一行一行解碼 for (j = 0; j <wHeight; j++) { i = 0; while (i < wWidth) { // 讀取一個字節 bChar = *lpTemp; lpTemp++; if ((bChar & 0xC0) == 0xC0) { // 行程 iCount = bChar & 0x3F; // 讀取下一個字節 bChar = *lpTemp; lpTemp++; // bChar重復iCount次保存 memset(&lpDst[(wHeight - j - 1) * lLineBytes + i], bChar, iCount); // 已經讀取像素的個數加iCount i += iCount; } else { // 保存當前字節 lpDst[(wHeight - j - 1) * lLineBytes + i] = bChar; // 已經讀取像素的個數加1 i += 1; } } } // 釋放內存 delete lpSrc; //************************************************************* // 調色板 // 讀調色板標志位 file.Read(&bChar, 1); if (bChar != 0x0C) { // 出錯 // 解除鎖定 ::GlobalUnlock((HGLOBAL) hDIB); // 釋放內存 ::GlobalFree((HGLOBAL) hDIB); // 返回NULL。 return NULL; } // 分配內存以讀取編碼后的象素 lpSrc = new BYTE[768]; // 計算DIB中調色板的位置 lpDst = (BYTE *) pDIB + sizeof(BITMAPINFOHEADER); // 讀取調色板 if (file.Read(lpSrc, 768) != 768) { // 大小不對。 // 解除鎖定 ::GlobalUnlock((HGLOBAL) hDIB); // 釋放內存 ::GlobalFree((HGLOBAL) hDIB); // 返回NULL。 return NULL; } // 給調色板賦值 for (i = 0; i < 256; i++) { lpDst[i * 4] = lpSrc[i * 3 + 2]; lpDst[i * 4 + 1] = lpSrc[i * 3 + 1]; lpDst[i * 4 + 2] = lpSrc[i * 3]; lpDst[i * 4 + 3] = 0; } // 釋放內存 delete lpSrc; // 解除鎖定 ::GlobalUnlock((HGLOBAL) hDIB); // 返回DIB句柄 return hDIB;}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -