今回は、フォトレタッチソフトなどで良く見かける「カスタムフィルタ」の画像処理プログラムを作ってみました。このフィルタは、あるピクセルを中心とする一定の範囲内のピクセルに対して特定の演算を行いその結果をピクセルに書き出すフィルタで、エンボスやぼかしなどさまざまな効果を出す事ができます。なかなか楽しいので、お手持ちのビットマップにフィルタをかけて遊んでみてください フィルタの作成今回は、3×3のフィルタを作ります。つまり、あるピクセルを囲む3×3ピクセルの範囲で処理を行うわけですね。このフィルタは、範囲内のピクセルの値にある数値を掛けて合計していき、その数値をある数で割った後ある数を加えます。つまり、フィルタはピクセルに掛ける数値をあらわす3×3行列とその結果を割る除算値、結果に加える加算値で構成されるわけです。具体的には、あるピクセルを中心とする3×3ピクセルの各ピクセルに対して、対応する行列の値を掛けて合計します。そして、その値を除算値で割り加算値を加えた数値をピクセルの値とするわけです。 ・フィルタの例 1 1 1 1 1 1 1 1 1 除算値9 加算値0 上のフィルタは、ぼかし処理です。このフィルタを、p5を中心とする以下のピクセル列に適応してみましょう。 p1 p2 p3 p4 p5 p6 p7 p8 p9 p5=(p1×1+p2×1+p3×1+p4×1+p5×1+p6×1+p7×1+p8×1+p9×1)/9+0 この処理を、ビットマップの各ピクセルのRGB各成分に対して行います。これは、以前やったぼかしとまったく同じ処理ですね。今回のプログラムでは、フィルタをdouble型2次元配列dFil[3][3]に除算値をdDiv、加算値をdPlsに入れるようにしました。 実際にフィルタ処理を行う部分は以下のようになっています。この例では、24ビットDIBのピクセル列がlpWrkに入っているものとし、ビットマップの一番外側1ピクセルを除いた範囲で画像処理を行っています。 for (i=1;i<dwHeight-1;i++) /* フィルタ処理 */ for (j=1;j<dwWidth-1;j++) { dr=0; dg=0; db=0; for (k=0;k<3;k++) /* RGB各成分の値を行列値を掛けて加算 */ for (l=0;l<3;l++) { dr+=(double)lpPixel[(j+l-1)*3+(k+i-1)*dwLength+2]*dFil[k][l]; dg+=(double)lpPixel[(j+l-1)*3+(k+i-1)*dwLength+1]*dFil[k][l]; db+=(double)lpPixel[(j+l-1)*3+(k+i-1)*dwLength]*dFil[k][l]; } dr=dPls+dr/dDiv; dg=dPls+dg/dDiv; db=dPls+db/dDiv; if (dr<0) dr=0; if (dr>255) dr=255; if (dg<0) dg=0; if (dg>255) dg=255; if (db<0) db=0; if (db>255) db=255; lpWrk[j*3+i*dwLength+2]=(BYTE)dr; lpWrk[j*3+i*dwLength+1]=(BYTE)dg; lpWrk[j*3+i*dwLength]=(BYTE)db; } プログラムまず、適当なフルカラービットマップファイルをドロップしてください。続いて、行列と除算値・加算値を実数で指定してフィルタを作ったら「処理」ボタンでフィルタを掛けます。初期状態ではエンボス処理のフィルタになっていますが、エンボス処理ではフィルタをかける前に「白黒化」ボタンでグレースケールに変換しておくと良いでしょう。 プログラムを起動したら、画像処理の結果を見ながらフィルタの設定を変更してみてください。 |