?? dib.cpp
字號:
{
int nBitCount;
// 對于Windows的DIB, 實際顏色的數目可以比象素的位數要少。
// 對于這種情況,則返回一個近似的數值。
// 判斷是否是WIN3.0 DIB
if (IS_WIN30_DIB(lpbi))
{
// 讀取dwClrUsed值
DWORD dwClrUsed = ((LPBITMAPINFOHEADER)lpbi)->biClrUsed;
if (dwClrUsed != 0)
{
// 如果dwClrUsed(實際用到的顏色數)不為0,直接返回該值
return (WORD)dwClrUsed;
}
}
// 讀取象素的位數
if (IS_WIN30_DIB(lpbi))
{
// 讀取biBitCount值
nBitCount = ((LPBITMAPINFOHEADER)lpbi)->biBitCount;
}
else
{
// 讀取biBitCount值
nBitCount = ((LPBITMAPCOREHEADER)lpbi)->bcBitCount;
}
// 按照象素的位數計算顏色數目
switch (nBitCount)
{
case 1:
return 2;
case 4:
return 16;
case 8:
return 256;
default:
return 0;
}
}
/*************************************************************************
*
* 函數名稱:
* DIBBitCount()
*
* 參數:
* LPBYTE lpbi - 指向DIB對象的指針
*
* 返回值:
* WORD - 返回調色板中顏色的種數
*
* 說明:
* 該函數返回DIBBitCount。
*
************************************************************************/
WORD CDIB::DIBBitCount(LPBYTE lpbi)
{
int nBitCount;
// 讀取象素的位數
if (IS_WIN30_DIB(lpbi))
{
// 讀取biBitCount值
nBitCount = ((LPBITMAPINFOHEADER)lpbi)->biBitCount;
}
else
{
// 讀取biBitCount值
nBitCount = ((LPBITMAPCOREHEADER)lpbi)->bcBitCount;
}
// 返回nBitCount
return nBitCount;
}
/*************************************************************************
*
* 函數名稱:
* CopyHandle()
*
* 參數:
* HGLOBAL h - 要復制的內存區域
*
* 返回值:
* HGLOBAL - 復制后的新內存區域
*
* 說明:
* 拷貝內存塊
*
************************************************************************/
HGLOBAL CDIB::CopyHandle (HGLOBAL h)
{
if (h == NULL)
return NULL;
// 獲取指定內存區域大小
DWORD dwLen = ::GlobalSize((HGLOBAL) h);
// 分配新內存空間
HGLOBAL hCopy = ::GlobalAlloc(GHND, dwLen);
// 判斷分配是否成功
if (hCopy != NULL)
{
// 鎖定
void* lpCopy = ::GlobalLock((HGLOBAL) hCopy);
void* lp = ::GlobalLock((HGLOBAL) h);
// 復制
memcpy(lpCopy, lp, dwLen);
// 解除鎖定
::GlobalUnlock(hCopy);
::GlobalUnlock(h);
}
return hCopy;
}
/*************************************************************************
*
* 函數名稱:
* SaveDIB()
*
* 參數:
* HDIB hDib - 要保存的DIB
* CFile& file - 保存文件CFile
*
* 返回值:
* BOOL - 成功返回TRUE,否則返回FALSE或者CFileException
*
* 說明:
* 將DIB保存到指定文件中
*
*************************************************************************/
BOOL CDIB::SaveDIB(HDIB hDib, CFile& file)
{
// Bitmap文件頭
BITMAPFILEHEADER bmfHdr;
// 指向BITMAPINFOHEADER的指針
LPBITMAPINFOHEADER lpBI;
if (hDib == NULL)
{
// 如果DIB為空,返回FALSE
return FALSE;
}
// 讀取BITMAPINFO結構,并鎖定
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;
// 計算DIB大小時,最簡單的方法是調用GlobalSize()函數。但是全局內存大小并
// 不是DIB真正的大小,它總是多幾個字節。這樣就需要計算一下DIB的真實大小。
// 文件頭大小+顏色表大小
// (BITMAPINFOHEADER和BITMAPCOREHEADER結構的第一個DWORD都是該結構的大小)
DWORD dwDIBSize = *(LPDWORD)lpBI + PaletteSize((LPBYTE)lpBI);
// 計算圖像大小
if ((lpBI->biCompression == BI_RLE8) || (lpBI->biCompression == BI_RLE4))
{
// 對于RLE位圖,沒法計算大小,只能信任biSizeImage內的值
dwDIBSize += lpBI->biSizeImage;
}
else
{
// 大小為Width * Height
DWORD dwBmBitsSize = WIDTHBYTES((lpBI->biWidth)*((DWORD)lpBI->biBitCount)) * lpBI->biHeight;
// 計算出DIB真正的大小
dwDIBSize += dwBmBitsSize;
// 更新biSizeImage(很多BMP文件頭中biSizeImage的值是錯誤的)
lpBI->biSizeImage = dwBmBitsSize;
}
// 計算文件大小:DIB大小+BITMAPFILEHEADER結構大小
bmfHdr.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER);
// 兩個保留字
bmfHdr.bfReserved1 = 0;
bmfHdr.bfReserved2 = 0;
// 計算偏移量bfOffBits,它的大小為Bitmap文件頭大小+DIB頭大小+顏色表大小
bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + lpBI->biSize + PaletteSize((LPBYTE)lpBI);
// 嘗試寫文件
TRY
{
// 寫文件頭
file.Write((LPBYTE)&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對象
*
*************************************************************************/
HDIB CDIB::ReadDIBFile(CFile& file)
{
BITMAPFILEHEADER bmfHeader;
HDIB hDIB;
LPBYTE lpDIB;
// 獲取DIB(文件)長度(字節)
DWORD dwBitsSize = file.GetLength();
// 嘗試讀取DIB文件頭
if (file.Read((LPBYTE)&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;
}
// 鎖定
lpDIB = (LPBYTE) ::GlobalLock((HGLOBAL) hDIB);
// 讀象素
if (file.ReadHuge(lpDIB, dwBitsSize - sizeof(BITMAPFILEHEADER)) !=
dwBitsSize - sizeof(BITMAPFILEHEADER) )
{
// 大小不對。
// 解除鎖定
::GlobalUnlock((HGLOBAL) hDIB);
// 釋放內存
::GlobalFree((HGLOBAL) hDIB);
// 返回NULL。
return NULL;
}
// 解除鎖定
::GlobalUnlock((HGLOBAL) hDIB);
// 返回DIB句柄
return hDIB;
}
/*************************************************************************
*
* 函數名稱:
* SetRgnColor()
*
* 參數:
* HDIB hDIB - 要讀取的文件
* CRect rect - 設置的矩形區
* COLORREF col - 填充的顏色
*
* 返回值:
* 無返回值
*
* 說明:
* 該函數用指定的顏色填充指定的區域
*
*************************************************************************/
void CDIB::SetRgnColor(HDIB hDIB, CRect rect, COLORREF col)
{
// 循環變量
LONG i;
LONG j;
// 指向DIB的指針
LPBYTE lpDIB;
// 指向DIB象素指針
LPBYTE lpDIBBits;
// 鎖定DIB
lpDIB = (LPBYTE) ::GlobalLock((HGLOBAL) hDIB);
// 找到DIB圖像象素起始位置
lpDIBBits = FindDIBBits(lpDIB);
// DIB的寬度
LONG lWidth = DIBWidth(lpDIB);
// DIB的高度
LONG lHeight = DIBHeight(lpDIB);
// 計算圖像每行的字節數
LONG lLineBytes = WIDTHBYTES(lWidth * 24);
// 對區域進行顏色填充
for (i = lHeight - rect.bottom; i < lHeight - rect.top; i++)
{
for (j = rect.left * 3; j < rect.right * 3; j++)
{
*(unsigned char *)(lpDIBBits + lLineBytes * i + j) = GetBValue(col);
j++;
*(unsigned char *)(lpDIBBits + lLineBytes * i + j) = GetGValue(col);
j++;
*(unsigned char *)(lpDIBBits + lLineBytes * i + j) = GetRValue(col);
}
}
// 解除鎖定
::GlobalUnlock((HGLOBAL) hDIB);
}
/*************************************************************************
*
* 函數名稱:
* SetCircleColor()
*
* 參數:
* HDIB hDIB - 要讀取的文件
* CRect rect - 設置的矩形區
* COLORREF col - 填充的顏色
*
* 返回值:
* 無返回值
*
* 說明:
* 該函數用指定的顏色填充指定的圓形區域
*
*************************************************************************/
void CDIB::SetCircleColor(HDIB hDIB, CRect rect, COLORREF col)
{
// 循環變量
LONG i;
LONG j;
// 指向DIB的指針
LPBYTE lpDIB;
// 指向DIB象素指針
LPBYTE lpDIBBits;
// 鎖定DIB
lpDIB = (LPBYTE) ::GlobalLock((HGLOBAL) hDIB);
// 找到DIB圖像象素起始位置
lpDIBBits = FindDIBBits(lpDIB);
// DIB的寬度
LONG lWidth = DIBWidth(lpDIB);
// DIB的高度
LONG lHeight = DIBHeight(lpDIB);
// 計算圖像每行的字節數
LONG lLineBytes = WIDTHBYTES(lWidth * 24);
// 中間變量
int cx, cy, dr;
// 對圓形區域進行顏色填充
for (i = lHeight - rect.bottom; i < lHeight - rect.top; i++)
{
for (j = rect.left; j < rect.right; j ++)
{
cx = abs(j - rect.left - 8);
cy = abs(i - lHeight + rect.bottom - 8);
dr = cx * cx + cy * cy;
if (dr > 64 || i < 0 || i > lHeight || j < 0 || j > lWidth)
continue;
*(unsigned char *)(lpDIBBits + lLineBytes * i + j * 3) = GetBValue(col);
*(unsigned char *)(lpDIBBits + lLineBytes * i + j * 3 + 1) = GetGValue(col);
*(unsigned char *)(lpDIBBits + lLineBytes * i + j * 3 + 2) = GetRValue(col);
}
}
// 解除鎖定
::GlobalUnlock((HGLOBAL) hDIB);
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -