?? dibapi.cpp
字號:
* DIBNumColors()
*
* 參數(shù):
* LPSTR lpbi - 指向DIB對象的指針
*
* 返回值:
* WORD - 返回調(diào)色板中顏色的種數(shù)
*
* 說明:
* 該函數(shù)返回DIB中調(diào)色板的顏色的種數(shù)。對于單色位圖,返回2,
* 對于16色位圖,返回16,對于256色位圖,返回256;對于真彩色
* 位圖(24位),沒有調(diào)色板,返回0。
*
************************************************************************/
WORD WINAPI DIBNumColors(LPSTR lpbi)
{
WORD wBitCount;
// 對于Windows的DIB, 實(shí)際顏色的數(shù)目可以比象素的位數(shù)要少。
// 對于這種情況,則返回一個(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對象的指針
*
* 返回值:
* 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對象保存到指定的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í),最簡單的方法是調(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))
{
// 對于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大小+BITMAPFILEHEADER結(jié)構(gòu)大小
bmfHdr.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER);
// 兩個(gè)保留字
bmfHdr.bfReserved1 = 0;
bmfHdr.bfReserved2 = 0;
// 計(jì)算偏移量bfOffBits,它的大小為Bitmap文件頭大小+DIB頭大小+顏色表大小
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對象讀到指定的內(nèi)存區(qū)域中。除BITMAPFILEHEADER
* 外的內(nèi)容都將被讀入內(nèi)存。
*
*************************************************************************/
HDIB WINAPI ReadDIBFile(CFile& file)
{
BITMAPFILEHEADER bmfHeader;
DWORD dwBitsSize;
HDIB hDIB;
LPSTR pDIB;
// 獲取DIB(文件)長度(字節(jié))
dwBitsSize = file.GetLength();
// 嘗試讀取DIB文件頭
if (file.Read((LPSTR)&bmfHeader, sizeof(bmfHeader)) != sizeof(bmfHeader))
{
// 大小不對,返回NULL。
return NULL;
}
// 判斷是否是DIB對象,檢查頭兩個(gè)字節(jié)是否是"BM"
if (bmfHeader.bfType != DIB_HEADER_MARKER)
{
// 非DIB對象,返回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) )
{
// 大小不對。
// 解除鎖定
::GlobalUnlock((HGLOBAL) hDIB);
// 釋放內(nèi)存
::GlobalFree((HGLOBAL) hDIB);
// 返回NULL。
return NULL;
}
// 解除鎖定
::GlobalUnlock((HGLOBAL) hDIB);
// 返回DIB句柄
return hDIB;
}
/*************************************************************************
*
* 函數(shù)名稱:
* DIBToPCX256()
*
* 參數(shù):
* LPSTR lpDIB - 指向DIB對象的指針
* CFile& file - 要保存的文件
*
* 返回值:
* BOOL - 成功返回True,否則返回False。
*
* 說明:
* 該函數(shù)將指定的256色DIB對象保存為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)識碼
pcxHdr.bManufacturer = 0x0A;
// PCX版本號
pcxHdr.bVersion = 5;
// PCX編碼方式(1表示RLE編碼)
pcxHdr.bEncoding = 1;
// 像素位數(shù)(256色為8位)
pcxHdr.bBpp = 8;
// 圖像相對于屏幕的左上角X坐標(biāo)(以像素為單位)
pcxHdr.wLeft = 0;
// 圖像相對于屏幕的左上角Y坐標(biāo)(以像素為單位)
pcxHdr.wTop = 0;
// 圖像相對于屏幕的右下角X坐標(biāo)(以像素為單位)
pcxHdr.wRight = wWidth - 1;
// 圖像相對于屏幕的右下角Y坐標(biāo)(以像素為單位)
pcxHdr.wBottom = wHeight - 1;
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -