[Part I. GIMP基礎功]

[Part II. 一種效果的誕生]
[Part III. Script-Fu的秘密]

28.6 電路圖,修改成可「單行」執行的 Script-Fu

修改成一行一行可執行的程式碼
  • 本節要將 circuit.scm 修改成在 Console 內可一行一行執行的 Scheme 程式碼。
  • circuit.scm 完整的程式碼可參考 28.5 節
  • 也可到 GIMP 系統的 scripts 目錄下找到該檔案。
  • 最主要修改的部份是,將「對話框接收輸入變數值」修改成「直接指定輸入變數值」。
  • 先要瞭解,circuit.scm 程式碼的執行流程。


最主要修改的部份
  • 不使用 let* 改用 define
  • 原本的程式使用 let* 定義與指定區域變數值。
  • (let* (()()()...) ()() ...) 這樣的語法括號太多。
  • 若要一行一行分析程式碼的意義,let* 語法,括號有好幾層,分析時,會造成一些干擾。
  • 現在不使用 let* 改用 define 來定義與指定變數值。


捨棄函數 script-fu-circuit,直接指定輸入變數值
  • 修改成最多的地方就是下列這部份。
  • 要注意括號的對齊。
  • 記得要刪除多餘的右括號 ) ,不然會出現錯誤訊息。
  • 修改後的程式碼,不再需要預先定義函數 script-fu-circuit ,但是要預先設定變數名稱、變數值 。

(define (script-fu-circuit image
                         drawable
                         mask-size
                         seed
                         remove-bg
                         keep-selection
                         separate-layer)
(let* (
      (type (car (gimp-drawable-type-with-alpha drawable)))
      (image-width (car (gimp-image-width image)))
      (image-height (car (gimp-image-height image)))
      (active-selection 0)
      (from-selection 0)
      (selection-bounds 0)
      (select-offset-x 0)
      (select-offset-y 0)
      (select-width 0)
      (select-height 0)
      (effect-layer 0)
      (active-layer 0)
      )


從下列的程式碼得知變數值的型態與大小
SF-IMAGE      "Image"             0
SF-DRAWABLE   "Drawable"          0
SF-ADJUSTMENT _"Oilify mask size" '(17 3 50 1 10 0 1)
SF-ADJUSTMENT _"Circuit seed"     '(3 1 3000000 1 10 0 1)
SF-TOGGLE     _"No background (only for separate layer)" FALSE
SF-TOGGLE     _"Keep selection"   TRUE
SF-TOGGLE     _"Separate layer"   TRUE


修改(if (= separate-layer TRUE) ...)這區塊
  • 要注意此區塊括號的對齊。
  • 下列這段程式碼 ,不使用 let 改用 set! 與 define。
  • 變數的定義 (define .....) 移到 if 之前。


(let ((floating-sel (car (gimp-edit-paste effect-layer FALSE))))
          (gimp-floating-sel-anchor floating-sel)
)

修改後的程式碼如下所列:

(define floating-sel 0)
(if (= separate-layer TRUE)
......
(set! floating-sel (car (gimp-edit-paste effect-layer FALSE)))
(gimp-floating-sel-anchor floating-sel)
......
)


修改後的程式碼,與測試的結果圖
  • 下面是修改後的程式碼。
  • 啟動 GIMP Script-fu Console
  • 將下面的 Scheme 程式碼,全部選取、複製、再貼入 Script-fu Console 文字框,按下 Enter 。
  • 過一會,就會看到結果圖。


(define inSize 256)
(define theWidth inSize)
(define theHeight inSize)
(define theImage (car (gimp-image-new theWidth theHeight RGB)))
(define baseLayer (car (gimp-layer-new theImage theWidth theHeight RGBA-IMAGE "Background" 100 NORMAL-MODE)))
(gimp-image-add-layer theImage baseLayer 0)
; 可以把顯示影像物件 theImage 提前到這裡
(gimp-display-new theImage)

; 前面的程式碼是為了生成「一個透明的圖層」
; 作為之後生成電路圖案的參考圖層
; 此參考圖層規範了電路圖案的長寬

(define image theImage) ; 指派影像物件
(define drawable baseLayer)  ; 指派圖層物件

(define mask-size 17)
(define seed 3)
(define remove-bg FALSE)
(define keep-selection TRUE)
(define separate-layer TRUE)

(define type (car (gimp-drawable-type-with-alpha drawable)))
(define image-width (car (gimp-image-width image)))
(define image-height (car (gimp-image-height image)))
(define active-selection 0)
(define from-selection 0)
(define selection-bounds 0)
(define select-offset-x 0)
(define select-offset-y 0)
(define select-width 0)
(define select-height 0)
(define effect-layer 0)
(define active-layer 0)

(gimp-context-push)
(gimp-image-undo-group-start image)

(gimp-layer-add-alpha drawable)

(if (= (car (gimp-selection-is-empty image)) TRUE)
(begin
(gimp-selection-layer-alpha drawable)
(set! active-selection (car (gimp-selection-save image)))
(set! from-selection FALSE))
(begin
(set! from-selection TRUE)
(set! active-selection (car (gimp-selection-save image)))
) ; 此為 begin 的右括號
) ; 此為 if 的右括號

(set! selection-bounds (gimp-selection-bounds image))
(set! select-offset-x (cadr selection-bounds))
(set! select-offset-y (caddr selection-bounds))
(set! select-width (- (cadr (cddr selection-bounds)) select-offset-x))
(set! select-height (- (caddr (cddr selection-bounds)) select-offset-y))

(define floating-sel 0)
(if (= separate-layer TRUE)
(begin
(set! effect-layer (car (gimp-layer-new image select-width select-height type "effect layer" 100 NORMAL-MODE)))

(gimp-image-add-layer image effect-layer -1)
(gimp-layer-set-offsets effect-layer select-offset-x select-offset-y)
(gimp-selection-none image)
(gimp-edit-clear effect-layer)
(gimp-selection-load active-selection)
(gimp-edit-copy drawable)

(set! floating-sel (car (gimp-edit-paste effect-layer FALSE)))
(gimp-floating-sel-anchor floating-sel)

(gimp-image-set-active-layer image effect-layer )) ; 此為 begin 的右括號
(set! effect-layer drawable)  ; 只有一行敘述可以不用 (begin ......)
) ; 此為 if 的右括號

(set! active-layer effect-layer)

(if (= remove-bg TRUE)
(gimp-context-set-foreground '(0 0 0))
(gimp-context-set-foreground '(14 14 14))
)

(gimp-selection-load active-selection)
(plug-in-maze RUN-NONINTERACTIVE image active-layer 5 5 TRUE 0 seed 57 1)
(plug-in-oilify RUN-NONINTERACTIVE image active-layer mask-size 0)
(plug-in-edge RUN-NONINTERACTIVE image active-layer 2 1 0)
(if (= type RGBA-IMAGE)
(gimp-desaturate active-layer))

(if (and
(= remove-bg TRUE)
(= separate-layer TRUE))
(begin (gimp-by-color-select active-layer '(0 0 0) 15 2 TRUE FALSE 10 FALSE)
(gimp-edit-clear active-layer)))

(if (= keep-selection FALSE)
(gimp-selection-none image))

(gimp-image-remove-channel image active-selection)
(gimp-image-set-active-layer image drawable)

(gimp-image-undo-group-end image)

(gimp-displays-flush)

(gimp-context-pop)