========================================
gtProgプログラミングの解説
======================================== ver0.08


※この説明はGontaさんのフィルターに資料として添付されている内容をそのまま使用しています。
以外と見る機会が少ないかもと思いUPさせて頂きました。

[プログラム開発手順]========================================
・Groupを打ち込む
・Titleを打ち込む
・Initializeプログラムを打ち込む
・Transformプログラムを打ち込む
・[Check]ボタンを押してエラーチェックする
・[Save]ボタンを押してプログラムを保存する
 (gtProg.iniファイルに保存されます)


[内部動作]==================================================

プログラムは二つ(Initialize,Transform)に分かれています。内部動作を簡単にC言語で書くと以下のようになっています。

'Initialize'中のパラメータ(?ライン)処理
if(実行ボタンが押された){
'Initialize'中のプログラム部分処理(?ラインをコメントとしてスキップ)
for(y=0; y<画像のYサイズ; y++){
for(x=0; x<画像のXサイズ; x++){
'Transform'プログラムの処理
}
}
}

'Initialize'は一度のみ画像処理を走査線方向に走らせる前に実行されます。
'Transform'は各ピクセルに対して実行されます。



[Initializeプログラム]======================================

大きく分けて2つのパートがあります。
1) '?'で始まっている行(スライダ用のパラメータの定義)
2) その他の行(初期化処理)

1)のフォーマット
'?'に続きパラメータ名,表示するメッセージ,最小値,最大値,デフォルト値;
これを1行で定義します。
ex) ?param,message,0,100,50;
 たとえばこの行はパラメータparamを使用して、最小値0、最大値100、デフォルト値を50としたスライダーバーを定義します。フィルター実行画面(スライダーの横)には'message'と表示されます。
パラメータ行は12まで記述できます。それ以上記述するとエラーになります。

2)のフォーマット
'?'以外の行はプログラムとして実行されます。このパートとTransformプログラムは同じ形式で記述します。

・Initializeプログラムの最初の行にcoord=?の定義をするようにしてください。



[Transformプログラム]=======================================

この部分には各ピクセルに対して行う処理を記述します。
このプログラムが呼ばれる前にr,t,x,y,R,G,Bのパラメータがセットされます。
このプログラムが終了した後には
coord=1 なら(r,t)のピクセル値を現在のピクセル値にします。
coord=2 なら(x,y)のピクセル値を現在のピクセル値にします。
coord=0 ならR,G,Bの値を現在のピクセル値にします。
coord=-1 なら何もしません。

(r,t)はRθ座標系、(x,y)はXY座標系です。



[言語仕様]==================================================

C言語に近い形をとっています。処理の手抜きのため、いくつかの構文は使用できません。以下に大体の仕様を記述しておきます。細かいことはサンプルプログラムを参照してください。
・a++, --bなどの計算式は記述できません。a=a+1, b=b-1という風に記述してください。
・+=, -=などの演算子も使用できません。
・!,&,|,^の演算子も今のところ使用できません。
・三項演算子は使用できません。
・変数はファイル名を除き、double型で扱っています。
・%演算子は変数を整数に変換してから余りを求めています。
・変数の定義の必要はありません。初期値は0です。
・変数長は256バイトまでは処理されます。
・プログラムはInitialize,Transformとも4096文字までです。
・if(a=(b==c))...のような記述は出来ません。
 代入は別のラインに記述する必要があります。
・ファンクションの定義などは出来ません。
・もちろんポインタなども使用できません。
・制御構造としてはif文とwhile文が使用できます。
 (無限ループのチェックはしていませんので注意してください)



[システム変数]==============================================

・coord
'Initialize'の先頭行に定義します。'Transform'プログラム実行後にどの値を現在のピクセルに代入するかを決めます。0でR,G,Bを使用します。1で(r,t)の値を現在のピクセルにコピーします。このとき補間(Interpolation)で指定された計算方法をとります。2で(x,y)のピクセルをコピーします。その他の値(-1など)を代入した場合は、プログラム実行後にどの値も現在のピクセルに代入しません。'Transform'プログラム中で変更することによりダイナミックに処理を変えることも出来ます。

・vTplane
プレビュー用のパラメータです。1を設定することで、透明度をプレビューに反映させます。透明な部分は黒で表示されます。普段は透明度は無視してプレビューを表示していますが、透明度を変更するようなフィルタでは1を設定してあります。

・vScale
プレビュー用のパラメータです。1を設定すると、全画面の縮小を表示せずに、同一スケールで画像の左上部分を表示します。ドット単位でパラメータ指定するようなフィルタでは、縮小すると処理結果が異なるため1を設定してあります。

・xs,ys
画像のサイズです。もちろんプレビュー表示時には値は小さくなっています。読み取り専用。書き込んでも実害はありませんが混乱の元です。

・cx,cy
画像の中心。この値を元にx,y,r,tが計算されます。デフォルトではxs/2,ys/2となっています。

・x,y,r,t
(x,y)座標と(r,t)座標。
r=sqrt(x*x+y*y), t=atan2(y,x)という関係になっているはずです。
Transformが呼ばれる前は0,0,0,0。Transform中ではピクセルの座標が代入されています。

・R,G,B,T
ピクセル値、0以上255以下。Tは0で完全な透明、255で不透明。
デフォルト値は0,0,0,255。Transform中では現在ピクセルのカラーが代入されています。

・pi
3.14159。よく使うためデフォルトで登録してあります。
代入できますが、混乱の元。

・H,L,S
HLS()関数を使うと結果が代入されます。デフォルトは0,0,0。

・loop
デフォルト1です。'Initialize'中で数値を設定すると、その回数だけ'Transform'を含むループがまわされます。複数回に分けて処理を行う場合などに利用できます。

・keepImage
ver0.08で追加。デフォルト0。keepImage=0では、loopを変更して処理する場合、二度目以降の処理で出力バッファの内容を入力バッファにコピーします。keepImage=1としておくと、二度目以降の処理でもコピーしません。



[関数]======================================================

・sin(n),cos(n),tan(n),exp(n),log(n),pow(n,m),abs(n)
・sqrt(n),acos(n),asin(n),atan2(y,x)
math.hのC標準ライブラリの関数と同じです。

・rand(min,max)
min以上max未満の乱数を発生します。

・srand(n)
乱数の種を初期化します。

・int(n)
整数部分を返します。nがマイナスの場合は最も近くnより小さい整数を返します。n=-1.5の場合は-2です。

・min(a,b),max(a,b)
aとbのうち最小、最大を返します。

・sgn(n)
nの符号を返します。不の場合は-1,0で0,正の場合1。

・R(x,y),G(x,y),B(x,y),T(x,y)
(x,y)座標のカラーを返します。現在座標以外のカラーを参照することが出来ます。

・exit(n)
nが0か正でインタープリタを即座に終了します。プログラムが長くなる場合には、処理速度アップと、深いネスティング防止に。負の数を指定すると、画像処理を即座に終了します。処理される以前のピクセル値は不定となります。

・get(x,y)
(x,y)のカラーをR,G,B変数に展開します。R(x,y),G(x,y)...と何度も座標計算をするよりは処理速度が速いと思います。

・add(x,y,n)
R=R+R(x,y)*n; G=G+G(x,y)*n; B=B+B(x,y)*n;と同じです。

・HLS(r,g,b)
r,g,bの値からh,l,sを計算し、変数H,L,Sに代入します。
それぞれの値は0〜255までの実数です。

・RGB(h,l,s)
h,l,sの値からr,g,bを計算し、変数R,G,Bに代入します。
それぞれの値は0〜255までの実数です。

・SetMatrix3(n,9変数,係数)
n番目の3x3マトリクスに9変数と係数をセットします。コンボルーションの計算に使用します。nは0から7まで、8個のマトリクスを持つことが出来ます。
例)SetMatrix3(0, 1,1,1,1,1,1,1,1,1, 1/9);   ローパスフィルタ

・SetMatrix5(n,25変数,係数)
n番目の5x5マトリクスに25変数と係数をセットします。コンボルーションの計算に使用します。nは0から7まで、3x3マトリクスと共用で8個のマトリクスを持つことが出来ます。

・Conv(n,x,y)
n番目のマトリクスを使って(x,y)座標のコンボルーションを計算し、結果をR,G,B,Tにセットします。


…と、ここまでは入力イメージに対して出力イメージを計算する関数です。通常の画像変形およびカラー調整などの処理は以上の関数でできます。これに対して、ペンなどを使って能動的に出力イメージに描画する場合のため以下の関数が用意されています。



・LoadBmp(n,str)
ビットマップファイルを読み込みます。.../filter/Gontaをカレントディレクトリとしています。nは0から7までで、設定するビットマップの番号を指定します。Matrixとは別の領域を取っています。strは拡張子.bmpを除いたファイル名です。
例)LoadBmp(0,"Pen/MyPen");       Pen/MyPen.bmpを読み込む。

・LoadBmpNum(n,str,num)
ペンに番号をつけたものをファイル名にして読み込みます。
例)LoadBmp(0,"Pen/MyPen",3);     Pen/MyPen03.bmpを読み込む。

・xs(n),ys(n)
n番目のビットマップの画像サイズを取得できます。

・getb(n,x,y)
n番目のビットマップの(x,y)のカラーをR,G,B変数に展開します。

・_R(x,y),_G(x,y),_B(x,y),_T(x,y)
出力用イメージに設定されているカラーを読み出します。書き込む以前のデータは不定です。アンダーバーから始まっている関数は出力イメージ上の処理を意味しています。

・_get(x,y),_add(x,y,n),_Conv(n,x,y)
get(x,y),add(x,y,n),Conv(n,x,y)と同じですが、出力バッファを使って処理を行います。

・_Pset(x,y)
R,G,Bの変数の値を出力イメージの(x,y)座標に書き込みます。

・_Tset(x,y)
透明度Tを出力イメージの(x,y)座標に書き込みます。

・_Draw(n,x,y)
ペンnを使って出力イメージの(x,y)に描画します。カラーはR,G,Bパラメータが使用されます。またTでペンの濃度を調整できます。

・_DrawT(n,x,y)
ペンnを使って出力イメージの(x,y)の透明度に加減算します。Tパラメータを変更するとそのパラメータ分だけ透明度プレーンに加算されます。マイナスを指定すれば減算できます。

・_Fill(r,g,b)
出力イメージを(r,g,b)で塗りつぶします。Tで濃度を調整できます。
ペンで描画する前に出力イメージに白紙を設定しておきたいときなどに使用できます。普通はInitializeプログラム中で使う関数です。

・_FillT(t)
出力イメージの透明度をtで塗りつぶします。普通はInitializeプログラム中で使う関数です。

・_Copy(n)
n=0で入力イメージを出力イメージにコピーします。
n=1で加算合成。
n=2で減算合成。
n=3で逆減算合成。
n=4で乗算合成。
n=-1で出力イメージと入力イメージを入れ替え。
ペンでオリジナルイメージの上に描画したいときなどに使用できます。普通はInitializeプログラム中で使う関数です。

・clean(n)
コンボルーション関連で必要になったのでv0.08で追加しました。完全に透明なピクセルの値をnにします(R=G=B=n)。Pixiaでは完全に消しゴムをかけたところでもピクセル値を保存しています。それで透明な部分の隣にあるピクセルと透明な部分のピクセルを演算すると、そのままでは値が不安定になる場合が出てきました。この関数を使うと、完全透明な部分は黒とか白に出来るので、演算結果が安定します。
ex) clean(0)        完全透明な部分は黒色にする。



coord=0としてR,G,Bを計算するのと、coord=2としてX-Y座標系で計算して、Transformプログラムの最後に、get(x,y); と書くのでは処理としては同じになります。ただし、補間処理はされません。
同じくcoord=-1として処理するのと、coord=0として、Transformプログラムの最後に、_Pset(x,y); _Tset(x,y); と書くのでは処理としては同じになります。ただし何度も座標計算するので遅くなります。

============================================================
2002/11/26
Gonta

戻る