1. 程式人生 > >利用GDI+處理圖像的色彩

利用GDI+處理圖像的色彩

擴展 ras 加權 bit urn alpha codec malloc status

首先先介紹一下ColorMatrix結構體:表示顏色的變換關系,定義如下:

typedef struct {

  REAL m[5][5];

} ColorMatrix;

ColorMatrix結構體一般和ImageAttribute類配合使用,使用的方式是先調用ImageAttibute::SetColorMatrix,運用該顏色變化矩陣,然後在繪制函數中將ImageAttribute對象作為DrawImage函數參數。以下的圖像色彩變換都會用到這個結構體。

一、改變圖像的透明度:只需要縮放Alpha分量就能到達效果。

int GetEncoderClsid(const WCHAR* format, CLSID* pClisd); // 獲取對應編碼器的CLSID

int CMyDlg::GetEncoderClsid(const WCHAR* format, CLSID* pClisd) // 獲取對應編碼器的CLSID
{
  UINT num = 0; // 圖像編碼器的數量
  UINT size = 0; // 圖像編碼器數組的字節數

  Gdiplus::ImageCodecInfo* pImageCodecInfo = NULL;
  GetImageEncodersSize(&num, &size);
  if (size == 0)
  return -1;
  pImageCodecInfo = (Gdiplus::ImageCodecInfo*)(malloc(size));

  GetImageEncoders(num, size, pImageCodecInfo);
  for(UINT j = 0;j<num;++j)
  {
    if (wcscmp(pImageCodecInfo[j].MimeType, format) == 0)
    {
      *pClisd = pImageCodecInfo[j].Clsid;
      free(pImageCodecInfo);
      return j;
    }
  }
  free(pImageCodecInfo);
  return -1;
}

/**********************************************************************************
* 作用:改變指定圖像的透明度,並將新圖像按照指定的圖像格式和路徑保存
* 參數:imagePath 為原圖路徑
* alpha 為分量縮放系數
* savePath 為用於保存處理後圖像的路徑
* 返回值: 轉換是否成功
**********************************************************************************/
BOOL ChangeImageAlpha(const CString& imagePath, REAL alpha, const CString& savePath);

BOOL CMyGDIDlg::ChangeImageAlpha(const CString& imagePath, REAL alpha, const CString& savePath)
{
  Bitmap bitmap(imagePath);
  if (bitmap.GetLastStatus() != Ok)
  return false;

  int nWidth = bitmap.GetWidth();
  int nHeight = bitmap.GetHeight();

  // 構建新圖像對象
  Bitmap image(nWidth, nHeight);
  Rect rect(0, 0, nWidth, nHeight);
  // 利用新圖像對象繪制
  Graphics graph(&image);

  // 構建顏色變化矩陣
  ColorMatrix colorMatrix = {
  1, 0, 0, 0, 0,
  0, 1, 0, 0, 0,
  0, 0, 1, 0, 0,
  0, 0, 0, alpha, 0,
  0, 0, 0, 0, 1
  };

  ImageAttributes imageAttr;
  imageAttr.SetColorMatrix(&colorMatrix);

  // 運用顏色變換矩陣繪制新圖像
  graph.DrawImage(&bitmap, rect, 0, 0, nWidth, nHeight, UnitPixel, &imageAttr);

  CLSID encoderClsid; // 文件編碼器的CLSID
  CString strExt = savePath.Right(3);
  strExt.MakeLower();
  // 根據擴展名獲得不同的CLSID
  if (strExt == _T("png"))
    GetEncoderClsid(_T("image/png"), &encoderClsid);
  else if (strExt == _T("jpg"))
    GetEncoderClsid(_T("image/jpg"), &encoderClsid);
  else
    GetEncoderClsid(_T("image/bmp"), &encoderClsid);

  if (image.Save(savePath, &encoderClsid, NULL) == Ok)
    return true;
  else
    return false;
}

調用: ChangeImageAlpha(_T("E:\\素材\\jpg\\1.jpg"), 0.5, _T("D:\\1.png"));

二、將圖像轉換為灰度圖:原理就是使圖中紅、綠、藍3個分量值相等。一般有3中方式:

(1)平均值法:使每個像素的三原色值等於紅、綠、藍3分量的平均值

  R = G = B = (R + G +B) / 3

(2)最大值法:每個像素的三原色等於紅、綠、藍3分量的最大值

  R = G = B = max(R, G, B)

(3)加權平均值法:給予紅、綠、藍3分量不同的權值然後相加

  R = G = B = WrR + WgG + WbB

  人眼對於三原色的敏感度從高到底分別是綠、紅、藍,所以三原色權值取值關系應該是 Wg > Wr > Wb。

  依據YUV顏色空間可知當 R = G = B = 0.299R + 0.587 + 0.114B時能夠的到最合理的灰度圖。

  算法與前文類似,在這裏只需修改一下顏色變化矩陣即可:

  // 構建顏色變化矩陣

  ColorMatrix colorMatrix = {
    0.299f, 0.299f, 0.299f, 0, 0,
    0.587f, 0.587f, 0.587f, 0, 0,
    0.114f, 0.114f, 0.114f, 0, 0,
    0, 0, 0, 1, 0,
    0, 0, 0, 0, 1
  };

三、改變圖像的亮度:是通過改變紅、綠、藍顏色分量的增量來實現的。公式如下:  

  // brightness 為亮度變化量

  REAL f = brightness / 255.0f;
  // 構建顏色變化矩陣
  ColorMatrix colorMatrix = {
    1, 0, 0, 0, 0,
    0, 1, 0, 0, 0,
    0, 0, 1, 0, 0,
    0, 0, 0, 1, 0,
    f, f, f, 0, 1
  };

四、改變圖像的對比度:一般來說對比度越大,圖像越清晰醒目,色彩也越鮮明艷麗;而對比度越小,則會讓圖畫顯得比較灰暗。

  圖像的對比度變化公式如下:其中f為對比度,默認為1.

  Rt = 128 + (R - 128)f

  Gt = 128 + (G -128)f

  Bt = 128+ (B - 128)f

  REAL f = 0.0f;
  if (contrast >= 0)
    f = (contrast + 10.0f) / 10.0f;
  else
    f = (255 + contrast) / 255.0f;
  // 構建顏色變化矩陣
  ColorMatrix colorMatrix = {
    f, 0, 0, 0, 0,
    0, f, 0, 0, 0,
    0, 0, f, 0, 0,
    0, 0, 0, 1, 0,
    0.5f*(1-f), 0.5f*(1 - f), 0.5f*(1 - f), 0, 1
  };

  

利用GDI+處理圖像的色彩