Archive for February, 2010
Script-Fu の解説続き
前回に引き続いて実際に公開してる[複数の画像からパターンを一括作成]を用いてのScript-Fuの解説です。
今回はメインの処理部分を見ていきます。
(define (script-fu-fe-layers-to-patterns img drawable dir) (map (lambda (layer) (let* ((basename (remove-extension (car (gimp-drawable-get-name layer)))) (filename (concat dir "/" basename ".pat"))) (file-pat-save 1 img layer filename basename basename))) (vector->list (cadr (gimp-image-get-layers img)))))
define で関数の定義
まず、一行目。
(define (script-fu-fe-layers-to-patterns img drawable dir)
この define を使うことにより新しい関数を定義できます。
引数の一つ目が関数の名前、ここでは script-fu-fe-layers-to-patterns になっています。
その後ろについてる img, drawable, dir の3つが引数ですね。
これは前回の script-fu-register で使った SF-IMAGE, SF-DRAWBLE, SF-DIRNAME を受け取ってます。
そうそう、関数名は頭に script-fu- が付けることが決まってるそうです。
あとは他のスクリプトと被らないようにだけ気をつけて適当に命名してください。
便利な map の使い方
(map (lambda (layer)
ここがとっつきにくいポイントなので、map を使った簡単な例を紹介ます。
(map + '(1 2 3) '(4 5 6))
では、GIMPを立ち上げてメニューの[フィルタ]→[Script-Fu]→[コンソール]を開いて
上のコードを入力欄にいれて、エンターキーを叩いて確定してください。
(5 7 9)
と表示されたでしょう。次は + を * に変えて入力してください
(map * '(1 2 3) '(4 5 6))
こんどは
(4 10 18)
と表示されましたね。同じように – や / も試して見てください
(map - '(1 2 3) '(4 5 6)) ; (0.25 0.4 0.5) (map - '(1 2 3) '(4 5 6)) ; (-3 -3 -3)
規則には気づかれたでしょうか?
具体的に述べますと map は 第一引数に関数をとりそれ以降のリストに適用し、
その結果をリストで返します。つまり
(map + '(1 2 3) '(4 5 6))
は
(list (+ 1 4) (+ 2 5) (+ 3 6)) ; listはリストを返す関数
と同様の処理になります。大変便利な関数なのですが普通は+などの簡単な処理ではなく
自分の定義したもっと複雑な関数を適用させる事が多いでしょう。
scheme でよく使う lambda とは
そこで出てくるのが lambda(無名関数)です。
無名関数とはその名の通り名前を持たない関数です。
言葉にするとややこしいですが「関数を定義するまでもない簡単な関数が欲しい時に使う」ぐらいの理解で大丈夫でしょう
さて、その使い方の解説のために初めは名前を持つ関数を作ってみます。
(define (add-2 n) (+ n 2))
この関数 add-2 は 数字を一つ引数にとり、その数字に 2 を足して返します。先程のmapと組み合わせると
(map add-2 '(1 2 3)) ; (3 4 5)
となります。実際にGIMPのコンソールで試してみてください。
そしてこれを lambda を使って書くとどうなるかといいますと
(map (lambda (n) (+ n 2)) '(1 2 3))
となります。 lambdaを使うことによって add-2 を使わずに記述できるようになりました。
(lambda (引数) 処理部分)
という構造です。この map と lambda の組み合わせは scheme では頻繁に登場します。
よく C や JAVA のプログラミングに慣れている人が while や if 文を使って記述している処理も
map, lambda を使えば簡潔にわかりやすく書けてしまうことも多々ありますので、どんどん使っていきましょう
let の使い方
次は let についての説明です
(let* ((basename (remove-extension (car (gimp-drawable-get-name layer)))) (filename (concat dir "/" basename ".pat")))
また難しいですね。解説するには長すぎるので、短いサンプルをひとつ
(let* ((foo 3)(bar 1)) (+ foo bar))
この処理では局所変数 foo に 3 を bar に 1 を代入しその合計を返しています。
scheme では変数を set! でも代入できますが推奨されていませんのでこのような処理になります。
[複数の画像からパターンを一括作成]のスクリプトでは局所変数 basename と filename に必要な情報を代入してるわけです。
長くなってきましたので今回はここまで。 あと1,2回で終わります
Script-Fuとは何か?
簡単にいうと自動化処理を記述するための方法です。
GIMPではそのために Scheme という括弧だらけの言語が採用されています。はじめはその見た目や独特さに戸惑うと思いますが、慣れてくるとrubyやjavascriptと似た性質がある事に気づきその面白さがわかってくるでしょう。
さて、前置きを長くおいても仕方がありませんのでまずこのチュートリアルで何を作れるようになるかを見ていきます。今回のお題はこのBlogで公開している「複数の画像からパターンを一括作成(Script-Fu)」を使うことにしましょう。
まず、実際に全体を見てください。
; This program is free software; ; you can redistribute it and/or modify ; it under the terms of the GNU General Public License Version 3. ; This program is distributed in the hope that it will be ; useful, but WITHOUT ANY WARRANTY; ; See the attached file or the link below. ; http://www.gnu.org/licenses/gpl-3.0.html ; ; Copyright (C) 2008 鉄(Tetsu) Mail : hogehoge@ironsand.net , ; Webpage : http://gimp.sblo.jp/ (lang:jp) ; ; 2009/03/15 save each layers as patterns (define (script-fu-fe-layers-to-patterns img drawable dir) (map (lambda (layer) (let* ((basename (remove-extension (car (gimp-drawable-get-name layer)))) (filename (concat dir "/" basename ".pat"))) (file-pat-save 1 img layer filename basename basename))) (vector->list (cadr (gimp-image-get-layers img))))) ;; add this script to the menu. (script-fu-register "script-fu-fe-layers-to-patterns" "/File/Save layers as patterns" "layers to patterns" "tetsu" ; writer "tetsu" ; copyright "2009/03" "" SF-IMAGE "Image" 0 SF-DRAWABLE "Drawable" 0 SF-DIRNAME "Directory" "MyPicture_" )
全部で34行しかありません。コメントが13行ありますので実質21行ですね。
Schemeのコメント
コメントが13行と書きましたが、scheme では”;”で始まる行、もしくは”;”以降の部分すべてがコメントになります。コメント部分はGIMPからは無視されますが、人間には有益な情報が詰まっていますので初めから順に見ていきましょう。
; This program is free software; ; you can redistribute it and/or modify ; it under the terms of the GNU General Public License Version 3. ; This program is distributed in the hope that it will be ; useful, but WITHOUT ANY WARRANTY; ; See the attached file or the link below. ; http://www.gnu.org/licenses/gpl-3.0.html
はい、英語ですね。まず読む気がしませんね。ですが、安心してください。ここに書いてあるのは「このスクリプトがGPL3で配布されてますよ~」ということだけです。
GPLとは
GPLとはプログラムの配布におけるライセンスで、「自由に使っていいですよ。ソースコードも誰でも見れるようにしておきますよ。でも、あなたがこれを使うときも同じようにGPLライセンスを使って公開してくださいね」という物です。詳しくは下記のサイト参考にしてください。
http://www.opensource.jp/gpl/gpl.ja.html.euc-jp
http://www.gnu.org/licenses/gpl-faq.ja.html
; Copyright (C) 2008 鉄(Tetsu) Mail : web-@-ironsand.net , ; Webpage : http://gimp.sblo.jp/ (lang:jp) ; ; 2009/03/15 save each layers as patterns
次のこの部分は誰が書いたか、と連絡先(ダミー)それに、スクリプトの機能と、それを書いた日付が書いています。
schemeの基礎
そろそろ本題の処理部分に入っていきたいところですが、schemeの基礎部分を理解してないと何が何だか分からなくなってしまうので本当に最低限のことだけをお伝えしようと思います。まずschemeの全ての文は括弧で囲まれた形になります。例えば 3 と 4 と 5 を比べて、大きい方の数字を返すのは
(max 3 4 5)
になります。はじめの max が関数で、3, 4, 5 が引数ですね。JAVAなどの言語では引数が “,” で区切られますがschemeではスペースで区切られます。
スペースの代わりに改行してもOKです。だから上のコードは
(max 3 4 5)
と書いても良いわけです。ちなみにJAVAで同じ物を書くなら
max(max(3, 4), 5);
となります。それでは以上を踏まえた上で登録部分の処理から見ていきましょう。
(script-fu-register ;GIMPに登録するための関数 "script-fu-fe-layers-to-patterns" ;このスクリプトの関数名 "/File/Save layers as patterns" ;メニューのどこに表示させるか "layers to patterns" ;スクリプトの説明 "tetsu" ; writer ;製作者 "tetsu" ; copyright ;著作権者 "2009/03" ;作成日 "" ;色の形式(RGBなど) SF-IMAGE "Image" 0 ;GIMPで開いてる画像のID SF-DRAWABLE "Drawable" 0 ;DrawableのID SF-DIRNAME "Directory" "MyPicture_" ;ディレクトリを選択 )
この一行目の script-fu-register が関数で、ズラズラーと後ろに引数が並んでいます。コメントを足しておきましたので大体は上のコードを見て頂くとして、問題はSF-IMAGE SF-DRAWABLE SF-DIRNAME などですね。 初めの2つ SF-IMAGEと SF-DRAWBLE はGIMPで画像を開いてる状態でscript-fuを呼び出しますと、自動的にID(整数)が関数に渡されます。今回のようにそれ以外の SF-DIRNAME などが渡されますと script-fu を実行したとき、ユーザーに選択や入力のためのダイアログが表示されます。
思ったより長くなっちゃいましたのでので、続きは次回。