從script_fu中學習影像處理技巧:水波動畫

 

scripts目錄下有超過100個 *.scm檔,這些是學習影像處理技巧的最好教材,在「使用GIMP編輯動畫(四)」這篇文章中已經有討論過水波動畫,本文延續該篇文章,要研究Sven Neumann所寫的waves-anim.scm程式碼是如何產生水波的動畫。

讀了本文你將學會如何寫一個製作簡單動畫的Script-Fu。

一、執行Script-Fu

 

花的水波動畫

 

靜止的花

多圖層的動畫

 

l          對上圖,執行[image] -> Script_Fu -> Animators ->Waves使用預設的參數:Amplitude設10、Wavelength設20、Number of Frames設 6,產生左圖。

l          Amplitude與Wavelength是根據影像的大小來設定的。小的Amplitude小的Wavelength可產生漣波的效果。

l          Number of Frames設 6使得每個畫框的水波相差為60度(360÷6)。

 

 

        使用Gimp圖形界面來編輯影像的每個動作都有相對應的函數,gimp-edit-copy、gimp-edit-paste、gimp-edit-cut對應的便是最常使用的影像複製、影像貼上、影像剪下等動作。

以下我們使用Gimp圖形界面,一步一步作來產生水波動畫。藉由這過程來體會程式碼的意思。

 

二、使用Gimp圖形界面,一步一步作

每個步驟所產生的影像視窗與圖層對話盒

以圖形使用者介面產生水波效果的動畫,需要的步驟:

對應到waves-anim.scm程式碼中的函數

 

l          首先要計算要產生多少個圖框的動畫。

l          若是6個圖框,則水波的相移phaseshift=360÷6=60度。

l          num-frames=6

l          Phaseshift=60

l          一開始Phase=0

l          remaining-frames=6

flower.jpg的影像視窗

 

Background圖層

l          gimp-channel-ops-duplicate函數的目的是複製一個影像的所有圖層、所有色頻(channels),及相關的所有資料到新的影像物件,gimp-channel-ops-duplicate函數我在Gimp圖形界面上找不到對應的動作。

l          我直接在原本flower.jpg的影像視窗操作,假設flower.jpg影像只有一個名為Background的圖層。

46:image (car (gimp-channel-ops-duplicate img)))

47:source-layer (car (gimp-image-get-active-layer image)))

 

複製Background圖層

l          在操作圖層的對話盒中,複製Background圖層產生1個新的圖層,將新的圖層更名為Frame 2(replace)。

56: (while (> remaining-frames 1)

59: (waves-layer (car (gimp-layer-copy source-layer TRUE)))

60: (layer-name (string-append "Frame”

(number->string

(- (+ num-frames 2) remaining-frames) 10)

" (replace)"))

66: (gimp-layer-set-preserve-trans waves-layer FALSE)

67:(gimp-image-add-layer image waves-layer -1)

68:(gimp-layer-set-name waves-layer layer-name)

 

使用Waves濾鏡

l          對Frame 2(replace)圖層的影像執行[image] -> Filters -> Distorts -> Waves,Mode設Smear、Amplitude設10、Wavelength設20、Phase設 0,產生左圖。

70:(plug-in-waves 1 image waves-layer amplitude phase wavelength 0 FALSE)

重覆上面步驟

l          重覆上面步驟:# 表3、4、5、6

l          複製Background圖層產生新圖層,圖層更名為Frame # (replace),新圖層要在既有的圖層的上方。

l          對Frame # (replace)圖層的影像執行Waves濾鏡,Phase設(#-2)×-60(為負號),其餘參數照舊。

79:(set! remaining-frames (- remaining-frames 1))

80:(set! phase (- phase phaseshift))

回到

56: (while (> remaining-frames 1)

判斷是否還要繼續執行 while 迴圈,

花的水波動畫

l          將Background圖層更名為Frame 1。

l          對Frame 1圖層的影像執行Waves濾鏡,Phase設360,其餘參數照舊。

l          執行[image] -> Filters -> Animation Playback來播放多圖層的動畫。

l          或存成Gif動畫檔。

當remaining-frames>1,結束while 迴圈,

84:(gimp-layer-set-name source-layer "Frame 1")

85:(plug-in-waves 1 image sources-layer amplitude phase wavelength 0 FALSE)

 

 

三、原始程式碼:

l          程式碼waves-anim.scm分三部份

l          1~31行:註解,版權宣告。

l          32~58行::(define (script-fu-waves-anim   )) ,在測試程式的過程中,我將它改為script-fu-sphere2

l          59~98行:(script-fu-register " script-fu-waves-anim "  )

l          我將括號對齊,方便研究程式碼,故行數與原本的檔案不一樣。

 

1:  ; The GIMP -- an image manipulation program

2:  ; Copyright (C) 1995 Spencer Kimball and Peter Mattis

3:  ;

4:  ; This program is free software; you can redistribute it and/or modify

5:  ; it under the terms of the GNU General Public License as published by

6:  ; the Free Software Foundation; either version 2 of the License, or

7:  ; (at your option) any later version. 

8:  ;

9:  ; This program is distributed in the hope that it will be useful,

10: ; but WITHOUT ANY WARRANTY; without even the implied warranty of

11: ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the

12: ; GNU General Public License for more details.

13: ;

14: ; You should have received a copy of the GNU General Public License

15: ; along with this program; if not, write to the Free Software

16: ; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

17: ;

18: ;

19: ; waves-anim.scm   version 1.01   1997/12/13

20: ;

21: ; CHANGE-LOG:

22: ; 1.00 - initial release

23: ; 1.01 - some code cleanup, no real changes

24: ;

25: ; Copyright (C) 1997 Sven Neumann <sven@gimp.org>

26: ;

27: ;

28: ; Makes a copy of your image and creates an animation of the active layer

29: ; as if a stone was thrown into the image. The animation may be saved with

30: ; the gif-plug-in.

31:

 

32: (define (script-fu-waves-anim img

33:                        drawable

34:                         amplitude

35:                         wavelength

36:                         num-frames

37:                         invert)

38:   (let*

39:        (

40:          (amplitude (max 0 amplitude))

41:          (wavelength (max 0 wavelength))

42:          (num-frames (max 1 num-frames))

43:          (remaining-frames num-frames)

44:          (phase 0)

45:          (phaseshift (/ 360 num-frames))

46:          (image (car (gimp-channel-ops-duplicate img)))

47:          (source-layer (car (gimp-image-get-active-layer image)))

48:        )

49:

50:        (gimp-image-undo-disable image)

51:

52:        (if (= invert TRUE)

53:            (set! phaseshift (- 0 phaseshift))

54:        )

55: 

 

 

 

 

num-frames=6

 

 

 

 

 

 

 

Phase=0

 

Phaseshift=60

 

 

 

56:        (while (> remaining-frames 1)

57:            (let*

58:                (

59:                  (waves-layer (car (gimp-layer-copy source-layer TRUE)))

60:                      (layer-name (string-append "Frame "

61:                                    (number->string

62:                                       (- (+ num-frames 2)

63:                                          remaining-frames) 10)

64:                                      " (replace)"))

65:                )

66:                 (gimp-layer-set-preserve-trans waves-layer FALSE)

67:                  (gimp-image-add-layer image waves-layer -1)

68:             (gimp-layer-set-name waves-layer layer-name)

69:

70:                  (plug-in-waves 1

71:                                   image

72:                                   waves-layer

73:                                   amplitude

74:                                   phase

75:                                   wavelength

76:                                   0

77:                                  FALSE)

78:    

79:                   (set! remaining-frames (- remaining-frames 1))

80:                   (set! phase (- phase phaseshift))

81:             )

82:          )

83:

 

 

 

string-append函數:把字串串接起來。

number->string函數:把數字變字串。

 

一開始remaining-frames=num-frames,

故num-frames+2-remaining-frames=2

 

最後合成的字串 "Frame 2 (replace)"

84:         (gimp-layer-set-name source-layer "Frame 1")

85:         (plug-in-waves 1

86:                 image

87:                     source-layer

88:                       amplitude

89:                   phase

90:                       wavelength

91:                       0

92:                       FALSE)

93:

94:          (gimp-image-undo-enable image)

95:          (gimp-display-new image)

96:   )

97: )

98:

 

99:  (script-fu-register "script-fu-waves-anim"

100:             _"<Image>/Script-Fu/Animators/Waves..."

101:             "Animate an image like a stone's been thrown into it"

102:             "Sven Neumann <sven@gimp.org>"

103:             "Sven Neumann"

104:             "1997/13/12"

105:             "RGB* GRAY*"

107:             SF-IMAGE "Image" 0

108:             SF-DRAWABLE "Drawable" 0

109:             SF-ADJUSTMENT _"Amplitude"        '(10  1  101 1 10 1 0)

110:              SF-ADJUSTMENT _"Wavelength"       '(10 .10 100 1 10 1 0)

111:              SF-ADJUSTMENT _"Number of Frames" '(6  1   512 1 10 0 1)

112:              SF-TOGGLE     _"Invert direction" FALSE

113: )

 

 

四、其他函數的說明:

gimp-channel-ops-duplicate函數

 

gimp-image-add-layer函數

 

plug-in-waves函數

 

46:(image (car (gimp-channel-ops-duplicate img)))

67:(gimp-image-add-layer image waves-layer -1)

70:(plug-in-waves 1 image waves-layer amplitude phase wavelength 0 FALSE)

由DB Browser對話盒的資料可推出第46行、第67行、第70行是什麼意思。