前に作成したコンボリューション関連関数を手直しして前回作成したGDI+用クラスから使えるように
した。
コンボリューションはソースコードが(パラメータの一覧があるおかげでで)無駄に長いので別クラス として宣言してそこから派生させる形で実装している。

以下のソースコードを「DnpImageConvolution.h」のファイル名で保存する。
前に作成した「DnpImage.h」に変更を加える。派生元クラスとしてCDnpImageConvolutionを入れ、 コンボリューション処理関連関数を追加する。。
コンボリューションはソースコードが(パラメータの一覧があるおかげでで)無駄に長いので別クラス として宣言してそこから派生させる形で実装している。
解説
実行例
画像処理として以下のコードでシャープ化を行った。_cImage2.Convolution(CDnpImageConvolution::CONV_SHARP01);

ソースコード
GDI+を利用した画像処理テストのスケルトン2を 元に拡張する。以下のソースコードを「DnpImageConvolution.h」のファイル名で保存する。
#pragma once
class CDnpImageConvolution
{
public:
enum CONVOLUTION_TYPE
{
CONV_DUMMY = 0,
CONV_EMBOSS01,
CONV_EMBOSS02,
CONV_EMBOSS03,
CONV_EMBOSS04,
CONV_EMBOSS05,
CONV_EMBOSS06,
CONV_EMBOSS07,
CONV_EMBOSS08,
CONV_EMBOSS09,
CONV_SOBEL01,
CONV_PREWITT01,
CONV_KIRSH01,
CONV_EDGE01,
CONV_EDGE02,
CONV_EDGE03,
CONV_EDGE04,
CONV_EDGE05,
CONV_EDGE06,
CONV_EDGE07,
CONV_EDGEENHANCE01,
CONV_AVRREMOVE01,
CONV_SHARP01,
CONV_SHARP02,
CONV_SHARP03,
CONV_SHARP04,
CONV_SOFT01,
CONV_SOFT02,
CONV_SOFT03,
CONV_SOFT04,
CONV_SOFT05,
CONV_SOFT06,
CONV_SOFT07,
CONV_SOFT08,
CONV_LAPLACIAN01,
CONV_LAPLACIAN02,
CONV_DUMMY_END
};
//
// コンボリューション処理パラメータの対称度チェック
//
//例えば下の2つのパラメータは"同じ処理を角度を変えて行うもの"
//と考えることができる(左を45度回転したものが右になるため)。
//この行列の場合、45度回転を8回繰り返すと元と同じ形になる。
//この関数はこの8回から1つ引いた"7"という値を返す。
//
// [ 1 ][ 1 ][ 1 ] [ 0 ][ 1 ][ 1 ]
// [ 0 ][ 0 ][ 0 ] [ 0 ][ 0 ][ 1 ]
// [ 0 ][ 0 ][ 0 ] [ 0 ][ 0 ][ 0 ]
//
UINT GetConvolutionRotateCount(int pnOperate[9])
{
int i;
int pnOperateCopy[9];
int nTmp;
memcpy(pnOperateCopy,pnOperate,sizeof(int) * 9);
for(i = 0; i < 8; i++)
{
nTmp = pnOperateCopy[8];
pnOperateCopy[8] = pnOperateCopy[7];
pnOperateCopy[7] = pnOperateCopy[6];
pnOperateCopy[6] = pnOperateCopy[5];
pnOperateCopy[5] = pnOperateCopy[3];
pnOperateCopy[3] = pnOperateCopy[2];
pnOperateCopy[2] = pnOperateCopy[1];
pnOperateCopy[1] = pnOperateCopy[0];
pnOperateCopy[0] = nTmp;
if(memcmp(pnOperate,pnOperateCopy,sizeof(int) * 9) == 0)
return i;
}
ATLASSERT(0);
return 8;
}
//
// コンボリューション処理パラメータの回転
//
//
//例えば下の2つのパラメータは"同じ処理を角度を変えて行うもの"
//と考えることができる(左を45度回転したものが右になるため)。
//この行列の場合、45度回転を8回繰り返すと元と同じ形になる。
//この関数は指定した回数だけ45度回転をする
//
// [ 1 ][ 1 ][ 1 ] [ 0 ][ 1 ][ 1 ]
// [ 0 ][ 0 ][ 0 ] [ 0 ][ 0 ][ 1 ]
// [ 0 ][ 0 ][ 0 ] [ 0 ][ 0 ][ 0 ]
//
bool GetConvolutionRotate(UINT nCount,int pnOperate[])
{
UINT i;
int nTmp;
nCount = nCount % 8;
for(i = 0; i < nCount; i++)
{
//forで何度も回転するのは効率が悪いが最大7回なので大したことはない
nTmp = pnOperate[8];
pnOperate[8] = pnOperate[7];
pnOperate[7] = pnOperate[6];
pnOperate[6] = pnOperate[5];
pnOperate[5] = pnOperate[3];
pnOperate[3] = pnOperate[2];
pnOperate[2] = pnOperate[1];
pnOperate[1] = pnOperate[0];
pnOperate[0] = nTmp;
}
return true;
}
bool GetConvolutionOperator(CONVOLUTION_TYPE enumType,int pnOperate[])
{
// int pnOperate[9];
//パラメータ参照元
// http://www.rebol.net/rebcode/demos/convolution-rc.r
//など
switch(enumType)
{
case CONV_DUMMY:
case CONV_DUMMY_END:
//ダミー処理パラメータ
pnOperate[0] = 0; //[ 0 ][ 0 ][ 0 ]
pnOperate[1] = 0; //[ 0 ][ 1 ][ 0 ]
pnOperate[2] = 0; //[ 0 ][ 0 ][ 0 ]
pnOperate[3] = 0;
pnOperate[4] = 1;
pnOperate[5] = 0;
pnOperate[6] = 0;
pnOperate[7] = 0;
pnOperate[8] = 0;
break;
case CONV_EMBOSS01:
//エンボス処理パラメータ1
pnOperate[0] = 0; //[ 0 ][ 0 ][ 0 ]
pnOperate[1] = 0; //[ 0 ][ 1 ][ 0 ]
pnOperate[2] = 0; //[ 0 ][ 0 ][ -8 ]
pnOperate[3] = 0;
pnOperate[4] = 1;
pnOperate[5] = 0;
pnOperate[6] = 0;
pnOperate[7] = 0;
pnOperate[8] = -1;
break;
case CONV_EMBOSS02:
//エンボス処理パラメータ2
pnOperate[0] = 2; //[ 2 ][ 0 ][ 0 ]
pnOperate[1] = 0; //[ 0 ][ -1 ][ 0 ]
pnOperate[2] = 0; //[ 0 ][ 0 ][ -1 ]
pnOperate[3] = 0;
pnOperate[4] = -1;
pnOperate[5] = 0;
pnOperate[6] = 0;
pnOperate[7] = 0;
pnOperate[8] = -1;
break;
case CONV_EMBOSS03:
//エンボス処理パラメータ3
pnOperate[0] = -2; //[ -2 ][ -1 ][ 0 ]
pnOperate[1] = -1; //[ -1 ][ 1 ][ 1 ]
pnOperate[2] = 0; //[ 0 ][ 1 ][ 2 ]
pnOperate[3] = -1;
pnOperate[4] = 1;
pnOperate[5] = 1;
pnOperate[6] = 0;
pnOperate[7] = 1;
pnOperate[8] = 2;
break;
case CONV_EMBOSS04:
//エンボス処理パラメータ4Laplascian
pnOperate[0] = -1; //[ -1 ][ 0 ][ -1 ]
pnOperate[1] = 0; //[ 0 ][ 4 ][ 0 ]
pnOperate[2] = -1; //[ -1 ][ 0 ][ -1 ]
pnOperate[3] = 0;
pnOperate[4] = 4;
pnOperate[5] = 0;
pnOperate[6] = -1;
pnOperate[7] = 0;
pnOperate[8] = -1;
break;
case CONV_EMBOSS05:
//エンボス処理パラメータ5全方向
case CONV_EDGE04:
//エッジ検出処理パラメータ4
pnOperate[0] = -1; //[ -1 ][ -1 ][ -1 ]
pnOperate[1] = -1; //[ -1 ][ 8 ][ -1 ]
pnOperate[2] = -1; //[ -1 ][ -1 ][ -1 ]
pnOperate[3] = -1;
pnOperate[4] = 8;
pnOperate[5] = -1;
pnOperate[6] = -1;
pnOperate[7] = -1;
pnOperate[8] = -1;
break;
case CONV_EMBOSS06:
//エンボス処理パラメータ6水平方向
pnOperate[0] = 0; //[ 0 ][ 0 ][ 0 ]
pnOperate[1] = 0; //[ -1 ][ 2 ][ -1 ]
pnOperate[2] = 0; //[ 0 ][ 0 ][ 0 ]
pnOperate[3] = -1;
pnOperate[4] = 2;
pnOperate[5] = -1;
pnOperate[6] = 0;
pnOperate[7] = 0;
pnOperate[8] = 0;
break;
case CONV_EMBOSS07:
//エンボス処理パラメータ8水平垂直
pnOperate[0] = 0; //[ 0 ][ -1 ][ 0 ]
pnOperate[1] = -1; //[ -1 ][ 4 ][ -1 ]
pnOperate[2] = 0; //[ 0 ][ -1 ][ 0 ]
pnOperate[3] = -1;
pnOperate[4] = 4;
pnOperate[5] = -1;
pnOperate[6] = 0;
pnOperate[7] = -1;
pnOperate[8] = 0;
break;
case CONV_EMBOSS08:
//エンボス処理パラメータ9Lossy
pnOperate[0] = 1; //[ 1 ][ -2 ][ 1 ]
pnOperate[1] = -2; //[ 1 ][ -2 ][ 4 ]
pnOperate[2] = 1; //[ -2 ][ -1 ][ -2 ]
pnOperate[3] = -2;
pnOperate[4] = 4;
pnOperate[5] = -2;
pnOperate[6] = -2;
pnOperate[7] = -1;
pnOperate[8] = -2;
break;
case CONV_EMBOSS09:
//エンボス処理パラメータ10
pnOperate[0] = -4; //[ -4 ][ -2 ][ 0 ]
pnOperate[1] = -2; //[ -2 ][ 2 ][ 2 ]
pnOperate[2] = 0; //[ 0 ][ 2 ][ 4 ]
pnOperate[3] = -2;
pnOperate[4] = 2;
pnOperate[5] = 2;
pnOperate[6] = 0;
pnOperate[7] = 2;
pnOperate[8] = 4;
break;
case CONV_SOBEL01:
//Sobel処理パラメータ水平
pnOperate[0] = 1; //[ 1 ][ 2 ][ 1 ]
pnOperate[1] = 2; //[ 0 ][ 0 ][ 0 ]
pnOperate[2] = 1; //[ -1 ][ -2 ][ -1 ]
pnOperate[3] = 0;
pnOperate[4] = 0;
pnOperate[5] = 0;
pnOperate[6] = -1;
pnOperate[7] = -2;
pnOperate[8] = -1;
break;
case CONV_PREWITT01:
//Prewitt処理パラメータ水平
pnOperate[0] = 1; //[ 1 ][ 1 ][ 1 ]
pnOperate[1] = 1; //[ 0 ][ 0 ][ 0 ]
pnOperate[2] = 1; //[ -1 ][ -1 ][ -1 ]
pnOperate[3] = 0;
pnOperate[4] = 0;
pnOperate[5] = 0;
pnOperate[6] = -1;
pnOperate[7] = -1;
pnOperate[8] = -1;
break;
case CONV_KIRSH01:
//Kirsh処理パラメータ水平
pnOperate[0] = 5; //[ 5 ][ 5 ][ 5 ]
pnOperate[1] = 5; //[ -3 ][ -3 ][ -3 ]
pnOperate[2] = 5; //[ -3 ][ -3 ][ -3 ]
pnOperate[3] = -3;
pnOperate[4] = -3;
pnOperate[5] = -3;
pnOperate[6] = -3;
pnOperate[7] = -3;
pnOperate[8] = -3;
break;
case CONV_EDGE01:
//エッジ検出処理パラメータ1
pnOperate[0] = 0; //[ 0 ][ 1 ][ 0 ]
pnOperate[1] = 1; //[ 1 ][ -4 ][ 1 ]
pnOperate[2] = 0; //[ 0 ][ 1 ][ 0 ]
pnOperate[3] = 1;
pnOperate[4] = -4;
pnOperate[5] = 1;
pnOperate[6] = 0;
pnOperate[7] = 1;
pnOperate[8] = 0;
break;
case CONV_EDGE02:
//エッジ検出処理パラメータ2
pnOperate[0] = -5; //[ -5 ][ 0 ][ 0 ]
pnOperate[1] = 0; //[ 0 ][ 0 ][ 0 ]
pnOperate[2] = 0; //[ 0 ][ 0 ][ -5 ]
pnOperate[3] = 0;
pnOperate[4] = 0;
pnOperate[5] = 0;
pnOperate[6] = 0;
pnOperate[7] = 0;
pnOperate[8] = -5;
break;
case CONV_EDGE03:
//エッジ検出処理パラメータ3
pnOperate[0] = -125; //[ -125 ][ -125 ][ -125 ]
pnOperate[1] = -125; //[ -125 ][ 1000 ][ -125 ]
pnOperate[2] = -125; //[ -125 ][ -125 ][ -125 ]
pnOperate[3] = -125;
pnOperate[4] = 1000;
pnOperate[5] = -125;
pnOperate[6] = -125;
pnOperate[7] = -125;
pnOperate[8] = -125;
break;
//case CONV_EDGE04:
// //エッジ検出処理パラメータ4
// break;
case CONV_EDGE05:
//エッジ検出処理パラメータ5
pnOperate[0] = -1; //[ -1 ][ -1 ][ -1 ]
pnOperate[1] = -1; //[ 2 ][ 2 ][ 2 ]
pnOperate[2] = -1; //[ -1 ][ -1 ][ -1 ]
pnOperate[3] = 2;
pnOperate[4] = 2;
pnOperate[5] = 2;
pnOperate[6] = -1;
pnOperate[7] = -1;
pnOperate[8] = -1;
break;
case CONV_EDGE06:
//エッジ検出処理パラメータ6
pnOperate[0] = -5; //[ -5 ][ -5 ][ -5 ]
pnOperate[1] = -5; //[ -5 ][ 39 ][ -5 ]
pnOperate[2] = -5; //[ -5 ][ -5 ][ -5 ]
pnOperate[3] = -5;
pnOperate[4] = 39;
pnOperate[5] = -5;
pnOperate[6] = -5;
pnOperate[7] = -5;
pnOperate[8] = -5;
break;
case CONV_EDGE07:
//エッジ検出処理パラメータ7
pnOperate[0] = 0; //[ 0 ][ 2 ][ 0 ]
pnOperate[1] = 0; //[ 2 ][ -8 ][ 2 ]
pnOperate[2] = 0; //[ 0 ][ 2 ][ 0 ]
pnOperate[3] = -1;
pnOperate[4] = 1;
pnOperate[5] = 0;
pnOperate[6] = 0;
pnOperate[7] = 0;
pnOperate[8] = 0;
break;
case CONV_EDGEENHANCE01:
//エッジ強調処理パラメータ
pnOperate[0] = 0; //[ 0 ][ 0 ][ 0 ]
pnOperate[1] = 0; //[ -1 ][ 1 ][ 0 ]
pnOperate[2] = 0; //[ 0 ][ 0 ][ 0 ]
pnOperate[3] = -1;
pnOperate[4] = 1;
pnOperate[5] = 0;
pnOperate[6] = 0;
pnOperate[7] = 0;
pnOperate[8] = 0;
break;
case CONV_AVRREMOVE01:
//平均削除処理パラメータ
pnOperate[0] = -1; //[ -1 ][ -1 ][ -1 ]
pnOperate[1] = -1; //[ -1 ][ 9 ][ -1 ]
pnOperate[2] = -1; //[ -1 ][ -1 ][ -1 ]
pnOperate[3] = -1;
pnOperate[4] = 9;
pnOperate[5] = -1;
pnOperate[6] = -1;
pnOperate[7] = -1;
pnOperate[8] = -1;
break;
case CONV_SHARP01:
//シャープ処理パラメータ1
pnOperate[0] = -1; //[ -1 ][ -1 ][ -1 ]
pnOperate[1] = -1; //[ -1 ][ 16 ][ -1 ]
pnOperate[2] = -1; //[ -1 ][ -1 ][ -1 ]
pnOperate[3] = -1;
pnOperate[4] = 16;
pnOperate[5] = -1;
pnOperate[6] = -1;
pnOperate[7] = -1;
pnOperate[8] = -1;
break;
case CONV_SHARP02:
//シャープ処理パラメータ2
pnOperate[0] = 0; //[ 0 ][ -2 ][ 0 ]
pnOperate[1] = -2; //[ -2 ][ 11 ][ -2 ]
pnOperate[2] = 0; //[ 0 ][ -2 ][ 0 ]
pnOperate[3] = -2;
pnOperate[4] = 11;
pnOperate[5] = -2;
pnOperate[6] = 0;
pnOperate[7] = -2;
pnOperate[8] = 0;
break;
case CONV_SHARP03:
//シャープ処理パラメータ3
pnOperate[0] = 0; //[ 0 ][ -1 ][ 0 ]
pnOperate[1] = -1; //[ -1 ][ 5 ][ -1 ]
pnOperate[2] = 0; //[ 0 ][ -1 ][ 0 ]
pnOperate[3] = -1;
pnOperate[4] = 5;
pnOperate[5] = -1;
pnOperate[6] = 0;
pnOperate[7] = -1;
pnOperate[8] = 0;
break;
case CONV_SHARP04:
//シャープ処理パラメータ4
pnOperate[0] = 0; //[ 0 ][ -3 ][ 0 ]
pnOperate[1] = -3; //[ -3 ][ 24 ][ -3 ]
pnOperate[2] = 0; //[ 0 ][ -3 ][ 0 ]
pnOperate[3] = -3;
pnOperate[4] = 24;
pnOperate[5] = -3;
pnOperate[6] = 0;
pnOperate[7] = -3;
pnOperate[8] = 0;
break;
case CONV_SOFT01:
//Gaussian blur処理パラメータ
pnOperate[0] = 1; //[ 1 ][ 2 ][ 1 ]
pnOperate[1] = 2; //[ 2 ][ 4 ][ 2 ]
pnOperate[2] = 1; //[ 1 ][ 2 ][ 1 ]
pnOperate[3] = 2;
pnOperate[4] = 4;
pnOperate[5] = 2;
pnOperate[6] = 1;
pnOperate[7] = 2;
pnOperate[8] = 1;
break;
case CONV_SOFT02:
//Gaussian blur処理パラメータ
pnOperate[0] = 45; //[ 45 ][ 122 ][ 45 ]
pnOperate[1] = 122; //[ 122 ][ 322 ][ 122 ]
pnOperate[2] = 45; //[ 45 ][ 122 ][ 45 ]
pnOperate[3] = 122;
pnOperate[4] = 322;
pnOperate[5] = 122;
pnOperate[6] = 45;
pnOperate[7] = 122;
pnOperate[8] = 45;
break;
case CONV_SOFT03:
//Gaussian blur処理パラメータ
pnOperate[0] = 0; //[ 0 ][ 1 ][ 0 ]
pnOperate[1] = 1; //[ 1 ][ 1 ][ 1 ]
pnOperate[2] = 0; //[ 0 ][ 1 ][ 0 ]
pnOperate[3] = 1;
pnOperate[4] = 1;
pnOperate[5] = 1;
pnOperate[6] = 0;
pnOperate[7] = 1;
pnOperate[8] = 0;
break;
case CONV_SOFT04:
//ぼかし処理パラメータ
pnOperate[0] = 1; //[ 1 ][ 2 ][ 1 ]
pnOperate[1] = 2; //[ 2 ][ 3 ][ 2 ]
pnOperate[2] = 1; //[ 1 ][ 2 ][ 1 ]
pnOperate[3] = 2;
pnOperate[4] = 3;
pnOperate[5] = 2;
pnOperate[6] = 1;
pnOperate[7] = 2;
pnOperate[8] = 1;
break;
case CONV_SOFT05:
//ぼかし処理パラメータ
pnOperate[0] = 625; //[ 625 ][ 1250 ][ 625 ]
pnOperate[1] = 1250; //[ 1250 ][ 2500 ][ 1250 ]
pnOperate[2] = 625; //[ 625 ][ 1250 ][ 625 ]
pnOperate[3] = 1250;
pnOperate[4] = 2500;
pnOperate[5] = 1250;
pnOperate[6] = 625;
pnOperate[7] = 1250;
pnOperate[8] = 625;
break;
case CONV_SOFT06:
//ぼかし処理パラメータ
pnOperate[0] = 1; //[ 1 ][ 1 ][ 1 ]
pnOperate[1] = 1; //[ 1 ][ 1 ][ 1 ]
pnOperate[2] = 1; //[ 1 ][ 1 ][ 1 ]
pnOperate[3] = 1;
pnOperate[4] = 1;
pnOperate[5] = 1;
pnOperate[6] = 1;
pnOperate[7] = 1;
pnOperate[8] = 1;
break;
case CONV_SOFT07:
//ぼかし処理パラメータ
pnOperate[0] = 0; //[ 0 ][ 1 ][ 0 ]
pnOperate[1] = 1; //[ 1 ][ 0 ][ 1 ]
pnOperate[2] = 0; //[ 0 ][ 1 ][ 0 ]
pnOperate[3] = 1;
pnOperate[4] = 0;
pnOperate[5] = 1;
pnOperate[6] = 0;
pnOperate[7] = 1;
pnOperate[8] = 0;
break;
case CONV_SOFT08:
//ぼかし処理パラメータ
pnOperate[0] = 2; //[ 2 ][ 2 ][ 2 ]
pnOperate[1] = 2; //[ 2 ][ 1 ][ 2 ]
pnOperate[2] = 2; //[ 2 ][ 2 ][ 2 ]
pnOperate[3] = 2;
pnOperate[4] = 1;
pnOperate[5] = 2;
pnOperate[6] = 2;
pnOperate[7] = 2;
pnOperate[8] = 2;
break;
case CONV_LAPLACIAN01:
//ラプラシアン処理パラメータ全方向
pnOperate[0] = 1; //[ 1 ][ 1 ][ 1 ]
pnOperate[1] = 1; //[ 1 ][ -8 ][ 1 ]
pnOperate[2] = 1; //[ 1 ][ 1 ][ 1 ]
pnOperate[3] = 1;
pnOperate[4] = -8;
pnOperate[5] = 1;
pnOperate[6] = 1;
pnOperate[7] = 1;
pnOperate[8] = 1;
break;
case CONV_LAPLACIAN02:
//ラプラシアン処理パラメータ上下左右
pnOperate[0] = 0; //[ 0 ][ 1 ][ 0 ]
pnOperate[1] = 1; //[ 1 ][ -4 ][ 1 ]
pnOperate[2] = 0; //[ 0 ][ 1 ][ 0 ]
pnOperate[3] = 1;
pnOperate[4] = -4;
pnOperate[5] = 1;
pnOperate[6] = 0;
pnOperate[7] = 1;
pnOperate[8] = 0;
break;
default:
ATLASSERT(0);
return false;
}
return true;
}
//
// コンボリューション処理
//
//pnOperateは処理行列(3行3列)
//bNotDivideは積算後に除算を行わないか、行うかの指定(falseなら除算する)
//
bool Convolution(UINT nWidth,UINT nHeight,BYTE* pData,int nStrideBytes,int pnOperate[9],bool bNotDivide=false)
{
int i;
ULONG x;
ULONG y;
long nTmpR;
long nTmpG;
long nTmpB;
int nDiv; //計算結果を除算する値 = pnOperate[]の合計値
BYTE* pNew; //新しい色値の画像を入れるバイト配列
BYTE* pNewTmp;
BYTE* pDataTmp;
RGBTRIPLE* pRgbUp; //左上の元値のピクセル(+1で上、+2で右上)
RGBTRIPLE* pRgbCur; //左の元値のピクセル(+1で中心、+2で右)
RGBTRIPLE* pRgbDown; //左下の元値のピクセル(+1で下、+2で右下)
RGBTRIPLE* pRgbNew; //新しい色値を代入するピクセル
RGBTRIPLE* ppRefPos[9]; //元値の上下左右斜め全9ピクセル位置
pDataTmp = pData;
if(bNotDivide)
nDiv = 1;
else
{
nDiv = 0;
for(i = 0; i < 9; i++)
nDiv += pnOperate[i];
if(nDiv < 0)
nDiv *= -1;
if(nDiv == 0)
nDiv = 1;
}
pNew = new BYTE[nStrideBytes * nHeight];
pNewTmp = pNew;
for(y = 1; y < nHeight - 1; y++)
{
pRgbUp = (RGBTRIPLE*)pData;
pRgbCur = (RGBTRIPLE*)((BYTE*)pRgbUp + nStrideBytes);
pRgbDown= (RGBTRIPLE*)((BYTE*)pRgbCur + nStrideBytes);
pRgbNew = (RGBTRIPLE*)(pNew + nStrideBytes);
for(x = 1; x < nWidth - 1; x++)
{
//あるピクセルの上下左右のピクセルポインタ
ppRefPos[0] = pRgbUp;
ppRefPos[1] = pRgbUp + 1;
ppRefPos[2] = pRgbUp + 2;
ppRefPos[3] = pRgbCur;
ppRefPos[4] = pRgbCur + 1;
ppRefPos[5] = pRgbCur + 2;
ppRefPos[6] = pRgbDown;
ppRefPos[7] = pRgbDown + 1;
ppRefPos[8] = pRgbDown + 2;
//テーブルの値を使って計算
nTmpR = 0;
nTmpG = 0;
nTmpB = 0;
for(i = 0; i < 9; i++)
{
if(pnOperate[i] == 0)
continue;
nTmpR += ppRefPos[i]->rgbtRed * pnOperate[i];
nTmpG += ppRefPos[i]->rgbtGreen * pnOperate[i];
nTmpB += ppRefPos[i]->rgbtBlue * pnOperate[i];
}
//平均値を求めるために除算
if(nDiv != 1)
{
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;
pRgbNew[x].rgbtBlue = (BYTE)nTmpB;
pRgbNew[x].rgbtGreen = (BYTE)nTmpG;
pRgbNew[x].rgbtRed = (BYTE)nTmpR;
pRgbUp++;
pRgbCur++;
pRgbDown++;
}
//左端のピクセルは1つ右のピクセルと同じものを採用
pRgbNew[0] = *(pRgbCur - nWidth + 1);
//右端のピクセルは1つ左のピクセルと同じものを採用
pRgbNew[nWidth - 1] = *(pRgbCur - 1);
pData += nStrideBytes;
pNew += nStrideBytes;
}
//上端のピクセル列は処理後の2列目と同じものを採用
memcpy(pNewTmp,pDataTmp + nStrideBytes,nStrideBytes);
//下端のピクセル列は処理の最終列と同じものを採用
memcpy(pNew,pData - nStrideBytes,nStrideBytes);
//処理後の画像を適用
memcpy(pDataTmp,pNewTmp,nStrideBytes * nHeight);
delete pNewTmp;
return true;
}
};
前に作成した「DnpImage.h」に変更を加える。派生元クラスとしてCDnpImageConvolutionを入れ、 コンボリューション処理関連関数を追加する。。
#pragma once
#include "DnpImageBase.h"
#include "DnpImageConvolution.h"
class CDnpImage : public CDnpImageBase, public CDnpImageConvolution
{
public:
//
// コンボリューション処理
//
bool Convolution(int pnOperate[9],bool bNotDivide=false)
{
bool ret;
int nStrideBytes;
BYTE* pData;
if(IsValidImage() == false)
return false;
ret = LockBits(&pData,&nStrideBytes);
if(ret == false)
return false;
ret = CDnpImageConvolution::Convolution(GetWidth(),GetHeight(),pData,nStrideBytes,pnOperate,bNotDivide);
UnlockBits();
return ret;
}
//
// コンボリューション処理
//
//指定したコンボリューション処理を行う。nRotateは処理パラメータ行列の右45度回転
//を何度行うかの指定。エンボスなどの非対称パラメータの場合は結果が変わる。
//パラメータが非対称かどうか(nRotateにいくつまでの値を指定できるか)は
//CDnpImageConvolution::GetConvolutionRotateCount()で調べる
//
bool Convolution(CDnpImageConvolution::CONVOLUTION_TYPE enumType,UINT nRotate=0)
{
int pnOperate[9];
bool ret;
if(IsValidImage() == false)
return false;
ret = GetConvolutionOperator(enumType,pnOperate);
if(ret == false)
return false;
GetConvolutionRotate(nRotate,pnOperate);
return Convolution(pnOperate);
}
。。。。省略。。。。
};
