解説
グレースケールを利用したコントラスト調節。画像をグレースケール化してそのヒストグラムを作成する。次にそのヒストグラム を累積して中間点の色値を算出する。併せてグレースケールの最小色値と最大色値も 取得しておく。そしてそれらの値を元に色値方向に2分割して新しい色値を決定する。
新しい色値は累積中間点までの色数に対して求まる1色ごとの"重み"を元の色値に乗 算することで決定する。
実行例

ソースコード
GDI+を利用した画像処理テストのスケルトンの 画像処理部分を以下のように変更する。
////////////////////////////
//画像処理
//
UINT x;
UINT y;
UINT nPos;
RGBTRIPLE* pTmp;
Gdiplus::BitmapData bitmapData;
pImage->LockBits(&Gdiplus::Rect(0,0,pImage->GetWidth(),pImage->GetHeight())
,Gdiplus::ImageLockModeRead | Gdiplus::ImageLockModeWrite,PixelFormat24bppRGB,&bitmapData);
pTmp = (RGBTRIPLE*)bitmapData.Scan0;
//コントラスト自動調節
{
/////////
//グレースケールヒストグラム作成
//
BYTE nGray;
ULONG pnHistgram[256];
ZeroMemory(pnHistgram,sizeof(ULONG) * 256);
nPos = 0;
for(y = 0; y < pImage->GetHeight(); y++)
{
for(x = 0; x < pImage->GetWidth(); x++, nPos++)
{
nGray = (BYTE)((77 * pTmp[nPos].rgbtRed + 150 * pTmp[nPos].rgbtGreen + 29 * pTmp[nPos].rgbtBlue) >> 8);
pnHistgram[nGray]++;
}
}
/////////
//ヒストグラムの累積中間点算出
//
ULONG nCount;
ULONG nHalfCount;
nHalfCount = (pImage->GetWidth() * pImage->GetHeight()) / 2;
nCount = 0;
for(y = 0; y < 256; y++)
{
nCount += pnHistgram[y];
if(nCount >= nHalfCount)
break;
}
nHalfCount = y;
/////////
//ヒストグラムの累積最小・最大点算出
//
int nMin;
int nMax;
for(y = 0; y < 256; y++)
{
if(pnHistgram[y] != 0)
break;
}
nMin = y;
for(y = 255; y >= 0; y--)
{
if(pnHistgram[y] != 0)
break;
}
nMax = y;
/////////
//自動調節
//
double dH;
double dL;
dH = 127.0 / (nMax - nHalfCount); //分母がゼロになる可能性あり
dL = 127.0 / (nHalfCount - nMin);
nPos = 0;
for(y = 0; y < pImage->GetHeight(); y++)
{
for(x = 0; x < pImage->GetWidth(); x++, nPos++)
{
pTmp[nPos].rgbtBlue = (pTmp[nPos].rgbtBlue < nHalfCount) ? (pTmp[nPos].rgbtBlue - nMin) * dL : (pTmp[nPos].rgbtBlue - nHalfCount - nMin+1) * dH + 128;
pTmp[nPos].rgbtGreen= (pTmp[nPos].rgbtGreen < nHalfCount) ? (pTmp[nPos].rgbtGreen - nMin) * dL : (pTmp[nPos].rgbtGreen- nHalfCount - nMin+1) * dH + 128;
pTmp[nPos].rgbtRed = (pTmp[nPos].rgbtRed < nHalfCount) ? (pTmp[nPos].rgbtRed - nMin) * dL : (pTmp[nPos].rgbtRed - nHalfCount - nMin+1) * dH + 128;
}
}
}
pImage->UnlockBits(&bitmapData);
