?? dibapi.cpp
字號(hào):
// ************************************************************************// 文件名: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",寫(xiě)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。 * * 說(shuō)明: * 該函數(shù)主要用來(lái)繪制DIB對(duì)象。其中調(diào)用了StretchDIBits()或者 * SetDIBitsToDevice()來(lái)繪制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()來(lái)繪制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。 * * 說(shuō)明: * 該函數(shù)按照DIB創(chuàng)建一個(gè)邏輯調(diào)色板,從DIB中讀取顏色表并存到調(diào)色板中, * 最后按照該邏輯調(diào)色板創(chuàng)建一個(gè)新的調(diào)色板,并返回該調(diào)色板的句柄。這樣 * ************************************************************************/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圖像象素起始位置 * * 說(shuō)明: * 該函數(shù)計(jì)算DIB中圖像象素的起始位置,并返回指向它的指針。 * ************************************************************************/LPSTR WINAPI FindDIBBits(LPSTR lpbi){ return (lpbi + *(LPDWORD)lpbi + ::PaletteSize(lpbi));}/************************************************************************* * * 函數(shù)名稱: * DIBWidth() * * 參數(shù): * LPSTR lpbi - 指向DIB對(duì)象的指針 * * 返回值: * DWORD - DIB中圖像的寬度 * * 說(shuō)明: * 該函數(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中圖像的高度 * * 說(shuō)明: * 該函數(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)色板的大小 * * 說(shuō)明: * 該函數(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ù) * * 說(shuō)明: * 該函數(shù)返回DIB中調(diào)色板的顏色的種數(shù)。對(duì)于單色位圖,返回2, * 對(duì)于16色位圖,返回16,對(duì)于256色位圖,返回256;對(duì)于真彩色 * 位圖(24位),沒(méi)有調(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ù) * * 說(shuō)明: * 該函數(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ū)域 * * 說(shuō)明: * 該函數(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 * * 說(shuō)明: * 該函數(shù)將指定的DIB對(duì)象保存到指定的CFile中。該CFile由調(diào)用程序打開(kāi)和關(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)) { // 不支持其它類(lèi)型的DIB保存 // 解除鎖定 ::GlobalUnlock((HGLOBAL) hDib); // 返回FALSE return FALSE; } // 填充文件頭 // 文件類(lèi)型"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位圖,沒(méi)法計(jì)算大小,只能信任biSizeImage內(nèi)的值 dwDIBSize += lpBI->biSizeImage;
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -