解説
コンボリュート法によるシャープ処理。あるピクセルの周囲に任意の負の値を乗算、中心に-8 倍した値を乗算した値に1を加算した合計値を新しい色値とする。ここでは下のような3行3列の処理パラメータのテーブルを用意してシャープ処理を実行してい る。このパラメータの値を変えればシャープ以外にもエッジ検出処理やエンボス処理などさまざま な画像処理を行える。
| -x | -x | -x |
| -x | 8x+1 | -x |
| -x | -x | -x |
実行例

ソースコード
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;
int pnOperate[9];
int nStrength;
//シャープ処理パラメータ
nStrength = 10;
pnOperate[0] = -1 * nStrength;
pnOperate[1] = -1 * nStrength;
pnOperate[2] = -1 * nStrength;
pnOperate[3] = -1 * nStrength;
pnOperate[4] = 8 * nStrength + 100;
pnOperate[5] = -1 * nStrength;
pnOperate[6] = -1 * nStrength;
pnOperate[7] = -1 * nStrength;
pnOperate[8] = -1 * nStrength;
{
int i;
long pnRefPos[9];
int nTmpR;
int nTmpG;
int nTmpB;
int nDiv;
int nStride;
int nPixelCount;
RGBTRIPLE* prgbTmp;
nDiv = 0;
for(i = 0; i < 9; i++)
nDiv += pnOperate[i];
if(nDiv < 0)
nDiv *= -1;
nStride = bitmapData.Stride / sizeof(RGBTRIPLE);
nPixelCount = nStride * pImage->GetHeight();
prgbTmp = new RGBTRIPLE[nPixelCount];
for(y = 1; y < pImage->GetHeight() - 1; y++)
{
nPos = y * nStride;
for(x = 1; x < pImage->GetWidth() - 1; x++, nPos++)
{
//あるピクセルの上下左右のピクセルオフセット計算
//いちいち計算するのは効率が悪いがソースコードは見やすい?
pnRefPos[0] = nPos - nStride - 1;
pnRefPos[1] = pnRefPos[0] + 1;
pnRefPos[2] = pnRefPos[0] + 2;
pnRefPos[3] = nPos - 1;
pnRefPos[4] = nPos;
pnRefPos[5] = nPos + 1;
pnRefPos[6] = nPos + nStride - 1;
pnRefPos[7] = pnRefPos[6] + 1;
pnRefPos[8] = pnRefPos[6] + 2;
//テーブルの値を使って計算
nTmpR = 0;
nTmpG = 0;
nTmpB = 0;
for(i = 0; i < 9; i++)
{
if(pnRefPos[i] < 0 || pnRefPos[i] >= nPixelCount)
continue;
nTmpR += pTmp[pnRefPos[i]].rgbtRed * pnOperate[i];
nTmpG += pTmp[pnRefPos[i]].rgbtGreen* pnOperate[i];
nTmpB += pTmp[pnRefPos[i]].rgbtBlue * pnOperate[i];
}
//平均値を求めるために除算
if(nDiv != 1 && nDiv != 0)
{
nTmpR /= nDiv;
nTmpG /= nDiv;
nTmpB /= nDiv;
}
//色ビット数を超えないように制限
nTmpR = (nTmpR < 0) ? 0 : nTmpR;
nTmpR = (nTmpR > 255) ? 255 : nTmpR;
nTmpG = (nTmpG < 0) ? 0 : nTmpG;
nTmpG = (nTmpG > 255) ? 255 : nTmpG;
nTmpB = (nTmpB < 0) ? 0 : nTmpB;
nTmpB = (nTmpB > 255) ? 255 : nTmpB;
prgbTmp[nPos].rgbtBlue = (BYTE)nTmpB;
prgbTmp[nPos].rgbtGreen = (BYTE)nTmpG;
prgbTmp[nPos].rgbtRed = (BYTE)nTmpR;
}
}
memcpy(pTmp,prgbTmp,sizeof(RGBTRIPLE) * nPixelCount);
delete prgbTmp;
}
pImage->UnlockBits(&bitmapData);
※ソースコード中に既知のバグというかミスコーディングがあります。nStrideを用意
していますがこれが諸悪の原因です。画像にどんな変化が加わるかを見るだけのテスト用途のため修正
はしていません。
