>> 古い記事: gimp-shell.el / gimp-mode を使ってみた
<< 新しい記事: Emacs で Script-Fu を書いて実行させる / script-fu-shell.rb

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

Script-Fu メモ

メモ。

コーディング

新旧の違いなど

2.2 以前の Script-Fu: SIODベース。
2.4 以後の Script-Fu: TinySchemeベース。Tiny-Fu。

関数について調べる場合


概ねこの図のような関係になっているので、

  • Gimp に固有の関数についてはプロシージャブラウザで調べる
  • TinyScheme の部分については「TinyScheme」「Scheme」 などのキーワードと関数名や機能名を組み合わせて検索する

という感じになります。

追記 20091126:
Gimp 公式サイトの Script-Fu Migration Guide というページに
More information about the Scheme syntax of Script-Fu can be found in the Revised5 Report on the Algorithmic Language Scheme, also know as R5RS. Tinyscheme does not support all features of R5RS, but if a precedure is available, it is supposed to behave like documented.
という記述があり、 訳すと「Script-Fu の Scheme の文法についてもっと知りたい場合は R5RS として知られている Revised5 Report on the Algorithmic Language Scheme を参照してください。 TinyScheme は R5RS のすべての機能をサポートしている訳ではありませんが、 procedure が使える場合はこの文書に説明されているように動くはずです。」 といった感じです。
なので、TinyScheme の文法や関数について原典に当たりたい場合はここ http://schemers.org/Documents/Standards/R5RS/HTML/ を見れば良いようです(ただし英語ですが)。

ある関数が Script-Fu で使えるかどうか調べる

Script-Fu コンソールに関数名だけ入力して評価(実行)

> number->string
#<CLOSURE> ←使える
> number2string
Error: eval: unbound variable: number2string ←使えない(number2stringは束縛されていない=定義されていない)

エラーコンソールと gimp-message

printfデバッグの Script-fu 版。

メニュー > ウィンドウ > ドッキング可能なダイアログ > エラーコンソール
でエラーコンソールを開いておく。

Script-Fu 側で gimp-message 関数に文字列を渡す。

gimp-message-error-console

tracing

メッセージが大量に出て??とりますが何もないよりは助かります。


> (tracing 1) ←トレースを有効にする

Gives: 0
> (number->string "foo") ←エラーの起こる S式

Eval: (number->string "foo")
Eval: number->string
Eval: "foo"
Apply to: ("foo")
Eval: (anyatom->string n number?)
Eval: anyatom->string
Eval: n
Eval: number?
Apply to: ("foo" #)
Eval: (if (pred n) (atom->string n) (error "xxx->string: not a xxx" n))
Eval: (pred n)
Eval: pred
Eval: n
Apply to: ("foo")
Eval: (error "xxx->string: not a xxx" n)
Eval: error
Eval: "xxx->string: not a xxx"
Eval: n
Apply to: ("xxx->string: not a xxx" "foo")Error: xxx->string: not a xxx "foo" 

参考: Gimp wiki - ScriptFuClass/Staying > スクリプトのデバッグ方法

エディタ

Emacs を使うと Scheme コーディング用の支援機能がいろいろと使えて理想的なのですが、 多少操作が独特なのでとっつきにくいかもしれません。 括弧が多い言語なので、Emacs 以外を使う場合でも、 サクラエディタなど対応する括弧のハイライト機能があるエディタを選んで使うと作業しやすいと思います。

gimp-shell.el

SIODベースの Script-Fu 用に書かれているためかそのままでは動きませんが、 Emacs ユーザの方は一度試しみてはいかがでしょうか。

Script-Fuサーバのプロトコル

  • TCPソケットを使う。
  • S式の評価結果が文字列の場合はその文字列を返し、それ以外は "Success" という文字列を返すだけ。 なので、結果が文字列以外の場合は細工をしないと詳細が分からない。
  • 複数のトップレベルの S式を送りたい場合は (begin ... ) で囲む。

ここらへんが参考になるかと:

utils

選択範囲のオフセット・幅・高さを得る


(define (my-selection-bounds img)
  (let* ((bounds (gimp-selection-bounds img))
         (offset-x (nth 1 bounds))
         (offset-y (nth 2 bounds))
         (right-bottom-x (nth 3 bounds))
         (right-bottom-y (nth 4 bounds))
         )
    (list offset-x
          offset-y
          (- right-bottom-x offset-x) ; width
          (- right-bottom-y offset-y) ; height
          )))

連続した数のリストを生成する


(define (seq n)
  (letrec
      ((seq-sub
        (lambda (n)
          (if (= n 0)
              '(0)
              (cons n
                    (seq-sub (- n 1)))))))
    (reverse (seq-sub (- n 1)))))

(seq 5)
;;=> (0 1 2 3 4)

リストから条件を満たす要素だけを得る


(define (select proc list)
  (cond ((null? list)
         '())
        ((proc (car list))
         (cons (car list) (select proc (cdr list))))
        (else
         (select proc (cdr list)))))

(select (lambda (x) (> x 1)) '(0 1 2 3))
;;=> (2 3)

レイヤー名からレイヤー(ID)を取得


(define (get-layer-by-name img layer-name)
  (let ((layers (vector->list (cadr (gimp-image-get-layers img))))
        (result '()))
    (for-each
     (lambda (layer)
       (if (equal? (car (gimp-layer-get-name layer))
                   layer-name)
           (set! result layer)))
     layers)
    result))

;; レイヤー名を指定してレイヤーを削除
(define (remove-layer-by-name img layer-name)
  (let ((layer (get-layer-by-name img layer-name)))
    (unless (null? layer)
            (gimp-image-remove-layer img layer))))

fold

無いようだったのでオレオレで書いてみた。 Scheme なので inject、reduce ではなく fold。


(define (fold proc init-value list)
  (let ((value init-value))
    (for-each
      (lambda (elem) (set! value (proc value elem)))
      list)
    value))

(fold (lambda (value x) (+ value x))
      0
      '(1 2 3 4))
;;=> 10
(fold (lambda (value x) (* value x))
      1
      '(1 2 3 4))
;;=> 24
追記 20100906: ありました。 foldr です。
> (foldr (lambda (acc item) (- acc item)) 1 '(1 2 3 4))
-9
> (foldr - 1 '(1 2 3 4))
-9

要素 x はリストの何番目か


;; 最初に出現する位置を返す
(define (index proc x list)
  (let ((temp (proc x list)))
    (if temp
        (- (length list) (length temp))
        ())))
(index member 1 '(1 2 3)) ;=> 0
(index member 3 '(1 2 3)) ;=> 2
(index member 0 '(1 2 3)) ;=> ()

;; drw はレイヤースタックの上から何番目か?
(define (drawable->pos-from-top img drw)
  (index member drw
        (vector->list (cadr (gimp-image-get-layers img)))))

printf

SLIB に含まれている printf.scm の require ~ の箇所をコメントアウトして Script-Fu のフォルダに入れておくと printf, fprintf, sprintf が動くことを確認しましたが 詳しくは調べていません。

選択範囲を一時的に退避して処理を行う


(define (with-selection-escape img proc)
  (let ((escaped-channel (car (gimp-selection-save img))))
    (proc)
    (gimp-selection-load escaped-channel)
    (gimp-image-remove-channel img escaped-channel)))

レイヤーの移動


(define (length-of-layers img)
  (length (vector->list (cadr (gimp-image-get-layers img)))))

(define (move-layer img drw dest)
  (if (or(>= dest (length-of-layers img))
         (<  dest 0))
      (gimp-message "invalid argument")
    (begin
     (gimp-image-raise-layer-to-top img drw)
     (let ((i 0))
       (while (< i dest)
         (gimp-image-lower-layer img drw)
         (set! i (+ i 1)))))))

その他

Script-Fu 青空教室 三限目 最初のスクリプトから:
ドロアブルはレイヤーとチャンネルの総称です。
Script-Fu 青空教室 三限目 最初のスクリプトから:
Script-Fu のスクリプトの場合は "script-fu-" に続けてスクリプトの名前を付けるのが慣例


Gimp 関連記事のもくじ

>> 古い記事: gimp-shell.el / gimp-mode を使ってみた
<< 新しい記事: Emacs で Script-Fu を書いて実行させる / script-fu-shell.rb
** ホームに戻る

コメント

コメントの投稿

管理者にだけ表示を許可する

|
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。