簡單的實現方案資料格式:YUV參考連結1:Processing in the 8-bit YUV Color Space參考連結2:關於YUV映像的亮度和對比的調整演算法參考連結2中採用CxImage(關於CxImage,參考:轉貼 CxImage類庫使用說明 - 走在路上 - 部落格頻道 - CSDN.NET)庫提供的處理方法,採用查表法處理效率很高。粘貼部分處理代碼
CxImage\ximadsp.cpp
/** * Changes the brightness and the contrast of the image. * \param brightness: can be from -255 to 255, if brightness is negative, the image becomes dark. * \param contrast: can be from -100 to 100, the neutral value is 0. * \return true if everything is ok */bool CxImage ::Light (long brightness , long contrast ){ if (! pDib) return false; float c=(100 + contrast)/100.0f; brightness+=128; BYTE cTable[256]; //<nipper> for ( int i=0; i<256; i++) { cTable[ i] = ( BYTE) max(0, min(255,( int)(( i-128)* c + brightness + 0.5f))); } return Lut( cTable);}/** * Changes the saturation of the image. * \param saturation: can be from -100 to 100, positive values increase the saturation. * \param colorspace: can be 1 (HSL) or 2 (YUV). * \return true if everything is ok */bool CxImage ::Saturate (const long saturation , const long colorspace ){...for (int i =0;i <256;i ++) { cTable[ i] = (BYTE)max(0,min (255,(int )((i -128)*(100 + saturation)/100.0f + 128.5f)));}...}通過如下處理,就可以得到處理後映像了
// Y分量,在對映像亮度和對比進行調節後,通過查表 m_YTable獲得新的Y 值// pdst為轉換後的映像,pbufy為原映像的Y分量for ( int height=0; height< m_frameHeight; height ++){ for ( int width=0; width< m_frameWidth; width ++) { *pdst++ = cTable[*pbufy++]; }}
其他方案:
方案1. 基於Dirextx利用像素著色器實現映像的亮度,飽和度操作
參考連結:基於dirextx 利用像素著色器實現映像的亮度,飽和度,色相,對比,變灰,反相操作該文提供一個原始碼,編譯時間需要D3D相關的lib庫。該程式將對影像處理的細節交個了D3D,通過設定一個D3DXMATRIX結構體完成亮度飽和度等的操作。優點:通過D3D實現,圖片處理速度快效率高。缺點:需要瞭解D3D相關的知識,學習成本較大。
方案2. 使用DirectDraw色彩控制IDirectDrawColorControl參考連結:http://www.codingnow.com/directx6/dx6_dd11.htm#gamma參考連結:http://www.dpfiles.com/dpfileswiki/index.php?title=Tricks_of_the_Windows_Game_Programming_Gurus%2C_Chapter_7:_Advanced_DirectDraw_and_Bitmapped_Graphics原理與DirectX類似,因為我做的項目其2D映像渲染是使用DirectDraw實現的,很自然的想到了使用這個方法,但要非常注意的是,你的顯卡要能夠支援IDirectDrawColorControl,也就是說DirectDraw能夠提供相應capacity,很遺憾的是我的顯卡並不支援該特性,你可以用如下代碼測試是否該功能:
// initializes a direct draw struct#define DDRAW_INIT_STRUCT(ddstruct) { memset(&ddstruct,0,sizeof(ddstruct)); ddstruct.dwSize=sizeof(ddstruct); }// create IDirectDraw interface 7.0 object and test for errorif (FAILED(DirectDrawCreateEx(NULL, (void **)&lpdd, IID_IDirectDraw7, NULL))) return(0);DDCAPS hel_caps, hal_caps;// initialize the structuresDDRAW_INIT_STRUCT(hel_caps);DDRAW_INIT_STRUCT(hal_caps);if (FAILED(lpdd->GetCaps(&hal_caps, &hel_caps))) return(0);if (hal_caps.dwCaps2 & DDCAPS2_COLORCONTROLPRIMARY) OutputDebugString(_T("Supports primary surface contains color controls\n"));if (hal_caps.dwCaps2 & DDCAPS2_COLORCONTROLOVERLAY) OutputDebugString(_T("Supports overlay surface contains color controls\n"));if (hal_caps.dwCaps2 & DDCAPS2_PRIMARYGAMMA) OutputDebugString(_T("Supports loadable gamma ramps for the primary surface\n"));
同樣的,你需要對DirectDraw有必要的瞭解,如果是使用GDI來負責映像的繪製,那麼DirectX和DirectDraw的方案並不適合。
方案3 使用GDI+中的ColorMatrix
參考連結:
灰階、對比、亮度、飽和度基本影像處理源碼參考連結:GDI+ for VCL基礎 -- 顏色調整矩陣ColorMatrix詳解