?? dibimage.cpp
字號:
case 8:
return 256;
break;
default:
return 0;
break;
}
}
/*************************************************************************
* 函數名稱:
* CopyHandle()
* 參數:
* HGLOBAL h - 要復制的內存區域
* 返回值:
* HGLOBAL - 復制后的新內存區域
* 說明:
* 該函數復制指定的內存區域。返回復制后的新內存區域,出錯時返回0。
************************************************************************/
HGLOBAL CDibImage::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對象保存到指定的CFile中。該CFile由調用程序打開和關閉。
*************************************************************************/
BOOL CDibImage::SaveDIB(HDIB hDib, CFile& file)
{
BITMAPFILEHEADER bmfHdr; // Bitmap文件頭
LPBITMAPINFOHEADER lpBI; // 指向BITMAPINFOHEADER的指針
DWORD dwDIBSize; // DIB大小
if (hDib == NULL)
{
return FALSE;
}
// 讀取BITMAPINFO結構,并鎖定
lpBI = (LPBITMAPINFOHEADER) ::GlobalLock((HGLOBAL) hDib);
if (lpBI == NULL)
{
return FALSE;
}
// 判斷是否是WIN3.0 DIB
if (!IS_WIN30_DIB(lpBI))
{
// 不支持其它類型的DIB保存
::GlobalUnlock((HGLOBAL) hDib);
return FALSE;
}
////////////////////////////////////////////////////////////////////////
// 填充文件頭///////////////////////////////////////////////////////////
bmfHdr.bfType = DIB_HEADER_MARKER; // 文件類型"BM"
// 計算DIB大小時,最簡單的方法是調用GlobalSize()函數。但是全局內存大小并
// 不是DIB真正的大小,它總是多幾個字節。這樣就需要計算一下DIB的真實大小。
// 文件頭大小+顏色表大小
// (BITMAPINFOHEADER和BITMAPCOREHEADER結構的第一個DWORD都是該結構的大小)
dwDIBSize = *(LPDWORD)lpBI + PaletteSize((LPSTR)lpBI);
// 計算圖像大小
if ((lpBI->biCompression == BI_RLE8) || (lpBI->biCompression == BI_RLE4))
{
// 對于RLE位圖,沒法計算大小,只能信任biSizeImage內的值
dwDIBSize += lpBI->biSizeImage;
}
else
{
DWORD dwBmBitsSize; // 象素的大小
dwBmBitsSize = WIDTHBYTES((lpBI->biWidth)*((DWORD)lpBI->biBitCount))
* lpBI->biHeight; // 大小為Width * Height
dwDIBSize += dwBmBitsSize; // 計算出DIB真正的大小
// 更新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((LPSTR)lpBI);
/////////////////////////////////////////////////////////////////////////
// 嘗試寫文件////////////////////////////////////////////////////////////
TRY
{
file.Write((LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER)); // 寫文件頭
file.WriteHuge(lpBI, dwDIBSize); // 寫DIB頭和象素
}
CATCH (CFileException, e)
{
::GlobalUnlock((HGLOBAL) hDib);
THROW_LAST();
}
END_CATCH
::GlobalUnlock((HGLOBAL) hDib);
return TRUE;
}
/*************************************************************************
* 函數名稱:
* ReadDIBFile()
* 參數:
* CFile& file - 要讀取得文件文件CFile
* 返回值:
* HDIB - 成功返回DIB的句柄,否則返回NULL。
* 說明:
* 該函數將指定的文件中的DIB對象讀到指定的內存區域中。除BITMAPFILEHEADER
* 外的內容都將被讀入內存。
*************************************************************************/
HDIB CDibImage::ReadDIBFile(CFile& file)
{
BITMAPFILEHEADER bmfHeader;
HDIB hDIB;
LPSTR pDIB;
DWORD dwBitsSize;
dwBitsSize = file.GetLength(); // 獲取DIB(文件)長度(字節)
// 嘗試讀取DIB文件頭
if (file.Read((LPSTR)&bmfHeader, sizeof(bmfHeader)) != sizeof(bmfHeader))
{
return NULL;
}
// 判斷是否是DIB對象,檢查頭兩個字節是否是"BM"
if (bmfHeader.bfType != DIB_HEADER_MARKER)
{
return NULL;
}
// 為DIB分配內存
hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwBitsSize);
if (hDIB == 0)
{
return NULL;
}
pDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);
if (file.ReadHuge(pDIB, dwBitsSize - sizeof(BITMAPFILEHEADER)) !=
dwBitsSize - sizeof(BITMAPFILEHEADER) ) // 讀象素
{
::GlobalUnlock((HGLOBAL) hDIB);
::GlobalFree((HGLOBAL) hDIB);
return NULL;
}
::GlobalUnlock((HGLOBAL) hDIB);
return hDIB;
}
//////////////////////////////////////////////////////////////////////
// 圖像點運算函數
//////////////////////////////////////////////////////////////////////
/*************************************************************************
* 函數名稱:
* LinerTrans()
* 參數:
* LPSTR lpDIBBits - 指向源DIB圖像指針
* LONG lWidth - 源圖像寬度(象素數)
* LONG lHeight - 源圖像高度(象素數)
* FLOAT fA - 線性變換的斜率
* FLOAT fB - 線性變換的截距
* 返回值:
* BOOL - 成功返回TRUE,否則返回FALSE。
* 說明:
* 該函數用來對圖像進行灰度的線性變換操作。
************************************************************************/
BOOL CDibImage::LinerTrans(LPSTR lpDIBBits, LONG lWidth, LONG lHeight,
FLOAT fA, FLOAT fB)
{
unsigned char* lpSrc; // 指向源圖像的指針
LONG i; // 循環變量
LONG j;
LONG lLineBytes; // 圖像每行的字節數
FLOAT fTemp; // 中間變量
lLineBytes = WIDTHBYTES(lWidth * 8); // 計算圖像每行的字節數
for(i = 0; i < lHeight; i++) // 每行
{
for(j = 0; j < lWidth; j++) // 每列
{
// 指向DIB第i行,第j個象素的指針
lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;
fTemp = fA * (*lpSrc) + fB; // 線性變換
if (fTemp > 255) // 判斷是否超出范圍
{
*lpSrc = 255;
}
else if (fTemp < 0)
{
*lpSrc = 0;
}
else
{
*lpSrc = (unsigned char) (fTemp + 0.5); // 四舍五入
}
}
}
return TRUE;
}
/*************************************************************************
* 函數名稱:
* ThresholdTrans()
* 參數:
* LPSTR lpDIBBits - 指向源DIB圖像指針
* LONG lWidth - 源圖像寬度(象素數)
* LONG lHeight - 源圖像高度(象素數)
* BYTE bThre - 閾值
* 返回值:
* BOOL - 成功返回TRUE,否則返回FALSE。
* 說明:
* 該函數用來對圖像進行閾值變換。對于灰度值小于閾值的象素直接設置
* 灰度值為0;灰度值大于閾值的象素直接設置為255。
************************************************************************/
BOOL CDibImage::ThresholdTrans(LPSTR lpDIBBits, LONG lWidth, LONG lHeight, BYTE bThre)
{
unsigned char* lpSrc; // 指向源圖像的指針
LONG i; // 循環變量
LONG j;
LONG lLineBytes; // 圖像每行的字節數
lLineBytes = WIDTHBYTES(lWidth * 8);// 計算圖像每行的字節數
for(i = 0; i < lHeight; i++) // 每行
{
for(j = 0; j < lWidth; j++) // 每列
{
// 指向DIB第i行,第j個象素的指針
lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;
if ((*lpSrc) < bThre) // 判斷是否小于閾值
{
*lpSrc = 0;
}
else
{
*lpSrc = 255;
}
}
}
return TRUE;
}
/*************************************************************************
* 函數名稱:
* WindowTrans()
* 參數:
* LPSTR lpDIBBits - 指向源DIB圖像指針
* LONG lWidth - 源圖像寬度(象素數)
* LONG lHeight - 源圖像高度(象素數)
* BYTE bLow - 窗口下限
* BYTE bUp - 窗口上限
* 返回值:
* BOOL - 成功返回TRUE,否則返回FALSE。
* 說明:
* 該函數用來對圖像進行窗口變換。只有在窗口范圍內的灰度保持不變,
* 小于下限的象素直接設置灰度值為0;大于上限的象素直接設置灰度值為255。
************************************************************************/
BOOL CDibImage::WindowTrans(LPSTR lpDIBBits, LONG lWidth, LONG lHeight,
BYTE bLow, BYTE bUp)
{
unsigned char* lpSrc; // 指向源圖像的指針
LONG i; // 循環變量
LONG j;
LONG lLineBytes; // 圖像每行的字節數
lLineBytes = WIDTHBYTES(lWidth * 8);// 計算圖像每行的字節數
for(i = 0; i < lHeight; i++) // 每行
{
for(j = 0; j < lWidth; j++) // 每列
{
// 指向DIB第i行,第j個象素的指針
lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;
if ((*lpSrc) < bLow) // 判斷是否超出范圍
{
*lpSrc = 0;
}
else if ((*lpSrc) > bUp)
{
*lpSrc = 255;
}
}
}
return TRUE;
}
/*************************************************************************
* 函數名稱:
* GrayStretch()
* 參數:
* LPSTR lpDIBBits - 指向源DIB圖像指針
* LONG lWidth - 源圖像寬度(象素數)
* LONG lHeight - 源圖像高度(象素數)
* BYTE bX1 - 灰度拉伸第一個點的X坐標
* BYTE bY1 - 灰度拉伸第一個點的Y坐標
* BYTE bX2 - 灰度拉伸第二個點的X坐標
* BYTE bY2 - 灰度拉伸第二個點的Y坐標
* 返回值:
* BOOL - 成功返回TRUE,否則返回FALSE。
* 說明:
* 該函數用來對圖像進行灰度拉伸。
************************************************************************/
BOOL CDibImage::GrayStretch(LPSTR lpDIBBits, LONG lWidth, LONG lHeight,
BYTE bX1, BYTE bY1, BYTE bX2, BYTE bY2)
{
unsigned char* lpSrc; // 指向源圖像的指針
LONG i; // 循環變量
LONG j;
BYTE bMap[256]; // 灰度映射表
LONG lLineBytes; // 圖像每行的字節數
lLineBytes = WIDTHBYTES(lWidth * 8);// 計算圖像每行的字節數
// 計算灰度映射表
for (i = 0; i <= bX1; i++)
{
if (bX1 > 0) // 判斷bX1是否大于0(防止分母為0)
{
bMap[i] = (BYTE) bY1 * i / bX1;
}
else
{
bMap[i] = 0;
}
}
for (; i <= bX2; i++)
{
if (bX2 != bX1) // 判斷bX1是否等于bX2(防止分母為0)
{
bMap[i] = bY1 + (BYTE) ((bY2 - bY1) * (i - bX1) / (bX2 - bX1));
}
else
{
bMap[i] = bY1;
}
}
for (; i < 256; i++)
{
if (bX2 != 255) // 判斷bX2是否等于255(防止分母為0)
{
bMap[i] = bY2 + (BYTE) ((255 - bY2) * (i - bX2) / (255 - bX2));
}
else
{
bMap[i] = 255;
}
}
for(i = 0; i < lHeight; i++) // 每行
{
for(j = 0; j < lWidth; j++) // 每列
{
// 指向DIB第i行,第j個象素的指針
lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;
// 計算新的灰度值
*lpSrc = bMap[*lpSrc];
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -