[Part I. GIMP基礎功]

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



30.6 老照片,修改成可「單行」執行的 Script-Fu

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


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


捨棄函數 script-fu-old-photo ,直接指定輸入變數值
  • 修改成最多的地方就是下列這兩段部份。
  • 記得要刪除多餘的右括號 ) ,不然會出現錯誤訊息。
  • 修改後的程式碼,不再需要預先定義函數 script-fu-old-photo ,但是要預先設定變數名稱、變數值 。
(define (script-fu-old-photo inImage inLayer inDefocus inBorderSize inSepia inMottle inCopy)
(let (
(theImage 0)
(theLayer 0)
(theWidth 0)
(theHeight 0)
)


(let (
(mLayer (car (gimp-layer-new theImage theWidth theHeight
RGBA-IMAGE "Mottle"
100 DARKEN-ONLY-MODE)))
)


從下列的程式碼得知變數值的型態與大小
SF-IMAGE      "The image"     0
SF-DRAWABLE "The layer" 0
SF-TOGGLE _"Defocus" TRUE
SF-ADJUSTMENT _"Border size" '(20 0 300 1 10 0 1)
; since this plug-in uses the fuzzy-border plug-in, I used the
; values of the latter, with the exception of the initial value
; and the 'minimum' value.
SF-TOGGLE _"Sepia" TRUE
SF-TOGGLE _"Mottle" FALSE
SF-TOGGLE _"Work on copy" TRUE



關於 if
  • old-photo.scm 有很多 if 的陳敘句。
  • (if (condition) (expr1) (expr2) .......),要注意此區塊括號的對齊。
  • (if (condition) .......),區塊內不能使用 (define ......)。
  • 因此,(define (mLayer ......))這一行要往前移。


使用紅底黑框的圖案,來測試老照片的效果
  • 原本的old-photo.scm需要參考到既存的影像物件、圖層物件,才能正確運行 。
  • 添加「建立」的程式碼,這樣「老照片效果的程式」才能正確運行 。
  • 下圖是程式碼執行後的圖案,紅底黑框附帶兩個青色小方框。


(define width 256)
(define height 256)
(define img (car (gimp-image-new width height RGB)))
(define layer-one (car (gimp-layer-new img width height RGB-IMAGE "layer 1" 100 NORMAL-MODE)))
(gimp-image-add-layer img layer-one 0)
(gimp-display-new img)

; 重設為預設的筆刷 Circle (11)
(gimp-context-set-brush "Circle (11)")

(define color '(255 0 0))
(gimp-context-set-background color)
(gimp-selection-all img)
(gimp-edit-fill layer-one BACKGROUND-FILL) ;塗滿紅色

(set! color '(0 0 0))
(gimp-context-set-foreground color)
(gimp-selection-shrink img 10)
(gimp-edit-stroke layer-one) ;描繪出一個黑色外框

(gimp-selection-none img)

(set! color '(0 255 0))
(gimp-context-set-foreground color)
(gimp-context-set-brush "Circle (03)")
(gimp-rect-select img 50 50 50 50 0 TRUE 4)
(gimp-edit-stroke layer-one) ;描繪出一個青色方框

(gimp-selection-none img)

(gimp-rect-select img 150 150 50 50 0 TRUE 4)
(gimp-edit-stroke layer-one)
(gimp-selection-none img) ;描繪出一個青色方框


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

; 要先準備好「測試用的影像與圖層」
(define inImage img) ; 指派影像物件
(define inLayer layer-one) ; 指派圖層物件

(define inDefocus TRUE)
(define inBorderSize 20)
(define inSepia TRUE)
(define inMottle FALSE)
(define inCopy TRUE)

(define theImage 0)
(define theLayer 0)
(define theWidth 0)
(define theHeight 0)

(define mLayer 0)

(gimp-image-undo-group-start inImage)
(gimp-selection-all inImage)


(set! theImage (if (= inCopy TRUE)
(car (gimp-image-duplicate inImage))
inImage)
)

(set! theLayer (car (gimp-image-flatten theImage)))

(if (= inDefocus TRUE)
(plug-in-gauss-rle RUN-NONINTERACTIVE theImage theLayer 1.5 TRUE TRUE)
)

(if (> inBorderSize 0)
(script-fu-fuzzy-border theImage theLayer '(255 255 255) inBorderSize TRUE 8 FALSE 100 FALSE TRUE )
)

(set! theLayer (car (gimp-image-flatten theImage)))

(if (= inSepia TRUE)
(begin (gimp-desaturate theLayer)
(gimp-brightness-contrast theLayer -20 -40)
(gimp-color-balance theLayer 0 TRUE 30 0 -30)
)
)

(set! theWidth (car (gimp-image-width theImage)))
(set! theHeight (car (gimp-image-height theImage)))
(set! mLayer (car (gimp-layer-new theImage theWidth theHeight RGBA-IMAGE "Mottle" 100 DARKEN-ONLY-MODE)))

(if (= inMottle TRUE)
(begin (gimp-image-add-layer theImage mLayer 0)
(gimp-selection-all theImage)
(gimp-edit-clear mLayer)
(gimp-selection-none theImage)
(plug-in-noisify RUN-NONINTERACTIVE theImage mLayer TRUE 0 0 0 0.5)
(plug-in-gauss-rle RUN-NONINTERACTIVE theImage mLayer 5 TRUE TRUE)
(set! theLayer (car (gimp-image-flatten theImage)))
)
)


(if (= inCopy TRUE)
(begin (gimp-image-clean-all theImage)
(gimp-display-new theImage)
)
)

(gimp-selection-none inImage)
(gimp-image-undo-group-end inImage)
(gimp-displays-flush theImage)