Top > ScriptFuClass > Step3

CENTER:[[二限目>ScriptFuClass/Step2]] | [[Script-Fu 青空教室>ScriptFuClass]] | [[四限目>ScriptFuClass/Step4]]

---------


* 三限目 最初のスクリプト [#k5848e45]

#contents



これで最低限必要な Scheme の説明が終わり、最初のスクリプトを書くことができるようになりました。最初のスクリプトは非常にシンプルです。しかしとても重要な意味を持っています。まずはレイヤーを複製するスクリプトと新規画像を作るスクリプトを作ってみましょう。


** 3.1 画像依存型と独立実行型 [#f46552f4]

スクリプトには大きく分けて独立実行型のスクリプトと画像依存型のスクリプトの二種類があります。

*** 3.1.1 画像依存型 [#s449bca1]

画像依存型のスクリプトは、スクリプトの実行に画像 (やレイヤー等) を必要とする処理を行うスクリプトです。レイヤーに対して何らかの操作を行うものがそうです。このタイプのスクリプトはメニューのさまざまな場所に置かれています。

*** 3.1.2 独立実行型 [#r242f856]

独立実行型のスクリプトは、スクリプトの実行に画像を必要としないスクリプトです。画像を自前で作り上げてしまうものが多いです。このタイプのスクリプトは主に ''ファイル/画像の作成/{ボタン|ロゴ|パターン|Web ページテーマの作成}'' の下に置かれています。


この次では画像依存型スクリプトと独立実行型の簡単な例として、最も基本的なスクリプトを作ります。
画像依存型の例として、レイヤーを複製するスクリプトを挙げます。そして独立実行型の例としては、新規画像を作成するスクリプトを挙げます。


** 3.2 プロシージャブラウザ [#procedural-browser]

''ヘルプ/プロシージャブラウザ...'' にある プロシージャブラウザでは、Gimp のプロトコルデータベースに登録されていて Script-Fu から呼び出して利用することができる関数を検索することができます。


*** 3.2.1 プロシージャブラウザの使い方 [#c47de0a8]

Script-Fu を書く時で Gimp の機能を何か使いたいとき、プロシージャブラウザからお目当ての機能を行う関数を探して、入力として必要な引数 (あれば出力も) を確認することができます。スクリプトを作成した場合も、関数の一つとしてそのスクリプトがデータベースに登録されます。

関数を探す時は、検索欄に探したいターゲットのキーワードを入力するだけです。するとキーワードに一致する関数だけが左側に残ります。この下は "new" で検索した結果です。

&ref(fu3-dbbrowser-layer-new.png,nolink,gimp-layer-new の入出力);

左側から何か一つ関数を選ぶと、その関数に関する情報が右側に表示されます。その関数の説明と、(あれば) 全ての入力の引数と、全ての出力の引数についての情報と、ヘルプとその他の著作権情報などです。ヘルプにはその関数を使う上で重要な情報が詳しく書かれているので、はじめて使う関数の時には一度目を通しておくようにしましょう。

Script-Fu を書く時には、基本的にこのプロシージャブラウザで関数を探しながら書くことになります。そのため次の作業の繰り返しでスクリプトを書くことになります。

>使いたい・欲しい機能 (関数) がある
>    ↓
>プロシージャブラウザで探す
>    ↓
>入力/出力の引数を見る
>    ↓
>スクリプトに書く
>    ↓
>次の関数へ (最初に戻る)

検索したいキーワードが分からない場合は、Gimp を英語モードで起動するとツールやコマンドが英語表示になるので分かりやすいでしょう。英語モードで起動するには環境変数「lang」を「en」に設定します。環境変数の設定方法は使用している OS により異なるので該当サイトを参照してください。


*** 3.2.2 プロシージャブラウザで表示される引数型 [#g549e46d]

プロシージャブラウザの右側の入力パラメータ/出力返り値のところでは、引数として期待されている型が表示されています。スクリプトを書く場合には、間違った型の値を与えないようにしましょう。もし引数の方を間違えると、スクリプトを実行したときにエラーとなります。
プロシージャブラウザの右側の入力パラメータ/出力返り値のところでは、引数として期待されている型が表示されています。スクリプトを書く場合には、間違った型の値を与えないようにしましょう。もし引数の型を間違えると、スクリプトを実行したときにエラーとなります。

この下には引数型の説明がありますが、はじめて読む場合は読み飛ばしてしまっても構いません。後で読む必要が出てきたときに参照する程度でよいでしょう。


:ARRAY (FLOATARRAY/INT8ARRAY/INT32ARRAY/STRINGARRAY)|配列です。配列の型によって、小数点型、8/32 ビット整数型、文字列型に分かれます。

:CHANNEL|チャンネルです。リストになっており、先頭の要素はチャンネルの ID です。チャンネルマスクやクイックマスクも CHANNEL として扱われます。

:COLOR|色です。RGB の三要素の数値が入ったリストになります。

:DISPLAY|作成した IMAGE を実際に画像ウィンドウに表示するときに関係します。

:DRAWABLE|ドロアブルです。ドロアブルはレイヤーとチャンネルの総称です。リストになっており、先頭の要素はドロアブルの ID です。

:FLOAT|(浮動?) 小数点です。整数であっても 127.000000 のように小数点の有効桁まで付けて受け渡しを行います。

:IMAGE|画像です。リストになっており、先頭の要素は画像の ID です。 

:INT32|32 ビット型の整数です。取り得る数値の範囲が決まっている場合があるので、DB ブラウザに書いてある説明を読んでおきましょう。

:LAYER|レイヤーです。リストになっており、先頭の要素はレイヤーの ID です。

:PARASITE|パラサイトです。パラサイトを利用すると drawable などのターゲットに対して情報を付加することができます。

:SELECTION|選択領域です。リストに一つだけ要素が入っており、選択領域の ID (整数) があります。

:STRING|文字列です。文字列は二重引用符 (") で前後を囲まなくてはいけません。例えば文字列 string は "string" のようにします。二重引用符 " 自身を出力するにはエスケープ記号 \ で \" のようにエスケープします。

:VECTOR|ベクトル情報です。INT32 型の整数として収められます。


** 3.3 レイヤーを複製するスクリプト [#duplicate-layer]

ようやく最初の Script-Fu を書く作業です。このレイヤーを複製するスクリプトは、複製元のレイヤーを必要とする画像依存型のスクリプトです。

ここでは Scheme について色々と説明する前に、レイヤーを複製するだけという非常にシンプルな Script-Fu を書いてしまいます。それからスクリプトがどのような構成になっているのかを説明します。

*** 3.3.1 書いたスクリプトを置く [#xcccb988]

最初のスクリプトをぱっと見ただけでは、まだ何がどうなっているのか分からないでしょう。とりあえずこのスクリプトを、Unix ユーザーは Emacs 等のエディタで、Windows ユーザーはメモ帳などを使って入力して下さい。入力したファイルは、ファイル名として duplicate-layer.scm などとして保存して下さい。

この保存した duplicate-layer.scm を、あなたの個人用の scripts ディレクトリに入れます。Unix ユーザーと Windows ユーザーの場合ではそれぞれこのようになります。

-Unix:
>>$ cp duplicate.scm ~/.gimp-2.6/scripts/

-Windows:
>>duplicate.scm ファイルを C:\Documents and Settings\''(ユーザー名)''\.gimp-2.6\scripts フォルダに入れる

*** 3.3.2 レイヤー複製のスクリプト [#tb279880]

 (define (script-fu-duplicate-layer img layer)
   (let* (
          (copy-layer (car (gimp-layer-copy layer TRUE)))
         )
     (gimp-image-add-layer img copy-layer -1)
     (gimp-displays-flush)
   )
 )
 
 (script-fu-register
   "script-fu-duplicate-layer"
   "Duplicate Layer..."
   "description"
   "name"
   "copyright"
   "date"
   "RGB*"
   SF-IMAGE     "Image"     0
   SF-DRAWABLE  "Drawable"  0)
 
  (script-fu-menu-register "script-fu-duplicate-layer"
                           "<Image>/Filters/Test")

*** 3.3.3 スクリプトを動かす [#v9d8c61d]

それでは上のスクリプトの説明に入ります。新しいスクリプトを scripts ディレクトリにコピーしたら、Gimp を起動して下さい。自動的にこのスクリプトが読み込まれます。もし既に Gimp が起動している状態でスクリプトをコピーしたのなら、新しいスクリプトを Gimp に読み込ませるため ''フィルタ/Script-Fu/スクリプトを再読み込み...'' をしておいて下さい。スクリプトの一部を書き換えて、その変更を反映させたいときにもスクリプトを再読み込みさせると反映できます。

さっそく作成したスクリプトを動かしてみましょう。''フィルタ/Test/Duplicate Layer...'' のメニューパスに今回新しく作ったスクリプトが登録されていると思います。これを使うと、レイヤーが複製されます (レイヤーダイアログで確認して下さい)。ちょうどレイヤーダイアログの複製ボタンを押したときと同じ動作ですね。

*** 3.3.4 中でやっていること [#l24facdc]

なぜこのようになるのか、スクリプトでやっていることについて説明します。順番が逆になってしまいますが、最後の方から見ていきましょう。(先頭の数字は、このスクリプトの空白行も含んだ最初の方からの通し行番号です)

''スクリプトの登録''

 10| (script-fu-register
 11|   "script-fu-duplicate-layer"
 12|   "Duplicate Layer..."
 13|   "description"
 14|   "name"
 15|   "copyright"
 16|   "date"
 17|   "RGB*"
 18|   SF-IMAGE     "Image"     0
 19|   SF-DRAWABLE  "Drawable"  0)
 20|
 21| (script-fu-menu-register "script-fu-duplicate-layer"
 22|                          "<Image>/Filters/Test")

script-fu-register から始まっているこの 10 行目から 19 行目までの部分は、script-fu-duplicate-layer という関数を Gimp へ登録しています。21 行目と 22 行目では script-fu-duplicate-layer という関数をメニューに登録しています。

script-fu-register による Gimp への登録は、基本的に全てのスクリプトにとって必須です。11 行目はこのスクリプトを Gimp で登録する時に指定する名前で、すでに使用済みではない名前を自分で自由に設定することができます。ただし Script-Fu のスクリプトの場合は "script-fu-" に続けてスクリプトの名前を付けるのが慣例となっています。

12 行目はこのスクリプトのコマンドのメニューでの表示名を書きます。

13 行目はこのスクリプトの説明を書きます。

14 行目はこのスクリプトの著作権情報を書きます。

15 行目はこのスクリプトを作成した日付を書きます。これらはそれぞれアルファベットで記述し、プロシージャブラウザ... で見たときに右側に表示される情報となります。

17 行目はこのスクリプトがどの画像モードで使用できるのかという設定です。RGB* となっているのは、RGB モードと RGBA モードの両方で使えることを示しています。RGB モードだけをここで指定した場合、レイヤーにアルファチャンネルがあったときにこのスクリプトを使うことができません。モード指定は RGB(RGBA) のほかに、GRAY(GRAYA)、INDEXED(INDEXEDA) があり、それぞれグレースケールとインデックスモードになります。スクリプトが対象とするモードに合わせて指定しましょう

ここから後はスクリプト本体に渡す引数になります。18 行目と 19 行目はそれぞれイメージとドロアブルを取ってくるという指定です。画像依存型スクリプトの場合、SF-IMAGE "Image" 0 と SF-DRAWABLE "Drawable" 0 の二つは必ず必要になります。これを書いておくと、その時アクティブ((アクティブになっているとは、その時選択されている状態のことを指します。例えばレイヤーが 1 枚だけの時にはアクティブになっているレイヤーは存在するそのレイヤーだけですが、レイヤーが 2 枚のときはその時編集中のレイヤーのほうが選択されている状態なので、それがアクティブなレイヤーとなります。))になっている画像 (画像ウィンドウから見える画像と考えると分かりやすいかな) と、その時アクティブになっているドロアブル (この場合はレイヤーです) の二つをスクリプト本体に渡すことができます。

21 行目と 22 行目はスクリプトをメニューに配置するための登録をやっているところです。"Duplicate Layer..." のコマンドをメニューのどの位置に置くのかというもので、画像依存型スクリプトの場合は <Image> からメニューパスを書きはじめるタイプが多くなります。

''スクリプト本体の呼び出し''

  1| (define (script-fu-duplicate-layer img layer) 

1 行目、ここからスクリプトの本体が始まります。この行は script-fu-duplicate-layer という名前の関数を定義しています。この名前はスクリプトの登録した時に 11 行目で付けた名前と同じにしなければならず、この名前の関数がスクリプトを実行した時に呼び出されることになります。

この呼び出しに続けて img と layer というものがあります。これは何かというと、前述の SF-IMAGE と SF-DRAWABLE で取ってきた画像の情報とドロアブル (レイヤー) の情報がそれぞれの変数に入っているのです。そのためスクリプトの中でアクティブな画像を取り扱いたい時は img を、レイヤーを扱いたいときは layer を使えばいいことになります。

''本体の作業''

  2|  (let* (
  3|         (copy-layer (car (gimp-layer-copy layer TRUE)))
  4|        )
  5|    (gimp-image-add-layer img copy-layer -1)
  6|    (gimp-displays-flush)
  7|  )
  8|)

スクリプト本体を呼び出したら、次は本体内部で行う作業を書きます。作業を全て書き終えたら、1行目で呼び出した (define 文の括弧を閉じなければならないので、8 行目で括弧閉じ ")" を書いてこのスクリプトを終えています。つまり 1 行目の (define (script-fu-duplicate-layer img layer) の終わりは 8 行目で、1 行目から 8 行目のこの間が実際に今回のスクリプトの処理を行っているところです。

2 行目は局所変数を使用するため let* 構文を使っています。ここで使用している局所変数は copy-layer の一つだけです。局所変数の宣言は 3 行目で行っており、4 行目の閉じ括弧はここで let* 構文の変数宣言部分が終わりであることを示す閉じ括弧です。

3 行目はレイヤーをコピーしています。今パッと見ただけでは、なぜ car を使って (car はリストの先頭の要素を取り出すことを思い出して下さい)、それを copy-layer に入れているのか分からないでしょう。

ここので重要なのは、(gimp-layer-copy layer TRUE) では何が返ってくるのかということです。''ヘルプ/Script-Fu/プロシージャブラウザ...'' を開いてみて下さい。これはレイヤーをコピーする関数で、この関数を探すために検索欄に copy と入力して検索すると下のようになります。

&ref(fu3-dbbrowser-layer-copy.png,nolink,copy の検索結果);

すると Gimp に登録されている関数で copy というキーワードに一致するものがリストアップされます。ここから gimp-layer-copy というのがレイヤーをコピーする関数だと予想がつきます。これを見てみると、入力に layer と add-alpha の二つのパラメータが必要で、出力は layer-copy だということが分かります。

layer というのは 1 行目の define で出てきた layer に入っている数値をそのまま使います。add-alpha はレイヤーにアルファチャンネルを追加するかどうかで、ここでは TRUE としておきます。

そしてなぜ 3 行目で car を使うのかという理由は、gimp-layer-copy で layer をコピーした結果はリストで返ってくるからです。そのリストの先頭にはコピーしたレイヤーの ID 番号が入っています。この ID 番号を取り出して copy-layer に入れることで、次回からは copy-layer をコピーしたレイヤーとして扱うことができるようになります。

これでレイヤーをコピーしたものが手に入ったのですが、まだコピーしたレイヤーは実際のレイヤースタックには現れていません。単にコピーしたレイヤーが Gimp 内部で作られただけなので、レイヤー階層にコピーしたレイヤーを追加する必要があります。layer で検索すると、gimp-image-add-layer が見付かります。

&ref(fu3-dbbrowser-add-layer.png,nolink,layer で検索した結果);

これには入力パラメータとして image と layer と position を必要とします。この関数は画像 image にレイヤー layer を追加するという意味ですから、image には define 行で出てくる img を、layer にはコピーしたレイヤーを指す copy-layer を使います。position はレイヤースタックのどこに置くのかという位置を指定するもので、-1 を指定すると現在アクティブになっているレイヤーの上にレイヤーが追加されます。0 を指定すると強制的にレイヤースタックの一番上に追加されます。

(gimp-displays-flush) というのは、表示を更新するための決まり文句です。ここではレイヤーをコピーして追加したので表示に変化があります。5 行目が無ければこの変化が実際の表示に反映されません。スクリプト本体の最後には必ず書くようにしましょう。

8 行目の ) の閉じ括弧は (define に対応する括弧です。ここでスクリプトの本体が終わります。忘れずに閉じるようにしましょう。


** 3.4 画像を作成するスクリプト [#new-image]

次は新規画像を作成するスクリプトを作ってみます。このスクリプトは無から画像を産み出す独立実行型のスクリプトですです。下のスクリプトを、先ほどのスクリプトと同じ要領でファイルに書き、scripts ディレクトリに入れてスクリプトを再読み込みして下さい。

*** 3.4.1 画像作成のスクリプト [#m0ac5198]

 (define (script-fu-create-new-image bg-color width height)
 
   (let* (
          (img    (car (gimp-image-new width height RGB)))
          (layer  (car (gimp-layer-new img width height RGB-IMAGE
                                       "Background" 100 NORMAL-MODE)))
         )
 
     (gimp-context-push)
 
     (gimp-context-set-background bg-color)
     (gimp-drawable-fill layer BG-IMAGE-FILL)
     (gimp-image-add-layer img layer -1)
 
     (gimp-context-pop)
     (gimp-display-new img)
     (gimp-displays-flush)
 ))
 
 (script-fu-register
  "script-fu-create-new-image"
  "New Image..."
  "description"
  "name"
  "copyright"
  "date"
  ""
  SF-COLOR      "Background color"  '(255 255 255)
  SF-ADJUSTMENT "Width"             '(256 1 1024 1 10 0 1)
  SF-ADJUSTMENT "Height"            '(256 1 1024 1 10 0 1))
 
 (script-fu-menu-register "script-fu-create-new-image"
                          "<Image>/Filters/Test")

これは ''フィルタ/Test/New Image...'' にあります。これを呼び出すと下のようなダイアログが現れます。実行すると、背景色で指定した色の背景レイヤーを持ち、大きさが幅と高さで指定したサイズのレイヤーが現れるでしょう。

&ref(fu3-script-new-image.png,nolink,New Image ダイアログ);

このスクリプトは先ほどのスクリプトよりも長いので、入力のミスなどでスクリプトの実行中にエラーを返されたりするかもしれません。再読み込みをした時にエラーを返される場合は、開き括弧と閉じ括弧が正しく対応していない時が多いようです。一文字一文字が間違っていないかよく確かめて下さい。

***3.4.2 中でやっていること [#oefea33b]

''スクリプトの登録''

 20| (script-fu-register
 21|  "script-fu-create-new-image"
 22|  "New Image..."
 23|  "description"
 24|  "name"
 25|  "copyright"
 26|  "date"
 27|  ""

今回のスクリプトの関数の名前は create-new-image にしました。これが 21 行目です。22 行目でメニュー上でのコマンド名を指定しています。23、24、25、26 行は前回と同じく、スクリプトの説明と作者の名前とスクリプトの著作権表示とスクリプトを作成した日付です。27 行目には何も指定がありませんが、これはこのスクリプトがゼロの状態から画像を作成する独立実行型のため、対象とするイメージの型を指定をする必要が無いのです。

''引数入力ボックスの作成''

 28|  SF-COLOR      "Background color"  '(255 255 255)
 29|  SF-ADJUSTMENT "Width"             '(256 1 1024 1 10 0 1)
 30|  SF-ADJUSTMENT "Height"            '(256 1 1024 1 10 0 1))
 31| 
 32| (script-fu-menu-register "script-fu-create-new-image"
 33|                          "<Image>/Filters/Test")

28、29、30 行目では、スクリプトに与える値をユーザーに指定させるダイアログを作る元となります。これは独立実行型スクリプトであり、先程の画像依存型スクリプトのように最初に SF-IMAGE と SF-DRAWABLE を必ず必要とはしません。

ここではスクリプトに渡している引数は 3 つです。SF-COLOR はユーザーに色を選ばせます。2 つの SF-ADJUSTMENT はユーザーに値を選ばせます。その結果、下のようなダイアログが自動的に作られます。

&ref(fu3-script-new-image.png,nolink,New Image ダイアログ);

28 行目の SF-COLOR の最初の文字列は、上のダイアログでいえばこの設定のラベル名です。ここでは、この色は背景色として使われることを意図しているので "Background Color" としました。その隣にはリストがあります。このリストは色を表していて、'(赤 緑 青) という風に赤/緑/青を 0 から 255 の整数で指定すると、その色がスクリプトを最初に呼び出した時のデフォルトの色になります。今回は '(255 255 255) なので白色になっています。

29 行目と 30 行目の SF-ADJUSTMENT はラベル名が "Width" と "Height" と違っている以外は同じです。ここでは新しく作る画像の大きさ (幅と高さ) をユーザーに選ばせています。リストの中の要素は 7 つ必要です。それぞれの要素が何を指定しているのか左から順番に説明します。

一番最初は、このスクリプトを呼び出した時のデフォルトの値を設定しています。その次はこの数値の範囲の最低値を指定しています。その次はこの数値の最高値を指定しています。その隣は小さいステップ幅で、その隣は大きいステップ幅です。この二つは数値を増減させた時にどのくらいずつ値が変化するのかというものです。その次は実数の精度、つまり小数点第何位までの変更を許すかで、小数点以下の数値も必要とする場合に変更します。最後の数値は、この数値選択を 0 であればスライダーで、1 であれば数値入力ボックスで行うようにします。

これらをまとめると、この数値選択ではスライダーによって 1 から 1024 までの整数を選ぶことができ、デフォルトの値は 256 である、ということです。SF-ADJUSTMENT による数値選択はよく使うので、覚えておくと良いでしょう。

''スクリプト本体の呼び出し''

  1| (define (script-fu-create-new-image bg-color width height)

このスクリプトの本体の関数の名前を script-fu-create-new-image として定義しています。これは三つの引数を必要とします。それは bg-color と width と height です。bg-color にはスクリプトを実行した時に現れるダイアログでユーザーが指定した色 (これは要素が三つのリストになっている) が入ります。width と height には幅と高さが入ります。

画像依存型スクリプトである一番はじめのスクリプトと比較した場合、独立実行型スクリプトでは画像の img とレイヤーの layer を受け取る必要がないことに注意して下さい。

''画像とレイヤーの作成''

  3|   (let* (
  4|          (img    (car (gimp-image-new width height RGB)))
  5|          (layer  (car (gimp-layer-new img width height RGB-IMAGE
  6|                                       "Background" 100 NORMAL-MODE)))
  7|         )

このスクリプトは新しい画像を作るのですが、まだ何も存在しない状態なので、はじめに画像と画像上に存在するレイヤーが一つづつ必要です。新しく作成した画像にはレイヤーが無いのです。画像とレイヤーを最初に作ることにします。

&ref(fu3-dbbrowser-image-new.png,nolink,gimp-image-new の入出力);

4 行目では新しい画像を作っています。プロシージャブラウザで gimp-image-new を見てみると、入力に width と height と type が必要となっています。出力の返り値は image となっています。つまり新しく作成する画像の幅と高さと種類 (画像のモード: RGB、グレースケール、インデックス) を与えてやれば、その条件で作られた画像が返ってくるというわけです。画像の種類は RGB なので、RGB を指定してやります。

gimp-image-new 関数を呼び出した時の返り値はリストになっているので、この先頭を car で取り出してやります。これで新しく作成した画像の ID が手に入ります。この画像 ID を img に入れてやります。これで img が新しく作成した画像を指すことになります。

&ref(fu3-dbbrowser-layer-new.png,nolink,gimp-layer-new の入出力);

画像を作成しただけではまだ画像の中にレイヤーが存在しないので、次はレイヤーを新しく作ります。5 行目の gimp-layer-new 関数は沢山の入力が必要です。そして出力として新しく作成したレイヤーを返します。

image は、どの画像にレイヤーを作るのかを指定します。ここでは作ったばかりの img を使います。width と height はレイヤーの幅と高さです。画像の時の幅と高さと同じなので、ユーザーが指定した width と height になります。type はレイヤーの種類です。アルファチャンネル (A) 無しの RGB イメージでよいので、RGB-IMAGE を指定しています。

name はレイヤーの名前で、文字列なので "" で左右を囲みます。opacity はレイヤーの不透明度で、レイヤーダイアログにあるレイヤー不透明度のスライダーが表すものと同じです。mode はレイヤーの結合モードで、レイヤーダイアログにあるレイヤーモードに相当します。標準モードは NORMAL-MODE と指定します。

このような指定で作成されたレイヤーの結果は、やはりこれもリストで返ってくるので car で先頭を取り出してやる必要があります。そして取り出したレイヤー ID を layer に入れています。これで layer が新しく作成したレイヤーを指すようになりました。

''前処理''

  9|     (gimp-context-push)

9 行目では、その時点でのコンテキストを Gimp に記憶させています。「コンテキストを記憶する」というのは、例えばその時に使用中のブラシやパターンや描画色/背景色などを記憶するということです。次の 11 行目の処理で背景色を変更してしまうので、変更前の状態を記録しておきたいのです。

''画像にレイヤーを入れる''

 11|     (gimp-context-set-background bg-color)
 12|     (gimp-drawable-fill layer BG-IMAGE-FILL)
 13|     (gimp-image-add-layer img layer -1)

11 行目は背景色の色を変更しています。bg-color はスクリプトを実行した時にユーザーが指定した色です。もし bg-color に何が入っているのか忘れてしまったら、このスクリプトの説明の最初の方に戻りましょう。

12 行目の gimp-drawable-fill では、引数として与えた layer を 11 行目でセットした色の bg-color で塗す作業を行っています。この作業は背景の色をセットするという意味だけではなく、レイヤーの状態を初期化するという意味も持っています。なぜかというと、大抵新しく作成したレイヤーは初期化されていなくてランダムな模様が描かれているからです。そのため新規レイヤーを作成した時には gimp-drawable-fill の呼び出しでレイヤーを初期化してやる必要があります。色で塗りつぶすのではなく、透明((透明で塗りつぶす場合にはレイヤーの種類が RGBA などアルファチャンネルを持った状態である必要がある))で塗りつぶしたい場合には TRANS-IMAGE-FILL を塗りつぶしタイプに与えてやります。

この時点ではまだ画像にレイヤーはありません。そのため 13 行目で実際に画像にレイヤーを追加しています。gimp-layer-add-layer の説明は最初のスクリプトでしているので、そちらを参照して下さい。
この時点ではまだ画像にレイヤーはありません。そのため 13 行目で実際に画像にレイヤーを追加しています。gimp-image-add-layer の説明は最初のスクリプトでしているので、そちらを参照して下さい。

''後処理''

 15|     (gimp-context-pop)
 16|     (gimp-display-new img)
 17|     (gimp-displays-flush)
 18| ))

現在の背景色を 11 行目で変更してしまっため、スクリプトを呼び出す前とは違っているかもしれません。15 行目ではこれを 9 行目で gimp-context-push した時の状態に元に戻しています。このようにスクリプトの途中で変化してしまった状態をできるだけスクリプトの実行前の状態に戻しておくことがお勧めです。

16 行目では作成した画像をディスプレイに出現させています。画像を新しく作成しても gimp-display-new を使うまでは実際のディスプレイには表示されません。これはレイヤーを作成しても gimp-image-add-layer を使うまでは実際に画像にレイヤーが現れないことと同じです。新規画像を作成するタイプのスクリプトでは、新規画像の表示のためにこの呼び出しが必要になります。

17 行目はディスプレイの更新です。18 行目で (let* と (define で始まった終わりの括弧の二つがあります。


** 3.5 ドロップシャドウ文字を作るスクリプト [#drop-shadow]

上の二つのスクリプトは、画像依存型スクリプトと独立実行型スクリプトの例として基本的な部分しか持っていない非常に簡単なスクリプトでした。しかしこれではお世辞にも実用的であるとは言えません。もう少し実際に使えるスクリプトとして、ドロップシャドウを作るスクリプトを作ります。これも簡単なスクリプトですが、これができればもうスクリプトの書き方の基本はマスターしたことになるので、他のスクリプトを書くことができるようになります。

*** 3.5.1 手順の確認 [#mcf8e712]

まずスクリプトの前に、そのような手順でドロップシャドウ文字を作るのかを Gimp でやってみます。それを元にスクリプトを書き起こすようにすると、スクリプト作成の流れが分かって効率が良くなります。

+新規画像作成
+テキストを入力して文字レイヤーを作る
+上の文字レイヤーと同じ条件で、色だけ変えてシャドウレイヤーを作る
+文字レイヤーとシャドウレイヤーを反対方向に少しずらす
+シャドウレイヤーをガウシアンぼかしでぼかす
+シャドウレイヤーの不透明度を少し落とす 

*** 3.5.2 ドロップシャドウ文字のスクリプト [#c4fb6dc6]

このスクリプト中のセミコロン ";" で始まる行はコメント扱いになり、スクリプトの実行には影響を及ぼしません。スクリプトがある程度長くなったら、その部分が何の処理をやっているのかをコメント行として書いておくと、後でスクリプトを見たときに分かりやすくなります。

         ;; ドロップシャドウを作るスクリプト
 (define (script-fu-drop-shadow-text text size font bg-color text-color)
 
         ;; 変数宣言
   (let* ((img          (car (gimp-image-new 256 256 RGB)))
          (text-layer   0)
          (width        0)
          (height       0)
          (bg-layer     0)
          (shadow-layer 0))
 
         ;; 前処理
      (gimp-image-undo-disable img)
      (gimp-context-push)
 
         ;; テキストレイヤー作り
      (gimp-context-set-foreground text-color)
      (set! text-layer (car (gimp-text-fontname img -1 0 0 text 20
                                                TRUE size PIXELS font)))
 
         ;; 背景レイヤー作り
      (set! width  (car (gimp-drawable-width  text-layer)))
      (set! height (car (gimp-drawable-height text-layer)))
      (gimp-image-resize img width height 0 0)
      (set! bg-layer (car (gimp-layer-new img width height RGB-IMAGE
                                          "Background" 100 NORMAL-MODE)))
      (gimp-image-add-layer img bg-layer 1)
      (gimp-context-set-background bg-color)
      (gimp-edit-clear bg-layer)
 
         ;; ドロップシャドウの作成
      (gimp-context-set-foreground '(0 0 0))
      (set! shadow-layer (car (gimp-text-fontname img -1 0 0 text 20
                                                  TRUE size PIXELS font)))
      (gimp-channel-ops-offset shadow-layer FALSE OFFSET-TRANSPARENT 5 5)
      (gimp-channel-ops-offset text-layer FALSE OFFSET-TRANSPARENT (- 5) (- 5))
      (plug-in-gauss-iir2 1 img shadow-layer 20 20)
      (gimp-layer-set-opacity shadow-layer 75)
 
         ;; 後処理
      (gimp-context-pop)
      (gimp-image-undo-enable img)
      (gimp-display-new img)
      (gimp-displays-flush)
 ))
 
         ;; スクリプトの登録
 (script-fu-register
  "script-fu-drop-shadow-text"
  "Drop Shadow Text..."
  "Create the drop shadow text"
  "Iccii <iccii@hotmail.com>"
  "Iccii"
  "Jun, 2001/May, 2009"
  ""
  SF-STRING     "Text"               "Script-Fu!"
  SF-ADJUSTMENT "Font size (pixels)" '(100 2 1000 1 10 0 1)
  SF-FONT       "Font"               "Dragonwick"
  SF-COLOR      "Background color"   '(255 255 255)
  SF-COLOR      "Text color"         '(223 8 8))
  
 (script-fu-menu-register "script-fu-drop-shadow-text"
                          "<Image>/Filters/Test")


このスクリプトを動かすと下のようなダイアログが出てきます。先程よりも文字とフォントを選択させるボックスが増えていますね。スクリプトの機能が色々と増えていっており、柔軟になってきましたね。

&ref(fu3-scriptfu-drop-shadow.png,nolink,ドロップシャドウ文字のダイアログ);

*** 3.5.3 中でやっていること [#jaf1aaef]

''登録と始まり''

  1|         ;; ドロップシャドウを作るスクリプト
  2| (define (script-fu-drop-shadow-text text size font bg-color text-color)

 47|         ;; スクリプトの登録
 48| (script-fu-register
 49|  "script-fu-drop-shadow-text"
 50|  "Drop Shadow Text.."
 51|  "Create the drop shadow text"
 52|  "Iccii <iccii@hotmail.com>"
 53|  "Iccii"
 54|  "Jun, 2001/May, 2009"
 55|  ""
 56|  SF-STRING     "Text"               "Script-Fu!"
 57|  SF-ADJUSTMENT "Font size (pixels)" '(100 2 1000 1 10 0 1)
 58|  SF-FONT       "Font"               "Dragonwick"
 59|  SF-COLOR      "Background color"   '(255 255 255)
 60|  SF-COLOR      "Text color"         '(223 8 8))
 61|
 62| (script-fu-menu-register "script-fu-drop-shadow-text"
 63|                          "<Image>/Filters/Test")

最初にスクリプトの登録と、本体の呼び出しのところから説明します。このスクリプトの関数名は script-fu-drop-shadow-text です。入力ボックスが増えていますが、基本的にはこれまでと何ら変わりはありません。

ここで入力ボックスでユーザーに指定させている値は、ロゴとして使用する文字と (56 行目)、文字の大きさと (57 行目)、フォントの種類と (58 行目)、背景と文字の色です (59、60 行目)。これを 2 行目の define のところでそれぞれ text size font bg-color text-color の引数としてスクリプト本体に渡しています。

''変数宣言''

  4|         ;; 変数宣言
  5|   (let* ((img          (car (gimp-image-new 256 256 RGB)))
  6|          (text-layer   0)
  7|          (width        0)
  8|          (height       0)
  9|          (bg-layer     0)
 10|          (shadow-layer 0))

変数は使用する前に、使う変数を宣言する必要があります。宣言のときに初期値を与えられる場合は先に与えておき、初期値を与えられない場合は 0 を仮代入しておいて((必ずしも仮代入しておく必要はない))、後で set! 構文を使用して値を代入するという方法を使います。

最初に画像を作ります。RGB モードで、256x256 の大きさにします。ここで大きさを打ち決めしてしまっているのは、後で画像の大きさ (キャンバスサイズ) を再変更するからです。この時点では画像 img を先に作ってしまう必要があります。

なぜ先に画像 img を作ってしまう必要があるかといえば、gimp-text-fontname で文字のレイヤーを作るには、文字レイヤーを入れる場所となる画像が先に存在している必要があるからです。

''前処理''

 12|         ;; 前処理
 13|      (gimp-image-undo-disable img)
 14|      (gimp-context-push)

13 行目は、アンドゥスタックを無効にする関数です。これについては後述します。14 行目はコンテキストの保存を行っています。

''画像とロゴレイヤー作り''

 16|         ;; テキスト作り
 17|      (gimp-context-set-foreground text-color)
 18|      (set! text-layer (car (gimp-text-fontname img -1 0 0 text 20
 19|                                                TRUE size PIXELS font)))

gimp-text-fontname を呼び出すと、その時点での描画色を使って文字レイヤーを作ります。文字を作る前に描画色の色を指定した文字の色に変更しておかなければならないので、直前の 17 行目で gimp-context-set-foreground を呼び出しています。

gimp-text-fontname 関数は指定した大きさのフォント (ここでは size) で文字列 text の文字が入ったレイヤーを作ります。ここでは上下左右に 20 ピクセルだけの余白があるような大きさを自動的に計算してレイヤーを作ってくれます。そのためフォントサイズを大きくしても常に 20 ピクセルの余白があるテキストレイヤーができます。

''リサイズと背景レイヤー作り''

 21|         ;; 背景レイヤー作り
 22|      (set! width  (car (gimp-drawable-width  text-layer)))
 23|      (set! height (car (gimp-drawable-height text-layer)))
 24|      (gimp-image-resize img width height 0 0)
 25|      (set! bg-layer (car (gimp-layer-new img width height RGB-IMAGE
 26|                                          "Background" 100 NORMAL-MODE)))
 27|      (gimp-image-add-layer img bg-layer 1)
 28|      (gimp-context-set-background bg-color)
 29|      (gimp-edit-clear bg-layer)

この時点で画像にはテキストレイヤーが存在するのですが、画像の境界の大きさと文字レイヤーの境界の大きさは一致していません。文字レイヤーの境界の大きさを求めて、画像の大きさを文字レイヤーの大きさに合わせなければなりません。gimp-drawable-width/height でドロアブルの大きさを求めることができます。そして gimp-image-resize で画像の大きさを再変更しています。

このように、テキストの大きさに応じたサイズの画像を作りたい場合は、''gimp-image-new で任意の大きさの画像を仮に作っておき → テキストレイヤーを作ってサイズを自動作成してもらう → テキストレイヤーの大きさを調べて → gimp-image-resize で画像の大きさを再変更'' という一連の流れは定番なので覚えておくといいです。

まだ画像には文字レイヤーだけしか存在せず、ドロップシャドウのレイヤーと背景レイヤーが存在していません。そのため背景レイヤーから作ることにしましょう。gimp-image-add-layer で背景レイヤーを追加する場所は一番下ですから position には 1 を与えてやります。

''ドロップシャドウレイヤー作り''

 31|         ;; ドロップシャドウの作成
 32|      (gimp-context-set-foreground '(0 0 0))
 33|      (set! shadow-layer (car (gimp-text-fontname img -1 0 0 text 20
 34|                                                  TRUE size PIXELS font)))
 35|      (gimp-channel-ops-offset shadow-layer FALSE OFFSET-TRANSPARENT 5 5)
 36|      (gimp-channel-ops-offset text-layer FALSE OFFSET-TRANSPARENT (- 5) (- 5))
 37|      (plug-in-gauss-iir2 1 img shadow-layer 20 20)
 38|      (gimp-layer-set-opacity shadow-layer 75)

ドロップシャドウのレイヤーを作る方法はいくつか考えられますが、今回は文字レイヤーと全く同じようにして (但し色だけは影っぽく黒に変えて) 作ることにしました。そうすると文字レイヤーと同じ場所に重なるようにしてシャドウレイヤーができます。

文字と影がピッタリと重なっているのはまずいので、gimp-channel-ops-offset でそれぞれ右上と左下に少しだけずらして距離を作りました。そしてシャドウレイヤーにガウシアンぼかし (IIR) をかけました (37 行目)。この状態ではまだシャドウがクッキリしすぎているので、レイヤーの不透明度を 75% に下げておきました (38 行目)。


''後処理''

 40|         ;; 後処理
 41|      (gimp-context-pop)
 42|      (gimp-image-undo-enable img)
 43|      (gimp-display-new img)
 44|      (gimp-displays-flush)
 45| ))

後処理は大体どのスクリプトでもそれほど変わらないようです。コンテキストの状態をスクリプト実行前に戻して、ディスプレイを更新します。

*** 3.5.4 アンドゥ [#gimp-image-undo]

より本格的なスクリプトを書くなら、アンドゥ処理にも留意するようにしましょう。今回のスクリプトでアンドゥ処理を行っているのはこの二行です。

 13|      (gimp-image-undo-disable img)
 
 42|      (gimp-image-undo-enable img)

これは画像 img の処理をアンドゥスタックに追加しない/するというものです。はじめにアンドゥを無効にし、後で有効にしています。つまり、13 行目の gimp-image-unod-disable から 42 行目の gimp-image-undo-enable で囲まれたところまでの処理がアンドゥされないということです。

もしこのアンドゥ処理を行わなければ、スクリプトを実行した後の画像でアンドゥ操作 (Ctrl-Z) をした時には、一回分の処理づつ画像の状態が戻っていきます。通常これは好ましいことではありません。そのためスクリプトの実行中にはアンドゥができないようにしているのです。

しかし、あるひとまとまりの処理を一度のアンドゥ操作で行いたいという場合もあります。アンドゥ操作によって画像のある状態に戻りたいような時です。そのための関数も用意されています。

>(gimp-image-undo-group-start img)
> 
>(gimp-image-undo-group-end img) 

これは画像 img において gimp-image-undo-group-start から gimp-image-undo-group-end までに行った処理を一回のアンドゥ操作で行えるようにグループ化するものです。つまり、この間に挟まれた処理は一回の処理としてアンドゥスタックに収められるのです。アンドゥ (Ctrl-Z) すると gimp-image-undo-group-start を呼び出した時点に戻ることができます。


*** 3.5.5 プラグインの呼び出し方法 [#w848b28c]

これまでのスクリプトの作業ではすべて GIMP 本体で用意されている関数だけを使っていましたが、37 行目では初めて plug-in-gauss-iir2 プラグインを呼び出しています。プラグインは GIMP 本体とは別のプログラムですが、プラグインを利用する場合も GIMP 本体が提供している関数とほとんど同じように利用することができます。

プラグインを呼び出す場合にこれまでと違う点は、インタラクティブに呼び出すのか、非インタラクティブに呼び出すのかという違いです。

:インタラクティブモード|プラグインを呼び出すと、パラメータ入力のためのダイアログが出る
:非インタラクティブモード|パラメータ入力のためのダイアログは出ず、プラグインを呼び出すときにはパラメータをしっかりと指定してやる必要がある

通常プラグインを呼び出すときには非インタラクティブモードを利用するのが一般的で、そのためきちんとパラメータを与えてやる必要があります。
インタラクティブモードで呼び出すときには ''0'' を、非インタラクティブモードで呼び出すときには ''1'' を指定します。0 と 1 の代わりに ''RUN-INTERACTIVE'' と ''RUN-NONINTERACTIVE'' を使うこともできます。

プラグインを呼び出すときの一般的な書式:

> (plug-in-[プラグイン名] run-mode image drawable paramaters ...)

run-mode がインタラクティブモードで呼び出すのかどうかで、image、dawable、に続いて引数がいくつか続く場合が多いです。どの引数が必要なのかをプロシージャブラウザでしっかりと確認しておきましょう。


** 3.6 スクリプトの発展 [#ke362b66]

今回のドロップシャドウ文字のスクリプトは、それほど良いものではありません。文字の大きさをデフォルトよりも大きくした時、文字と比べて影のバランスが悪くなってしまいます。背景と文字の色が一色づつというのも単調ですね。

シャドウレイヤーを色々と細かく調節することができるようにしたり、文字や背景にグラデーションやパターン塗りが行えるように、等の工夫でスクリプトを発展させてみて下さい。ここで発展例を書くこともできますが、これはあなたへの宿題としておきます。是非挑戦してみて下さい。

グラデーションやパターンを使った時には、色を変更した時にやったように、スクリプトの実行の前後でグラデーションやパターンが元に戻るようにしてみて下さい。それほど難しくはないと思います。

-----

CENTER:[[二限目>ScriptFuClass/Step2]] | [[Script-Fu 青空教室>ScriptFuClass]] | [[四限目>ScriptFuClass/Step4]]

Backup   RSS of recent changes