简易的灰度处理
????? 近期在進(jìn)行自繪控件的開發(fā)時(shí),時(shí)常用到灰度圖像。譬如真彩色工具條中的Disable狀態(tài)的圖標(biāo),譬如真彩菜單Disable狀態(tài)的圖標(biāo)等。照常來說,可以讓控件的使用者去制作相應(yīng)的圖標(biāo)。然而,為了讓控件的使用者在使用控件時(shí)盡量簡(jiǎn)單,一個(gè)比較好的辦法是在程序中生成Disable狀態(tài)的圖標(biāo)。本文提供了一個(gè)簡(jiǎn)單的封裝類CGrayBitmap,使用它的靜態(tài)方法DoGray可以根據(jù)一個(gè)常規(guī)圖片生成它的灰度圖。
????? 原創(chuàng)文章,轉(zhuǎn)帖請(qǐng)注明出處:blog.csdn.net/sjdev
?????
要對(duì)圖像進(jìn)行灰度處理,首先需要獲取到圖像的數(shù)據(jù)。GetBitmapBits和GetDIBits都可以得到位圖的數(shù)據(jù)。GetBitmapBits用于獲取設(shè)備獨(dú)立位圖的數(shù)據(jù),GetDIBits用于獲取兼容位圖的數(shù)據(jù)。MSDN提示說GetBitmapBits只是為了兼容16位Windows而提供的,所以推薦使用GetDIBits。另外GetPixel也可以獲取位圖數(shù)據(jù),不過在進(jìn)行灰度處理時(shí)不建議使用,因?yàn)樗俣忍?/span>(在某些特殊情況下,GetPixel還是很有用的)。
首先看看GetDIBits函數(shù)的定義吧:
int GetDIBits(HDC hdc, HBITMAP hbmp, UINT uStartScan, UINT uScanLines, LPVOID lpvBits, LPBITMAPINFO lpbi, UINT uUsage);
注意,GetDIBits的第二個(gè)參數(shù)hbmp必須為兼容位圖;lpvBits用于接收位圖數(shù)據(jù),如果該參數(shù)為空,函數(shù)調(diào)用將填充lpbi的相應(yīng)參數(shù);lpbi參數(shù)表示指向BITMAPINFO結(jié)構(gòu)的指針,它指定了設(shè)備無關(guān)位圖的數(shù)據(jù)結(jié)構(gòu);uUsage用于指定BITMAPINFO結(jié)構(gòu)中bmpColors成員的數(shù)據(jù)格式,這里咱們使用DIB_RGB_COLORS,它表示顏色表由RGB三個(gè)值直接構(gòu)成(另外一個(gè)參數(shù)DIB_PAL_COLORS表示使用調(diào)色板)。
來看一下使用GetDIBits獲取位圖數(shù)據(jù)的代碼: // 獲取對(duì)象信息BITMAP bm; if (!::GetObject(hSrcBitmap, sizeof(BITMAP), (LPBYTE)&bm))return NULL;// 定義位圖信息BITMAPINFO bi;bi.bmiHeader.biSize = sizeof(bi.bmiHeader);bi.bmiHeader.biWidth = bm.bmWidth;bi.bmiHeader.biHeight = -bm.bmHeight;bi.bmiHeader.biPlanes = 1;bi.bmiHeader.biBitCount = 32; bi.bmiHeader.biCompression = BI_RGB; bi.bmiHeader.biSizeImage = bm.bmWidth * 4 * bm.bmHeight; // 32 bitbi.bmiHeader.biClrUsed = 0;bi.bmiHeader.biClrImportant = 0;// 獲取位圖數(shù)據(jù)HDC hdc = GetDC(NULL);BYTE* pBits = (BYTE*)new BYTE[bi.bmiHeader.biSizeImage];::ZeroMemory(pBits, bi.bmiHeader.biSizeImage);if (!::GetDIBits(hdc, hSrcBitmap, 0, bm.bmHeight, pBits, &bi, DIB_RGB_COLORS)){delete pBits;pBits = NULL;}
得到數(shù)據(jù)之后,就可以對(duì)于數(shù)據(jù)進(jìn)行處理了。由于我們得到的是RGB數(shù)據(jù),為了處理方便,定義了一個(gè)RGBX結(jié)構(gòu)。灰度算法比較多,這里使用了常用的加權(quán)法。
來看一下處理數(shù)據(jù)的代碼: // 對(duì)位圖數(shù)據(jù)進(jìn)行處理RGBX* pSrc = (RGBX*)pBits;RGBX* pDest = (RGBX*)new BYTE[bi.bmiHeader.biSizeImage];::ZeroMemory(pDest, bi.bmiHeader.biSizeImage);for (LONG i = 0; i < bm.bmWidth; i++) { for (LONG j = 0; j < bm.bmHeight; j++) { RGBX* pRGBSrc = &pSrc[j * bm.bmWidth + i];RGBX* pRGBDest = &pDest[j * bm.bmWidth + i];*pRGBDest = pRGBSrc->Gray();} }
將數(shù)據(jù)處理完之后,我們需要?jiǎng)?chuàng)建一個(gè)新的位圖并給它設(shè)置位圖數(shù)據(jù),這樣,新的位圖就生成了。注意SetDIBits參數(shù)中指定的位圖,必須是兼容位圖,所以程序中采用CreateCompatibleBitmap而不是CreateBitmap函數(shù)來創(chuàng)建位圖。代碼如下: // 創(chuàng)建新位圖,設(shè)置位圖數(shù)據(jù)HBITMAP hGray = ::CreateCompatibleBitmap(hdc, bm.bmWidth, bm.bmHeight);::SetDIBits(hdc, hGray, 0, bm.bmHeight, pDest, &bi, DIB_RGB_COLORS);
附件:
CGrayBitmap類的定義如下:
?#pragma once/// // CGrayBitmap class CGrayBitmap { /// // RGBX #pragma pack(push) #pragma pack(1)typedef struct tagRGBX{public: tagRGBX(BYTE red, BYTE green, BYTE blue) { btRed = red; btBlue = blue; btGreen = green; btUnused = 0; }BYTE btBlue;BYTE btGreen;BYTE btRed;protected:BYTE btUnused;public:tagRGBX Gray() { int r = (int)btRed * 3;int g = (int)btGreen * 6;int b = (int)btBlue;BYTE btGray = (BYTE)((r + g + b) / 10);return RGBX(btGray, btGray, btGray);}}RGBX;#pragma pack(pop) private:CGrayBitmap(){} public: static HBITMAP DoGray(const HBITMAP hSrcBitmap) { ASSERT(hSrcBitmap != NULL);// 獲取對(duì)象信息BITMAP bm; if (!::GetObject(hSrcBitmap, sizeof(BITMAP), (LPBYTE)&bm))return NULL;// 定義位圖信息BITMAPINFO bi;bi.bmiHeader.biSize = sizeof(bi.bmiHeader);bi.bmiHeader.biWidth = bm.bmWidth;bi.bmiHeader.biHeight = -bm.bmHeight;bi.bmiHeader.biPlanes = 1;bi.bmiHeader.biBitCount = 32; bi.bmiHeader.biCompression = BI_RGB; bi.bmiHeader.biSizeImage = bm.bmWidth * 4 * bm.bmHeight; // 32 bitbi.bmiHeader.biClrUsed = 0;bi.bmiHeader.biClrImportant = 0;// 獲取位圖數(shù)據(jù)HDC hdc = GetDC(NULL);BYTE* pBits = (BYTE*)new BYTE[bi.bmiHeader.biSizeImage];::ZeroMemory(pBits, bi.bmiHeader.biSizeImage);if (!::GetDIBits(hdc, hSrcBitmap, 0, bm.bmHeight, pBits, &bi, DIB_RGB_COLORS)){delete pBits;pBits = NULL;}// 對(duì)位圖數(shù)據(jù)進(jìn)行處理RGBX* pSrc = (RGBX*)pBits;RGBX* pDest = (RGBX*)new BYTE[bi.bmiHeader.biSizeImage];::ZeroMemory(pDest, bi.bmiHeader.biSizeImage);for (LONG i = 0; i < bm.bmWidth; i++) { for (LONG j = 0; j < bm.bmHeight; j++) { RGBX* pRGBSrc = &pSrc[j * bm.bmWidth + i];RGBX* pRGBDest = &pDest[j * bm.bmWidth + i];*pRGBDest = pRGBSrc->Gray();} } // 創(chuàng)建新位圖,設(shè)置位圖數(shù)據(jù)HBITMAP hGray = ::CreateCompatibleBitmap(hdc, bm.bmWidth, bm.bmHeight);::SetDIBits(hdc, hGray, 0, bm.bmHeight, pDest, &bi, DIB_RGB_COLORS);// 釋放資源delete[] pBits;pBits = NULL;delete[] pDest; pDest = NULL;::ReleaseDC(NULL,hdc); return hGray;} };
?
?
總結(jié)
- 上一篇: 求丑数
- 下一篇: 计算机考研400分以上,考研400分无缘