全体的な話を見るとC言語ながら出来るだけオブジェクトとして分割がされていて、PhotoShopのフィルタのSDKと比べてみても、かなりスマートな構造になっています。
なので、どれを使えばよいかと言うところさえ理解すれば、特に処理が複雑になることなく全体を完結に記述出来る性質があります
個人的には、「C言語分かるなら、黙ってRender関数とFilterImag関数を見ろ」と言う感じです。だいたいそれで大事なことは分かります。分かるのであれば、あとは細かい動作の補足になります。
(先ほども言いましたが…)SDK_Noseフィルタのコード中では、この処理はRender関数とRender関数から呼び出されているFilterImage関数の内部で行われています。
PF_Err Render ( PF_InData *in_data,
PF_OutData *out_data,
PF_ParamDef *params[],
PF_LayerDef *output )
{
…(以下略)
err = isP->iterate( in_data,
0, // progress base
lines, // progress final
¶ms[FILTER_INPUT]->u.ld, // src
NULL, // area - null for all pixels
(long)&fi, // refcon - your custom data pointer
FilterImage, // pixel function pointer
output); // dest
…(以下略)
}
ここのiterateメソッドが処理を行うFilterImage関数への参照を送っています。ここで大事なのは、主に第5引数「(long)&fi」と第6引数「FilterImage」です。
第5引数は送りたいデータを構造体にして、その中に一纏めにして送っています。そして第6引数はFilterImage関数で実際に処理を行っている事を示しています。
iterateメソッド、C++プログラマなら心当たりがあるでしょうが、一応解説しておくとiterate(数え上げる)の名の通り画像中のデータを1px毎に取り出して処理を行います。
実際にFilterImage関数の引数を見ると
PF_Err FilterImage (long refcon, long x, long y, PF_Pixel *in, PF_Pixel *out)
となっています。引数の一覧を見ると。次の様になっています。
型 | 変数名 | 意味 |
---|---|---|
long | refcon | パラメーターのデータへの参照。ここにオリジナルなデータを入れます。難しいので後回し |
long | x | 現在処理しているpxのx座標 |
long | y | 現在処理しているpxのy座標 |
PF_Pixel | *in | 現在処理しているpxの入力データ |
PF_Pixel | *out | 現在処理しているpxの出力データ |
この様に、1pxごとに、入力側画像、出力側画像へのピクセルへの参照。それにそこへのx,y座標がきちんとあります。そして、そのピクセルへのノイズを加えるかどうかを判断して、最後に出力画像の *outにその結果を代入すればよいと言うことになっています
iterateメソッドですが、基本的にはx,y座標しか受け取っていませんが、他にも細かいデータを送ることが出来ます。
第1引数のrefconを利用します。これは、他に送りたいデータがあった場合に、そのデータへの参照が代入されているので。2つ以上データを送りたい場合には代入を利用します。
例えば、送りたいデータがあった場合FilterParamsという構造体を作成して
typedef struct {
int width;
int height;
} FilterParams;
これをRender関数内部のiterateメソッドで送ります
FilterParams prm;
prm->width=100;
prm->height=100;
err = isP->iterate( in_data, 0, lines, ¶ms[FILTER_INPUT]->u.ld, NULL, (long)&prm, MakeBlankImage, output );
この様にしてFilterImageメソッドにデータを送って、最後にFilterImage関数内部で取り出します
PF_Err FilterImage(long refcon, long x, long y, PF_Pixel *in, PF_Pixel *out){
FilterParams *prm = (FilterParams *)refcon;
元々何処にデータがあるかというアドレスを受け取っているので、この様に変換を行って、データを取り出します。ポインタってそんなもんです。
画像の移動を行いたい場合はポインタの加算、減算を利用します。
右に10px移動したい場合は、*in変数を加算して
in += 10;
とします。これで10px右に移動します。またポインタを利用しているので、画像の外に処理が飛び出ない様に
if( 10 < x ){
// ここから移動処理を書きます
}
の様に、現在位置が大丈夫な位置かどうかのチェックを加えておくことを忘れないでください。
この様な方法を取ると当然、右端10pxが見切れて消滅しますのでそれが嫌な場合はサンプルのMFC_Shifter等で上下左右の端を広げるためのサンプルがありますので、そちらを見てあげて下さい