// dibapi.h////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef _INC_DIBAPI
#define _INC_DIBAPI // DIB句柄
DECLARE_HANDLE(HDIB); // DIB常量
#define PALVERSION 0x300 /* DIB宏 */
// 判斷是否是Win 3.0的DIB
#define IS_WIN30_DIB(lpbi) ((*(LPDWORD)(lpbi)) == sizeof(BITMAPINFOHEADER)) // 計(jì)算矩形區(qū)域的寬度
#define RECTWIDTH(lpRect) ((lpRect)->right - (lpRect)->left) // 計(jì)算矩形區(qū)域的高度
#define RECTHEIGHT(lpRect) ((lpRect)->bottom - (lpRect)->top) // 在計(jì)算圖像大小時(shí),,采用公式:biSizeImage = biWidth' × biHeight,。
// 是biWidth',而不是biWidth,,這里的biWidth'必須是4的整倍數(shù),,表示 // 大于或等于biWidth的,離4最近的整倍數(shù),。WIDTHBYTES就是用來計(jì)算 // biWidth' #define WIDTHBYTES(bits) (((bits) + 31) / 32 * 4) // PCX文件頭結(jié)構(gòu)
typedef struct{ BYTE bManufacturer; BYTE bVersion; BYTE bEncoding; BYTE bBpp; WORD wLeft; WORD wTop; WORD wRight; WORD wBottom; WORD wXResolution; WORD wYResolution; BYTE bPalette[48]; BYTE bReserved; BYTE bPlanes; WORD wLineBytes; WORD wPaletteType; WORD wSrcWidth; WORD wSrcDepth; BYTE bFiller[54]; } PCXHEADER; // 函數(shù)原型
BOOL WINAPI PaintDIB (HDC, LPRECT, HDIB, LPRECT, CPalette* pPal); BOOL WINAPI CreateDIBPalette(HDIB hDIB, CPalette* cPal); LPSTR WINAPI FindDIBBits (LPSTR lpbi); DWORD WINAPI DIBWidth (LPSTR lpDIB); DWORD WINAPI DIBHeight (LPSTR lpDIB); WORD WINAPI PaletteSize (LPSTR lpbi); WORD WINAPI DIBNumColors (LPSTR lpbi); WORD WINAPI DIBBitCount(LPSTR lpbi); HGLOBAL WINAPI CopyHandle (HGLOBAL h); BOOL WINAPI SaveDIB (HDIB hDib, CFile& file);
HDIB WINAPI ReadDIBFile(CFile& file); BOOL WINAPI DIBToPCX256(LPSTR lpDIB, CFile& file);
HDIB WINAPI ReadPCX256(CFile& file); #endif //!_INC_DIBAPI
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ************************************************************************
// 文件名:dibapi.cpp // // DIB(Independent Bitmap) API函數(shù)庫(kù): // // PaintDIB() - 繪制DIB對(duì)象 // CreateDIBPalette() - 創(chuàng)建DIB對(duì)象調(diào)色板 // FindDIBBits() - 返回DIB圖像象素起始位置 // DIBWidth() - 返回DIB寬度 // DIBHeight() - 返回DIB高度 // PaletteSize() - 返回DIB調(diào)色板大小 // DIBNumColors() - 計(jì)算DIB調(diào)色板顏色數(shù)目 // CopyHandle() - 拷貝內(nèi)存塊 // // SaveDIB() - 將DIB保存到指定文件中 // ReadDIBFile() - 重指定文件中讀取DIB對(duì)象 // // DIBToPCX256() - 將指定的256色DIB對(duì)象保存為256色PCX文件 // ReadPCX256() - 讀取256色PCX文件 // // ************************************************************************ #include "stdafx.h"
#include "dibapi.h" #include <io.h> #include <errno.h> #include <math.h>
#include <direct.h> /*
* Dib文件頭標(biāo)志(字符串"BM",,寫DIB時(shí)用到該常數(shù)) */ #define DIB_HEADER_MARKER ((WORD) ('M' << 8) | 'B') /*************************************************************************
* * 函數(shù)名稱: * PaintDIB() * * 參數(shù): * HDC hDC - 輸出設(shè)備DC * LPRECT lpDCRect - 繪制矩形區(qū)域 * HDIB hDIB - 指向DIB對(duì)象的指針 * LPRECT lpDIBRect - 要輸出的DIB區(qū)域 * CPalette* pPal - 指向DIB對(duì)象調(diào)色板的指針 * * 返回值: * BOOL - 繪制成功返回TRUE,否則返回FALSE,。 * * 說明: * 該函數(shù)主要用來繪制DIB對(duì)象,。其中調(diào)用了StretchDIBits()或者 * SetDIBitsToDevice()來繪制DIB對(duì)象。輸出的設(shè)備由由參數(shù)hDC指 * 定,;繪制的矩形區(qū)域由參數(shù)lpDCRect指定,;輸出DIB的區(qū)域由參數(shù) * lpDIBRect指定。 * ************************************************************************/ BOOL WINAPI PaintDIB(HDC hDC,
LPRECT lpDCRect, HDIB hDIB, LPRECT lpDIBRect, CPalette* pPal) { LPSTR lpDIBHdr; // BITMAPINFOHEADER指針 LPSTR lpDIBBits; // DIB象素指針 BOOL bSuccess=FALSE; // 成功標(biāo)志 HPALETTE hPal=NULL; // DIB調(diào)色板 HPALETTE hOldPal=NULL; // 以前的調(diào)色板 // 判斷DIB對(duì)象是否為空
if (hDIB == NULL) { // 返回 return FALSE; } // 鎖定DIB
lpDIBHdr = (LPSTR) ::GlobalLock((HGLOBAL) hDIB); // 找到DIB圖像象素起始位置
lpDIBBits = ::FindDIBBits(lpDIBHdr); // 獲取DIB調(diào)色板,,并選中它
if (pPal != NULL) { hPal = (HPALETTE) pPal->m_hObject; // 選中調(diào)色板
hOldPal = ::SelectPalette(hDC, hPal, TRUE); } // 設(shè)置顯示模式
::SetStretchBltMode(hDC, COLORONCOLOR); // 判斷是調(diào)用StretchDIBits()還是SetDIBitsToDevice()來繪制DIB對(duì)象
if ((RECTWIDTH(lpDCRect) == RECTWIDTH(lpDIBRect)) && (RECTHEIGHT(lpDCRect) == RECTHEIGHT(lpDIBRect))) { // 原始大小,,不用拉伸。 bSuccess = ::SetDIBitsToDevice(hDC, // hDC lpDCRect->left, // DestX lpDCRect->top, // DestY RECTWIDTH(lpDCRect), // nDestWidth RECTHEIGHT(lpDCRect), // nDestHeight lpDIBRect->left, // SrcX (int)DIBHeight(lpDIBHdr) - lpDIBRect->top - RECTHEIGHT(lpDIBRect), // SrcY 0, // nStartScan (WORD)DIBHeight(lpDIBHdr), // nNumScans lpDIBBits, // lpBits (LPBITMAPINFO)lpDIBHdr, // lpBitsInfo DIB_RGB_COLORS); // wUsage } else { // 非原始大小,,拉伸,。 bSuccess = ::StretchDIBits(hDC, // hDC lpDCRect->left, // DestX lpDCRect->top, // DestY RECTWIDTH(lpDCRect), // nDestWidth RECTHEIGHT(lpDCRect), // nDestHeight lpDIBRect->left, // SrcX lpDIBRect->top, // SrcY RECTWIDTH(lpDIBRect), // wSrcWidth RECTHEIGHT(lpDIBRect), // wSrcHeight lpDIBBits, // lpBits (LPBITMAPINFO)lpDIBHdr, // lpBitsInfo DIB_RGB_COLORS, // wUsage SRCCOPY); // dwROP } // 解除鎖定 ::GlobalUnlock((HGLOBAL) hDIB); // 恢復(fù)以前的調(diào)色板 if (hOldPal != NULL) { ::SelectPalette(hDC, hOldPal, TRUE); } // 返回 return bSuccess; } /*************************************************************************
* * 函數(shù)名稱: * CreateDIBPalette() * * 參數(shù): * HDIB hDIB - 指向DIB對(duì)象的指針 * CPalette* pPal - 指向DIB對(duì)象調(diào)色板的指針 * * 返回值: * BOOL - 創(chuàng)建成功返回TRUE,否則返回FALSE,。 * * 說明: * 該函數(shù)按照DIB創(chuàng)建一個(gè)邏輯調(diào)色板,,從DIB中讀取顏色表并存到調(diào)色板中, * 最后按照該邏輯調(diào)色板創(chuàng)建一個(gè)新的調(diào)色板,,并返回該調(diào)色板的句柄,。這樣 * 可以用最好的顏色來顯示DIB圖像。 * ************************************************************************/ BOOL WINAPI CreateDIBPalette(HDIB hDIB, CPalette* pPal) { // 指向邏輯調(diào)色板的指針 LPLOGPALETTE lpPal; // 邏輯調(diào)色板的句柄 HANDLE hLogPal; // 調(diào)色板的句柄 HPALETTE hPal = NULL; // 循環(huán)變量 int i; // 顏色表中的顏色數(shù)目 WORD wNumColors; // 指向DIB的指針 LPSTR lpbi; // 指向BITMAPINFO結(jié)構(gòu)的指針(Win3.0) LPBITMAPINFO lpbmi; // 指向BITMAPCOREINFO結(jié)構(gòu)的指針 LPBITMAPCOREINFO lpbmc; // 表明是否是Win3.0 DIB的標(biāo)記 BOOL bWinStyleDIB; // 創(chuàng)建結(jié)果 BOOL bResult = FALSE; // 判斷DIB是否為空 if (hDIB == NULL) { // 返回FALSE return FALSE; } // 鎖定DIB lpbi = (LPSTR) ::GlobalLock((HGLOBAL) hDIB); // 獲取指向BITMAPINFO結(jié)構(gòu)的指針(Win3.0) lpbmi = (LPBITMAPINFO)lpbi; // 獲取指向BITMAPCOREINFO結(jié)構(gòu)的指針 lpbmc = (LPBITMAPCOREINFO)lpbi; // 獲取DIB中顏色表中的顏色數(shù)目 wNumColors = ::DIBNumColors(lpbi); if (wNumColors != 0) { // 分配為邏輯調(diào)色板內(nèi)存 hLogPal = ::GlobalAlloc(GHND, sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * wNumColors); // 如果內(nèi)存不足,,退出 if (hLogPal == 0) { // 解除鎖定 ::GlobalUnlock((HGLOBAL) hDIB); // 返回FALSE return FALSE; } lpPal = (LPLOGPALETTE) ::GlobalLock((HGLOBAL) hLogPal); // 設(shè)置版本號(hào) lpPal->palVersion = PALVERSION; // 設(shè)置顏色數(shù)目 lpPal->palNumEntries = (WORD)wNumColors; // 判斷是否是WIN3.0的DIB bWinStyleDIB = IS_WIN30_DIB(lpbi); // 讀取調(diào)色板
for (i = 0; i < (int)wNumColors; i++) { if (bWinStyleDIB) { // 讀取紅色分量 lpPal->palPalEntry[i].peRed = lpbmi->bmiColors[i].rgbRed; // 讀取綠色分量 lpPal->palPalEntry[i].peGreen = lpbmi->bmiColors[i].rgbGreen; // 讀取藍(lán)色分量 lpPal->palPalEntry[i].peBlue = lpbmi->bmiColors[i].rgbBlue; // 保留位 lpPal->palPalEntry[i].peFlags = 0; } else { // 讀取紅色分量 lpPal->palPalEntry[i].peRed = lpbmc->bmciColors[i].rgbtRed; // 讀取綠色分量 lpPal->palPalEntry[i].peGreen = lpbmc->bmciColors[i].rgbtGreen; // 讀取紅色分量 lpPal->palPalEntry[i].peBlue = lpbmc->bmciColors[i].rgbtBlue; // 保留位 lpPal->palPalEntry[i].peFlags = 0; } } // 按照邏輯調(diào)色板創(chuàng)建調(diào)色板,,并返回指針 bResult = pPal->CreatePalette(lpPal); // 解除鎖定 ::GlobalUnlock((HGLOBAL) hLogPal); // 釋放邏輯調(diào)色板 ::GlobalFree((HGLOBAL) hLogPal); } // 解除鎖定 ::GlobalUnlock((HGLOBAL) hDIB); // 返回結(jié)果 return bResult; } /*************************************************************************
* * 函數(shù)名稱: * FindDIBBits() * * 參數(shù): * LPSTR lpbi - 指向DIB對(duì)象的指針 * * 返回值: * LPSTR - 指向DIB圖像象素起始位置 * * 說明: * 該函數(shù)計(jì)算DIB中圖像象素的起始位置,并返回指向它的指針,。 * ************************************************************************/ LPSTR WINAPI FindDIBBits(LPSTR lpbi) { return (lpbi + *(LPDWORD)lpbi + ::PaletteSize(lpbi)); } /************************************************************************* * * 函數(shù)名稱: * DIBWidth() * * 參數(shù): * LPSTR lpbi - 指向DIB對(duì)象的指針 * * 返回值: * DWORD - DIB中圖像的寬度 * * 說明: * 該函數(shù)返回DIB中圖像的寬度,。對(duì)于Windows 3.0 DIB,返回BITMAPINFOHEADER * 中的biWidth值,;對(duì)于其它返回BITMAPCOREHEADER中的bcWidth值,。 * ************************************************************************/ DWORD WINAPI DIBWidth(LPSTR lpDIB) { // 指向BITMAPINFO結(jié)構(gòu)的指針(Win3.0) LPBITMAPINFOHEADER lpbmi; // 指向BITMAPCOREINFO結(jié)構(gòu)的指針 LPBITMAPCOREHEADER lpbmc; // 獲取指針
lpbmi = (LPBITMAPINFOHEADER)lpDIB; lpbmc = (LPBITMAPCOREHEADER)lpDIB; // 返回DIB中圖像的寬度
if (IS_WIN30_DIB(lpDIB)) { // 對(duì)于Windows 3.0 DIB,返回lpbmi->biWidth return lpbmi->biWidth; } else { // 對(duì)于其它格式的DIB,,返回lpbmc->bcWidth return (DWORD)lpbmc->bcWidth; } } /************************************************************************* * * 函數(shù)名稱: * DIBHeight() * * 參數(shù): * LPSTR lpDIB - 指向DIB對(duì)象的指針 * * 返回值: * DWORD - DIB中圖像的高度 * * 說明: * 該函數(shù)返回DIB中圖像的高度,。對(duì)于Windows 3.0 DIB,,返回BITMAPINFOHEADER * 中的biHeight值;對(duì)于其它返回BITMAPCOREHEADER中的bcHeight值,。 * ************************************************************************/ DWORD WINAPI DIBHeight(LPSTR lpDIB) { // 指向BITMAPINFO結(jié)構(gòu)的指針(Win3.0) LPBITMAPINFOHEADER lpbmi; // 指向BITMAPCOREINFO結(jié)構(gòu)的指針 LPBITMAPCOREHEADER lpbmc; // 獲取指針
lpbmi = (LPBITMAPINFOHEADER)lpDIB; lpbmc = (LPBITMAPCOREHEADER)lpDIB; // 返回DIB中圖像的寬度
if (IS_WIN30_DIB(lpDIB)) { // 對(duì)于Windows 3.0 DIB,,返回lpbmi->biHeight return lpbmi->biHeight; } else { // 對(duì)于其它格式的DIB,返回lpbmc->bcHeight return (DWORD)lpbmc->bcHeight; } } /************************************************************************* * * 函數(shù)名稱: * PaletteSize() * * 參數(shù): * LPSTR lpbi - 指向DIB對(duì)象的指針 * * 返回值: * WORD - DIB中調(diào)色板的大小 * * 說明: * 該函數(shù)返回DIB中調(diào)色板的大小,。對(duì)于Windows 3.0 DIB,,返回顏色數(shù)目× * RGBQUAD的大小,;對(duì)于其它返回顏色數(shù)目×RGBTRIPLE的大小,。 * ************************************************************************/ WORD WINAPI PaletteSize(LPSTR lpbi) { // 計(jì)算DIB中調(diào)色板的大小 if (IS_WIN30_DIB (lpbi)) { //返回顏色數(shù)目×RGBQUAD的大小 return (WORD)(::DIBNumColors(lpbi) * sizeof(RGBQUAD)); } else { //返回顏色數(shù)目×RGBTRIPLE的大小 return (WORD)(::DIBNumColors(lpbi) * sizeof(RGBTRIPLE)); } } /************************************************************************* * * 函數(shù)名稱: * DIBNumColors() * * 參數(shù): * LPSTR lpbi - 指向DIB對(duì)象的指針 * * 返回值: * WORD - 返回調(diào)色板中顏色的種數(shù) * * 說明: * 該函數(shù)返回DIB中調(diào)色板的顏色的種數(shù)。對(duì)于單色位圖,,返回2,, * 對(duì)于16色位圖,返回16,,對(duì)于256色位圖,,返回256;對(duì)于真彩色 * 位圖(24位),,沒有調(diào)色板,返回0,。 * ************************************************************************/ WORD WINAPI DIBNumColors(LPSTR lpbi) { WORD wBitCount; // 對(duì)于Windows的DIB, 實(shí)際顏色的數(shù)目可以比象素的位數(shù)要少,。
// 對(duì)于這種情況,則返回一個(gè)近似的數(shù)值,。 // 判斷是否是WIN3.0 DIB if (IS_WIN30_DIB(lpbi)) { DWORD dwClrUsed; // 讀取dwClrUsed值 dwClrUsed = ((LPBITMAPINFOHEADER)lpbi)->biClrUsed; if (dwClrUsed != 0) { // 如果dwClrUsed(實(shí)際用到的顏色數(shù))不為0,,直接返回該值 return (WORD)dwClrUsed; } } // 讀取象素的位數(shù)
if (IS_WIN30_DIB(lpbi)) { // 讀取biBitCount值 wBitCount = ((LPBITMAPINFOHEADER)lpbi)->biBitCount; } else { // 讀取biBitCount值 wBitCount = ((LPBITMAPCOREHEADER)lpbi)->bcBitCount; } // 按照象素的位數(shù)計(jì)算顏色數(shù)目 switch (wBitCount) { case 1: return 2; case 4:
return 16; case 8:
return 256; default:
return 0; } } /************************************************************************* * * 函數(shù)名稱: * DIBBitCount() * * 參數(shù): * LPSTR lpbi - 指向DIB對(duì)象的指針 * * 返回值: * WORD - 返回調(diào)色板中顏色的種數(shù) * * 說明: * 該函數(shù)返回DIBBitCount。 * ************************************************************************/ WORD WINAPI DIBBitCount(LPSTR lpbi) { WORD wBitCount; // 讀取象素的位數(shù)
if (IS_WIN30_DIB(lpbi)) { // 讀取biBitCount值 wBitCount = ((LPBITMAPINFOHEADER)lpbi)->biBitCount; } else { // 讀取biBitCount值 wBitCount = ((LPBITMAPCOREHEADER)lpbi)->bcBitCount; } // 返回wBitCount return wBitCount; } /*************************************************************************
* * 函數(shù)名稱: * CopyHandle() * * 參數(shù): * HGLOBAL h - 要復(fù)制的內(nèi)存區(qū)域 * * 返回值: * HGLOBAL - 復(fù)制后的新內(nèi)存區(qū)域 * * 說明: * 該函數(shù)復(fù)制指定的內(nèi)存區(qū)域,。返回復(fù)制后的新內(nèi)存區(qū)域,,出錯(cuò)時(shí)返回0。 * ************************************************************************/ HGLOBAL WINAPI CopyHandle (HGLOBAL h)
{ if (h == NULL) return NULL; // 獲取指定內(nèi)存區(qū)域大小
DWORD dwLen = ::GlobalSize((HGLOBAL) h); // 分配新內(nèi)存空間 HGLOBAL hCopy = ::GlobalAlloc(GHND, dwLen); // 判斷分配是否成功 if (hCopy != NULL) { // 鎖定 void* lpCopy = ::GlobalLock((HGLOBAL) hCopy); void* lp = ::GlobalLock((HGLOBAL) h); // 復(fù)制 memcpy(lpCopy, lp, dwLen); // 解除鎖定 ::GlobalUnlock(hCopy); ::GlobalUnlock(h); } return hCopy;
} /*************************************************************************
* * 函數(shù)名稱: * SaveDIB() * * 參數(shù): * HDIB hDib - 要保存的DIB * CFile& file - 保存文件CFile * * 返回值: * BOOL - 成功返回TRUE,,否則返回FALSE或者CFileException * * 說明: * 該函數(shù)將指定的DIB對(duì)象保存到指定的CFile中,。該CFile由調(diào)用程序打開和關(guān)閉。 * *************************************************************************/ BOOL WINAPI SaveDIB(HDIB hDib, CFile& file) { // Bitmap文件頭 BITMAPFILEHEADER bmfHdr; // 指向BITMAPINFOHEADER的指針 LPBITMAPINFOHEADER lpBI; // DIB大小 DWORD dwDIBSize; if (hDib == NULL)
{ // 如果DIB為空,,返回FALSE return FALSE; } // 讀取BITMAPINFO結(jié)構(gòu),,并鎖定
lpBI = (LPBITMAPINFOHEADER) ::GlobalLock((HGLOBAL) hDib); if (lpBI == NULL) { // 為空,返回FALSE return FALSE; } // 判斷是否是WIN3.0 DIB if (!IS_WIN30_DIB(lpBI)) { // 不支持其它類型的DIB保存 // 解除鎖定 ::GlobalUnlock((HGLOBAL) hDib); // 返回FALSE return FALSE; } // 填充文件頭
// 文件類型"BM"
bmfHdr.bfType = DIB_HEADER_MARKER; // 計(jì)算DIB大小時(shí),,最簡(jiǎn)單的方法是調(diào)用GlobalSize()函數(shù),。但是全局內(nèi)存大小并
// 不是DIB真正的大小,它總是多幾個(gè)字節(jié),。這樣就需要計(jì)算一下DIB的真實(shí)大小,。 // 文件頭大小+顏色表大小 // (BITMAPINFOHEADER和BITMAPCOREHEADER結(jié)構(gòu)的第一個(gè)DWORD都是該結(jié)構(gòu)的大小) dwDIBSize = *(LPDWORD)lpBI + ::PaletteSize((LPSTR)lpBI); // 計(jì)算圖像大小 if ((lpBI->biCompression == BI_RLE8) || (lpBI->biCompression == BI_RLE4)) { // 對(duì)于RLE位圖,,沒法計(jì)算大小,,只能信任biSizeImage內(nèi)的值 dwDIBSize += lpBI->biSizeImage; } else { // 象素的大小 DWORD dwBmBitsSize; // 大小為Width * Height
dwBmBitsSize = WIDTHBYTES((lpBI->biWidth)*((DWORD)lpBI->biBitCount)) * lpBI->biHeight; // 計(jì)算出DIB真正的大小 dwDIBSize += dwBmBitsSize; // 更新biSizeImage(很多BMP文件頭中biSizeImage的值是錯(cuò)誤的)
lpBI->biSizeImage = dwBmBitsSize; } // 計(jì)算文件大小:DIB大?。獴ITMAPFILEHEADER結(jié)構(gòu)大小 bmfHdr.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER); // 兩個(gè)保留字 bmfHdr.bfReserved1 = 0; bmfHdr.bfReserved2 = 0; // 計(jì)算偏移量bfOffBits,,它的大小為Bitmap文件頭大小+DIB頭大?。伾泶笮?br> 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; } /************************************************************************* * * 函數(shù)名稱: * ReadDIBFile() * * 參數(shù): * CFile& file - 要讀取得文件文件CFile * * 返回值: * HDIB - 成功返回DIB的句柄,,否則返回NULL。 * * 說明: * 該函數(shù)將指定的文件中的DIB對(duì)象讀到指定的內(nèi)存區(qū)域中,。除BITMAPFILEHEADER * 外的內(nèi)容都將被讀入內(nèi)存,。 * *************************************************************************/ HDIB WINAPI ReadDIBFile(CFile& file)
{ BITMAPFILEHEADER bmfHeader; DWORD dwBitsSize; HDIB hDIB; LPSTR pDIB; // 獲取DIB(文件)長(zhǎng)度(字節(jié))
dwBitsSize = file.GetLength(); // 嘗試讀取DIB文件頭
if (file.Read((LPSTR)&bmfHeader, sizeof(bmfHeader)) != sizeof(bmfHeader)) { // 大小不對(duì),返回NULL,。 return NULL; } // 判斷是否是DIB對(duì)象,,檢查頭兩個(gè)字節(jié)是否是"BM"
if (bmfHeader.bfType != DIB_HEADER_MARKER) { // 非DIB對(duì)象,返回NULL,。 return NULL; } // 為DIB分配內(nèi)存
hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwBitsSize); if (hDIB == 0) { // 內(nèi)存分配失敗,,返回NULL。 return NULL; } // 鎖定 pDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB); // 讀象素
if (file.ReadHuge(pDIB, dwBitsSize - sizeof(BITMAPFILEHEADER)) != dwBitsSize - sizeof(BITMAPFILEHEADER) ) { // 大小不對(duì),。 // 解除鎖定 ::GlobalUnlock((HGLOBAL) hDIB); // 釋放內(nèi)存 ::GlobalFree((HGLOBAL) hDIB); // 返回NULL,。 return NULL; } // 解除鎖定 ::GlobalUnlock((HGLOBAL) hDIB); // 返回DIB句柄 return hDIB; } /*************************************************************************
* * 函數(shù)名稱: * DIBToPCX256() * * 參數(shù): * LPSTR lpDIB - 指向DIB對(duì)象的指針 * CFile& file - 要保存的文件 * * 返回值: * BOOL - 成功返回True,否則返回False,。 * * 說明: * 該函數(shù)將指定的256色DIB對(duì)象保存為256色PCX文件,。 * *************************************************************************/ BOOL WINAPI DIBToPCX256(LPSTR lpDIB, CFile& file) { // 循環(huán)變量 LONG i; LONG j; // DIB高度 WORD wHeight; // DIB寬度 WORD wWidth; // 中間變量 BYTE bChar1; BYTE bChar2; // 指向源圖像象素的指針 BYTE * lpSrc; // 指向編碼后圖像數(shù)據(jù)的指針 BYTE * lpDst; // 圖像每行的字節(jié)數(shù) LONG lLineBytes; // 重復(fù)像素計(jì)數(shù) int iCount; // 緩沖區(qū)已使用的字節(jié)數(shù) DWORD dwBuffUsed; // 指向DIB象素指針 LPSTR lpDIBBits; // 獲取DIB高度 wHeight = (WORD) DIBHeight(lpDIB); // 獲取DIB寬度 wWidth = (WORD) DIBWidth(lpDIB); // 找到DIB圖像象素起始位置 lpDIBBits = FindDIBBits(lpDIB); // 計(jì)算圖像每行的字節(jié)數(shù) lLineBytes = WIDTHBYTES(wWidth * 8); //************************************************************************* // PCX文件頭 PCXHEADER pcxHdr; // 給文件頭賦值 // PCX標(biāo)識(shí)碼 pcxHdr.bManufacturer = 0x0A; // PCX版本號(hào) pcxHdr.bVersion = 5; // PCX編碼方式(1表示RLE編碼) pcxHdr.bEncoding = 1; // 像素位數(shù)(256色為8位) pcxHdr.bBpp = 8; // 圖像相對(duì)于屏幕的左上角X坐標(biāo)(以像素為單位) pcxHdr.wLeft = 0; // 圖像相對(duì)于屏幕的左上角Y坐標(biāo)(以像素為單位) pcxHdr.wTop = 0; // 圖像相對(duì)于屏幕的右下角X坐標(biāo)(以像素為單位) pcxHdr.wRight = wWidth - 1; // 圖像相對(duì)于屏幕的右下角Y坐標(biāo)(以像素為單位) pcxHdr.wBottom = wHeight - 1; // 圖像的水平分辨率 pcxHdr.wXResolution = wWidth; // 圖像的垂直分辨率 pcxHdr.wYResolution = wHeight; // 調(diào)色板數(shù)據(jù)(對(duì)于256色PCX無意義,直接賦值為0) for (i = 0; i < 48; i ++) { pcxHdr.bPalette[i] = 0; } // 保留域,,設(shè)定為0,。 pcxHdr.bReserved = 0; // 圖像色彩平面數(shù)目(對(duì)于256色PCX設(shè)定為1)。 pcxHdr.bPlanes = 1; // 圖像的寬度(字節(jié)為單位),,必須為偶數(shù),。 // if ((wWidth & 1) == 0) // { pcxHdr.wLineBytes = wWidth; // } // else // { // pcxHdr.wLineBytes = wWidth + 1; // } // 圖像調(diào)色板的類型,1表示彩色或者單色圖像,,2表示圖像是灰度圖,。 pcxHdr.wPaletteType = 1; // 制作該圖像的屏幕寬度(像素為單位) pcxHdr.wSrcWidth = 0; // 制作該圖像的屏幕高度(像素為單位) pcxHdr.wSrcDepth = 0; // 保留域,取值設(shè)定為0,。 for (i = 0; i < 54; i ++) { pcxHdr.bFiller[i] = 0; } // 寫入文件頭 file.Write((LPSTR)&pcxHdr, sizeof(PCXHEADER)); //******************************************************************************* // 開始編碼 // 開辟一片緩沖區(qū)(2被原始圖像大小)以保存編碼結(jié)果 lpDst = new BYTE[wHeight * wWidth * 2]; // 指明當(dāng)前已經(jīng)用了多少緩沖區(qū)(字節(jié)數(shù)) dwBuffUsed = 0; // 每行 for (i = 0; i < wHeight; i++) { // 指向DIB第i行,,第0個(gè)象素的指針 lpSrc = (BYTE *)lpDIBBits + lLineBytes * (wHeight - 1 - i); // 給bChar1賦值 bChar1 = *lpSrc; // 設(shè)置iCount為1 iCount = 1; // 剩余列 for (j = 1; j < wWidth; j ++) { // 指向DIB第i行,第j個(gè)象素的指針 lpSrc++; // 讀取下一個(gè)像素 bChar2 = *lpSrc; // 判斷是否和bChar1相同并且iCount < 63 if ((bChar1 == bChar2) && (iCount < 63)) { // 相同,,計(jì)數(shù)加1 iCount ++; // 繼續(xù)讀下一個(gè) } else { // 不同,,或者iCount = 63 // 寫入緩沖區(qū) if ((iCount > 1) || (bChar1 >= 0xC0)) { // 保存碼長(zhǎng)信息 lpDst[dwBuffUsed] = iCount | 0xC0; // 保存bChar1 lpDst[dwBuffUsed + 1] = bChar1; // 更新dwBuffUsed dwBuffUsed += 2; } else { // 直接保存該值 lpDst[dwBuffUsed] = bChar1; // 更新dwBuffUsed dwBuffUsed ++; } // 重新給bChar1賦值 bChar1 = bChar2; // 設(shè)置iCount為1 iCount = 1; } } // 保存每行最后一部分編碼 if ((iCount > 1) || (bChar1 >= 0xC0)) { // 保存碼長(zhǎng)信息 lpDst[dwBuffUsed] = iCount | 0xC0; // 保存bChar1 lpDst[dwBuffUsed + 1] = bChar1; // 更新dwBuffUsed dwBuffUsed += 2; } else { // 直接保存該值 lpDst[dwBuffUsed] = bChar1; // 更新dwBuffUsed dwBuffUsed ++; } } // 寫入編碼結(jié)果 file.WriteHuge((LPSTR)lpDst, dwBuffUsed); // 釋放內(nèi)存 delete lpDst; //************************************************************************** // 寫入調(diào)色板信息 // 指向BITMAPINFO結(jié)構(gòu)的指針(Win3.0) LPBITMAPINFO lpbmi; // 指向BITMAPCOREINFO結(jié)構(gòu)的指針 LPBITMAPCOREINFO lpbmc; // 表明是否是Win3.0 DIB的標(biāo)記 BOOL bWinStyleDIB; // 開辟一片緩沖區(qū)以保存調(diào)色板 lpDst = new BYTE[769]; // 調(diào)色板起始字節(jié) * lpDst = 0x0C; // 獲取指向BITMAPINFO結(jié)構(gòu)的指針(Win3.0) lpbmi = (LPBITMAPINFO)lpDIB; // 獲取指向BITMAPCOREINFO結(jié)構(gòu)的指針 lpbmc = (LPBITMAPCOREINFO)lpDIB; // 判斷是否是WIN3.0的DIB bWinStyleDIB = IS_WIN30_DIB(lpDIB); // 讀取當(dāng)前DIB調(diào)色板 for (i = 0; i < 256; i ++) { if (bWinStyleDIB) { // 讀取DIB調(diào)色板紅色分量 lpDst[i * 3 + 1] = lpbmi->bmiColors[i].rgbRed; // 讀取DIB調(diào)色板綠色分量 lpDst[i * 3 + 2] = lpbmi->bmiColors[i].rgbGreen; // 讀取DIB調(diào)色板藍(lán)色分量 lpDst[i * 3 + 3] = lpbmi->bmiColors[i].rgbBlue; } else { // 讀取DIB調(diào)色板紅色分量 lpDst[i * 3 + 1] = lpbmc->bmciColors[i].rgbtRed; // 讀取DIB調(diào)色板綠色分量 lpDst[i * 3 + 2] = lpbmc->bmciColors[i].rgbtGreen; // 讀取DIB調(diào)色板藍(lán)色分量 lpDst[i * 3 + 3] = lpbmc->bmciColors[i].rgbtBlue; } } // 寫入調(diào)色板信息 file.Write((LPSTR)lpDst, 769); // 返回 return TRUE; } /*************************************************************************
* * 函數(shù)名稱: * ReadPCX256() * * 參數(shù): * CFile& file - 要讀取的文件 * * 返回值: * HDIB - 成功返回DIB的句柄,,否則返回NULL。 * * 說明: * 該函數(shù)將讀取指定的256色PCX文件,。將讀取的結(jié)果保存在一個(gè)未壓縮 * 編碼的DIB對(duì)象中,。 * *************************************************************************/ HDIB WINAPI ReadPCX256(CFile& file) { // PCX文件頭 PCXHEADER pcxHdr; // DIB大小(字節(jié)數(shù)) DWORD dwDIBSize; // DIB句柄 HDIB hDIB; // DIB指針 LPSTR pDIB; // 循環(huán)變量 LONG i; LONG j; // 重復(fù)像素計(jì)數(shù) int iCount; // DIB高度 WORD wHeight; // DIB寬度 WORD wWidth; // 圖像每行的字節(jié)數(shù) LONG lLineBytes; // 中間變量 BYTE bChar; // 指向源圖像象素的指針 BYTE * lpSrc; // 指向編碼后圖像數(shù)據(jù)的指針 BYTE * lpDst; // 臨時(shí)指針 BYTE * lpTemp; // 嘗試讀取PCX文件頭 if (file.Read((LPSTR)&pcxHdr, sizeof(PCXHEADER)) != sizeof(PCXHEADER)) { // 大小不對(duì),,返回NULL,。 return NULL; } // 判斷是否是256色PCX文件,檢查第一個(gè)字節(jié)是否是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; // 計(jì)算圖像每行的字節(jié)數(shù) lLineBytes = WIDTHBYTES(wWidth * 8); // 計(jì)算DIB長(zhǎng)度(字節(jié)) dwDIBSize = sizeof(BITMAPINFOHEADER) + 1024 + wHeight * lLineBytes; // 為DIB分配內(nèi)存 hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwDIBSize); if (hDIB == 0) { // 內(nèi)存分配失敗,,返回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; // 分配內(nèi)存以讀取編碼后的象素 lpSrc = new BYTE[file.GetLength() - sizeof(PCXHEADER) - 769]; lpTemp = lpSrc; // 讀取編碼后的象素 if (file.ReadHuge(lpSrc, file.GetLength() - sizeof(PCXHEADER) - 769) != file.GetLength() - sizeof(PCXHEADER) - 769 ) { // 大小不對(duì)。 // 解除鎖定 ::GlobalUnlock((HGLOBAL) hDIB); // 釋放內(nèi)存 ::GlobalFree((HGLOBAL) hDIB); // 返回NULL,。 return NULL; } // 計(jì)算DIB中像素位置 lpDst = (BYTE *) FindDIBBits(pDIB); // 一行一行解碼 for (j = 0; j <wHeight; j++) { i = 0; while (i < wWidth) { // 讀取一個(gè)字節(jié) bChar = *lpTemp; lpTemp++; if ((bChar & 0xC0) == 0xC0) { // 行程 iCount = bChar & 0x3F; // 讀取下一個(gè)字節(jié) bChar = *lpTemp; lpTemp++; // bChar重復(fù)iCount次保存 memset(&lpDst[(wHeight - j - 1) * lLineBytes + i], bChar, iCount); // 已經(jīng)讀取像素的個(gè)數(shù)加iCount
i += iCount; } else { // 保存當(dāng)前字節(jié) lpDst[(wHeight - j - 1) * lLineBytes + i] = bChar; // 已經(jīng)讀取像素的個(gè)數(shù)加1 i += 1; } } } // 釋放內(nèi)存 delete lpSrc; //************************************************************* // 調(diào)色板 // 讀調(diào)色板標(biāo)志位 file.Read(&bChar, 1); if (bChar != 0x0C) { // 出錯(cuò) // 解除鎖定 ::GlobalUnlock((HGLOBAL) hDIB); // 釋放內(nèi)存 ::GlobalFree((HGLOBAL) hDIB); // 返回NULL,。 return NULL; } // 分配內(nèi)存以讀取編碼后的象素 lpSrc = new BYTE[768]; // 計(jì)算DIB中調(diào)色板的位置 lpDst = (BYTE *) pDIB + sizeof(BITMAPINFOHEADER); // 讀取調(diào)色板 if (file.Read(lpSrc, 768) != 768) { // 大小不對(duì)。 // 解除鎖定 ::GlobalUnlock((HGLOBAL) hDIB); // 釋放內(nèi)存 ::GlobalFree((HGLOBAL) hDIB); // 返回NULL,。 return NULL; } // 給調(diào)色板賦值 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; } // 釋放內(nèi)存 delete lpSrc; // 解除鎖定 ::GlobalUnlock((HGLOBAL) hDIB); // 返回DIB句柄 return hDIB; } |
|