GIMP Script-Fuによる自動化入門

gimp-script-fu

GIMPを自動化して画像処理を楽にしたいけど、Lispという難しいプログラミング言語を使う上に、どこを探してもイージーなハウツーが見つからない。
所詮お絵描きソフトなんだから自動化のスクリプトって簡単に決まってるでしょ。

と、かじってはみたものの、深みにはまって何もできずもう挫折するしかなくなった人(大昔の私です)。
そんな人向けにイージーなGIMPの自動化の入門記事を作成中です。

本記事はまだまだ追記します。

スポンサーリンク

1. GIMP自動化のための事前準備

1-1. 入門でいきなりGIMP制御

入門者にスクリプトの説明から入るのは大間違い! 関数型言語を知らない人からすると、すっごく怖いんです、Lisp。
だから最初の最初は、恐怖感を少しでも和らげるため、いきなりGIMP制御してしまった方がいいんです。

直接コマンド入力してGIMP制御してみましょう。
本記事を上から順に読んでいけば、意外とあっさりGIMP制御できてしまうことに驚くと思います。

まずはGIMP。これを起動しないと始まりません。

GIMPが起動できたら、メニューから「フィルター(R)」ー「Script-Fu(S)」ー「Script-Fu コンソール(C)」を選択します。

以下のようなScript-Fuコンソールと呼ばれるコマンド入力ダイアログが表示されます。

このダイアログの下の方にある長細い四角にコマンドを入力することで、GIMPが制御できます。

早速簡単な制御をしてみましょう。
「(gimp-quit TRUE)」と入力し、Enterキーを押します。

GIMPアプリケーションが終了しました。

さきほど入力した「(gimp-quit TRUE)」は、GIMPを終了するための記述です。
()で囲われた独特な記述スタイルですが、これこそがLispの特徴です。
このような書式になっています。

(関数名 引数)

つまり「(gimp-quit TRUE)」の、gimp-quitが関数名、TRUEが引数ってことになります。

この簡単なルールさえ分かってしまえば、Lispって言語も案外簡単かもしれませんね。

1-2. Lisp(Scheme)に慣れる

Lispプログラミングに慣れておかないと、自動化を始めようとしても、書けもしないし読めもしないから散々時間をつかって徒労に終わる可能性大ですので、回り道でもしっかり覚えておきましょう。

Lisp(Scheme)のプログラムは、すべてリストの形で記述します。リストは()で表現し、リストの要素は空白で区切って()の中に以下のように並べます。

(要素1 要素2 要素3 ...)

これだけでは、プログラムの実行すらできないので、もう一つルールがあります。

リストの先頭の要素には関数を置き、以降の要素はその関数の引数を連ねます。

(関数名 引数1 引数2 ...)

関数によっては、引数が不要な場合もありますから、要素が一つ、つまり関数名しかない場合もあります。

(関数名)

ルールが分かったところで、簡単な足し算から実行してみます。
10 + 20の計算を行うには、Script-Fuコンソールで、

(+ 10 20)

と入力します。

Enterを押すと、結果が上方に表示されます。

もっとたくさんの数を足したい場合は、空白で区切って引数を並べれば良いだけです。

>(+ 1 2 3 4 5 6 7 8 9 10)
55

簡単な計算

足し算・・・は先ほどやりましたね。

>(+ 10 20)
30

引き算

>(- 50 15)
35

掛け算

>(* 3 4)
12

割り算

>(/ 100 8)
1.25

その他の計算
関数が用意されているので、たとえばべき乗ならpowを実行します。

>(pow 2 3)
8

混合
一種類の計算だけしかできないわけではなく、実行結果を組み合わせることで複雑な計算もできます。

>(* (pow 2 3) (- (/ 10 5) -5))
56

関数、変数の束縛

値を変数に紐つけることができます。いつも思いますが変数ではなく定数と呼ぶのが正解かもしれません。

>(define a 100)
a

これでaに100が束縛されました。

>a
100

関数の定義方法は少々複雑です。

>(define (f x) (+ 100 x))
f

これでfが定義されました。

>(f 30)
130

ローカル変数、というか局所的に変数を束縛するにはletを使います。
このように使います。

(let (このブロックで変数定義) (このブロックで定義した変数を使用))

変数aと変数bを定義して、aとbを足してみます。

>(let ((a 10) (b 20)) (+ a b))
30

リストと操作

リストはlist関数で作ることができます。

(list 10 20 30)

でもこれだとせっかくのリストが再利用できませんので、変数に束縛しましょう。

>(define a (list 10 20 30))
a

これでaに定義したリストが使えます。リストの先頭を取得してみましょう。car関数を使います。

>(car a)
10

carはリストの先頭要素を取得する関数です。carでわかりにくいなら、headも使えます。

>(head a)
10

次は、先頭以外のリストを取得。cdrを使います。

>(cdr a)
(20 30)

cdrはリストの先頭要素を除いたリストを取得する関数です。同じくcdrでわかりにくいならtailを使えます。

>(tail a)
(20 30)

1-3. プロシージャーブラウザ

メニューから「ヘルプ(H)」ー「プロシージャーブラウザ(B)」を選択します。

プロシージャーブラウザが起動し、プロシージャー(関数)の一覧が表示されました。

検索窓に関数名を入力すると、絞り込みされて知りたい関数の仕様がすぐに確認できます。

例えばgimp-quit(上画像)関数の引数の仕様を知りたい場合は、「パラメーター」を読みます。
「force INT32 Force GIMP to quit without asking (TRUE of FALSE)」
と記載されていますが、最初の「force INT32」が、パラメーター名と型になります。
続く「Force GIMP to quit without asking (TRUE of FALSE)」がこのパラメーターの説明です。
つまりTRUEを指定するとGIMPを強制終了し、FALSEを指定すると、確認メッセージを表示してくれるってことです。
本当にそうなっているか確認してみましょう。

GIMP起動後にまだ編集中の画像がない場合は、gimp-quitで TRUEを指定してもFALSEを指定しても挙動は変わらず、共に確認メッセージを表示せず強制終了します。
なので、TRUEとFALSEの違いを確認するには、編集中の画像を用意しなければなりません。
「新しい画像」を作成しましょう。

キャンバスサイズは適当で良いです100、100にしておきましょうか。

キャンバスが表示されたら、ブラシ等で絵を書きます。

メニューから「フィルター(R)」ー「Script-Fu(S)」ー「Script-Fu コンソール(C)」を選択します。

Script-Fu コンソールで、「(gimp-quit FALSE)」を入力してEnter。

(#t)が戻ってきただけで、何も変わっていないように見えます。

Script-Fu コンソールの裏に、確認メッセージが隠れていました。
(gimp-quit FALSE)を実行したため、GIMPの強制終了ではなく、確認メッセージが表示されることは確認できました。
「キャンセル」を選択しましょう。

次は、「gimp-quit TRUE」を入力してENTER。

GIMPのウィンドウがきれいさっぱりなくなりました。

gimp-quitにTRUEを指定したことにより、GIMPアプリケーションの強制終了になることを確認できました。

2. GIMP自動化への最初の一歩

Lispやプロシージャーについて軽く理解できたので、次はGIMP自動化への最初の一歩を踏み出してみましょう。

2-1. コンソールで基本関数を覚える

いきなりテキストファイルにLispを記述して覚えるのではなく、コンソールから対話式で基本的な関数を覚えていく方が上達が早いです。

画像リスト(gimp-image-list)

gimp-image-listには、編集中の画像の数と、画像IDのリストが格納されています。
プロシージャーブラウザで、gimp-image-listを検索して仕様を確認してみましょう。

書式
(gimp-image-list)

戻り値
プロシージャーブラウザでは「返り値」と表現されていますが、本記事では「戻り値」という言葉で統一します。
戻り値に以下の2つの要素のリストが返ります。
(num-images images-ids)

num-images 画像の数
image-ids 画像IDのリスト

Script-Fuコンソールでgimp-image-listを実行すると、

>(gimp-image-list)
(0 #())

GIMP起動直後は、編集画像がない状態ですので、

num-imagesが、0
image-idsが、#()、つまり空リストなので、画像IDなし

が返ってきました。

画像新規生成(gimp-image-new)

関数を使って画像の新規作成をしてみましょう。
画像を作成するには、gimp-image-newを使います。
プロシージャーブラウザでを確認すると、

書式
(gimp-image-new width height type)

width 幅
height 高さ
type 画像種類

戻り値
(image)

imageは、画像IDです。

Script-fuコンソールで、それぞれの引数を適当に指定してgimp-image-newを実行すると、

GIMPのメインのウィンドウを見ても、何の変化もなく、画像作成されてる様子はありません。
実は、新規作成した画像は、内部で生成されており、まだ画面上には表示されていません。

ここで、gimp-image-newの戻り値を確認してみます。

>(gimp-image-new 50 50 RGB)
(1)

(1)が返っていますね。この数字は画像IDです。画面上に生成された画像を表示するために使います。

画像表示(gimp-display-new)

作成した画像を画面に表示するには、gimp-display-newを使います。
関数仕様は以下のとおり。

書式
(gimp-display-new image)

image 画像ID

戻り値
(display)

display ディスプレイID

引数は1つで、gimp-image-newで作成した画像IDを指定します。
実行してみましょう。

(gimp-display-new 1)
(1)

ようやく画像がGIMPのウィンドウ上に現れました。

では続けて画像を追加していきましょう。

(gimp-image-new 100 10 RGB)
(2)
(gimp-display-new 2)
(1)


タブが追加されて、長細い画像が表示されました。

レイヤー生成(gimp-layer-new)

生成した画像を表示することはできました。しかし、空の画像のままではお絵かきができません。
レイヤーを生成してみましょう。gimp-layer-newを使います。

書式
(gimp-layer-new image width height type name opacity mode)

image 画像ID
width 幅
height 高さ
type レイヤー種別
name 名前
opacity 不透明度
mode モード

戻り値
(layer)

layer レイヤーID

実行します。

(gimp-layer-new 1 50 50 RGB-IMAGE "レイヤー" 100 LAYER-MODE-NORMAL)
(3)

戻り値に(3)が返ってきたので、今生成されたレイヤーIDは3になります。

レイヤー追加(gimp-image-insert-layer)

さらに、生成したレイヤーを追加して初めて画像にレイヤーが加わります。
レイヤーの追加は、gimp-image-insert-layerを使います。

書式
(gimp-image-insert-layer image layer parent position)

image 画像ID
layer レイヤーID
parent 親レイヤーID なしの場合0
position 追加レイヤー位置(0を指定すると一番上)

戻り値
成功した場合(#)が返ります。

(gimp-image-insert-layer 1 3 0 0)

塗り潰し(gimp-drawable-fill)

レイヤーが追加できたので、塗り潰してみましょう。

塗り潰しには、gimp-drawable-fillを使います。

書式
(gimp-drawable-fill layer fill-type)

layer レイヤーID
fill-type 塗り潰しの種類

fill-typeは、以下のいずれかです。
FILL-FOREGROUND
FILL-BACKGROUND
FILL-WHITE
FILL-TRANSPARENT
FILL-PATTERN

戻り値
成功した場合(#)が返ります。

(gimp-drawable-fill 3 FILL-WHITE)

2-2. もっと覚えたい関数

まだ理解が足りないって人は、他の関数もコンソールから使ってみましょう

直線を描く(gimp-pencil)

gimp-pencil関数で直線が描けます。

書式
(gimp-pencil drawable num-strokes strokes)

drawable 描画範囲(レイヤーID)
num-strokes strokesの要素数
strokes 座標リスト

座標リストは、(x1 y1 x2 y2 … xn yn)
と指定します。このリストの要素数をnum-strokesで指定します。

GIMP起動後の「新しい画像」で100,100のキャンバスで、本関数を実行してみます。

(gimp-pencil 2 8 #(20 20   20 80   80 20   80 80))

画像の拡大縮小(gimp-image-scale)

書式
(gimp-image-scale image new-width new-height)

image 画像ID
new-width 拡大縮小後の画像の幅
new-height 拡大縮小後の画像の高さ

(gimp-image-scale 1 200 200)

画像切り取り(gimp-image-crop)

書式
(gimp-image-crop image new-width new-height offx offy)

image 画像ID
new-width 切り取り後の画像の幅
new-height 切り取り後の画像の高さ
offx 切り取る左上位置のx座標
offy 切り取る左上位置のy座標

(gimp-image-crop 1 180 60 0 70)

画像リサイズ(gimp-image-resize)

書式
(gimp-image-resize image new-width new-height offx offy)

image 画像ID
new-width リサイズ後の画像の幅
new-height リサイズ後の画像の高さ
offx x座標オフセット位置
offy y座標オフセット位置

(gimp-image-resize 1 200 200 0 0)

3.初めてのGIMPスクリプト

3-1.テンプレを実行する

Lispに慣れてGIMPの関数にも慣れてきたところで、はじめてのスクリプトファイルを作って、GIMPから実行してみましょう。

最初にスクリプトファイルを作成します。

何も考えず以下の内容のテキストを、my-script.scmというファイル名で保存してください。
ここでは「/Users/takk/GIMP」に格納するものとしますので、自環境に合わせて読み替えてください。

(define (my-script) (gimp-quit TRUE))

(script-fu-register
  "my-script"              ;関数名
  "まいスクリプト"           ;メニューラベル
  "GIMPを終了します。"       ;description
  "takkete"                ;作成者
  "copyright 2020 takkete" ;コピーライト
  "May 28, 2020"           ;作成日付
  ""                       ;image type that the script works on
)
(script-fu-menu-register "my-script" "<Image>/File/Create")

次にスクリプトフォルダを準備します。
GIMPメニューの「設定」から「GIMPの設定」ウィンドウを表示します。

左に設定項目のブラウザ、中央から右にかけて設定値が表示されています。

左の設定項目のブラウザをスクロールし、フォルダの+をクリックしサブ項目を開き、スクリプトを選択します。

さきほど保存したスクリプトが格納されているフォルダを追加します。

では、テンプレスクリプトを読み込んで実行してみましょう。

メニューの「フィルター(R)」-「Script-Fu(S)」から「スクリプトを再読み込み(R)」をクリックします。

これで作成したスクリプトファイルがGIMPに読み込まれました。

メニューから「ファイル(F)」-「画像の生成(T)」を選択すると、出現していると思います。「まいスクリプト」

実行するとgimp-quitを実行しますので、GIMPが終了します。

3-2.テンプレを改造して絵を描く

さきほと実行したテンプレスクリプトに修正を加えて、キャンバスに絵を描いてみます。

my-script関数の内容を変更します。
gimp-quitを削除して、代わりに、begin関数から始まる、処理の羅列になっています。
begin関数は、引数で与えた処理を一つずつ実行してくれる関数です。
Lispに慣れていない人は、これがあれば怖いものなしの関数です。

(define (my-script)
  (begin
    (define img (car (gimp-image-new 480 320 RGB)))
    (define lyr (car (gimp-layer-new img 480 320 RGB-IMAGE
       "レイヤー" 100 LAYER-MODE-NORMAL)))
    (gimp-image-insert-layer img lyr 0 0)
    (gimp-drawable-fill lyr FILL-WHITE)
    (gimp-context-set-brush-size 40)
    (gimp-pencil lyr 8 #(40 40   40 280   440 40   440 280))
    (define dsp (car (gimp-display-new img)))))


(script-fu-register
  "my-script"                ;関数名
  "まいスクリプト"           ;メニューラベル
  "GIMPを終了します。"       ;description
  "takkete"                  ;作成者
  "copyright 2020 takkete"   ;コピーライト
  "May 28, 2020"             ;作成日付
  ""                        ;image type that the script works on
)
(script-fu-menu-register "my-script" "<Image>/File/Create")
"my-script.scm" 23L, 845C 書込み

上記の内容で、my-script.scmファイルを更新後、さきほどと同じように再読み込みしてから「まいスクリプト」を実行すると、以下のような画像が表示されます。

コメント

タイトルとURLをコピーしました