從script_fu中學習影像處理技巧:有光影的球體

 

scripts目錄下有超過100個 *.scm檔,這些是學習影像處理技巧的最好教材,以下我們來研究Spencer Kimball所寫的sphere.scm程式。

        讀了本文你會體會到漸層填色工具的威力無窮。

一、執行Script-Fu:

有光影的球體

l          執行[GIMP] -> Xtns -> Script_Fu -> Misc -> Sphere使用預設的參數:Radius設100、Lighting (degrees)設45、Shadow設" TRUE"、Background Color設黑色、Sphere Color設紅色,產生左圖。

l          左圖光源在45度角處(中心的右上角),故陰影在左下角。同時,球體的左下角較暗。

l          有光影的球體由發光的球體、陰影、白色的背景所組成。

l          製作時只需要1個圖層,或者你也可以使用3個圖層。

l          若只用1個圖層,則製作的流程為:白色的背景 -> 陰影 -> 球體。

l          sphere.scm程式碼,有一半的程式碼是在計算球體的圓心、半徑、光源的位置、陰影的位置與大小。

 

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

以下我們使用Gimp圖形界面,一步一步作來產生有光影的球體。藉由這過程來瞭解程式碼的意思。

 

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

每個步驟所產生的影像視窗

以圖形使用者介面產生有光影的球體,需要的步驟:

對應到sphere.scm程式碼中的函數

白色底色的背景

l          執行[GIMP] -> File -> New,產生大小375x250白色底色的影像。

l          圖層的名字更改為Sphere Layer

l          產生白色底色的影像,程式碼至少要4行才能做到,

    gimp-image-new:產生新影像

    gimp-layer-new:產生新圖層

gimp-image-add-layer:為影像加上圖層

gimp-edit-fill:將圖層填上白色

13:(img (car (gimp-image-new width height RGB)))

14: (drawable (car (gimp-layer-new img width height RGB_IMAGE "Sphere Layer" 100 NORMAL)))

27: (gimp-image-add-layer img drawable 0)

28: (gimp-palette-set-foreground sphere-color)

29: (gimp-palette-set-background bg-color)

30: (gimp-edit-fill drawable BG-IMAGE-FILL)

橢圓選取

l          使用橢圓選取工具圈出一個橢圓形的選取區域。橢圓選取工具的參數設定Feather設7.5。

l          橢圓選取的頂點座標(10.7,190),橢圓選取的寬176.8,橢圓選取的長50。

l          橢圓選取所使用的參數是根據程式碼中的公式算出來的。

l          你可以根據你的直覺不必太精確地產生一個橢圓形的選取區域。

46:(gimp-ellipse-select img shadow-x shadow-y shadow-w shadow-h REPLACE TRUE 7.5)

製作陰影

l          使用顏料桶工具為圓形的選取區域上色。

l          由於羽化選取區域的因素,使得字黑色的橢圓形的邊緣變模糊。

47:(gimp-bucket-fill drawable BG-BUCKET-FILL MULTIPLY 100 0 FALSE 0 0)

橢圓選取

l          使用橢圓選取工具圈出一個圓形的選取區域。

l          圓心為影像的中心(187.5,125)、半徑100,故橢圓選取的頂點座標(87.5,25),橢圓選取的寬200,橢圓選取的長200。

l          你可以根據你的直覺不必太精確地產生一個圓形的選取區域。

50: (gimp-ellipse-select img (- cx radius) (- cy radius) (* 2 radius) (* 2 radius) REPLACE TRUE FALSE 0)

工具選項對話盒

有光影的球體

l          漸層填色桶工具的參數選項設定如右。Gradient設Radial,放射狀的漸層。

l          在前景色為紅色、背景色為黑色,使用漸層填色工具,為圓形的選取區域上色。從圓心的右上角(230,82.6)這一點到左下角(116.8,195.7)這一點,拉一條直線。

l          由於是放射狀漸層,圓心的右上角(230,82.6)這一點附近是較亮的紅色,會有發光的感覺;左下角(116.8,195.7)這一點附近是較暗的紅色或黑色,有陰影的感覺。

l          圓心與光源位置是根據程式碼中的公式算出來的。

l          你可以根據你的直覺不必太精確地去製作有光影的球體。

51: (gimp-blend drawable FG-BG-RGB NORMAL RADIAL 100 offset REPEAT-NONE FALSE 0 0 light-x light-y light-end-x light-end-y)

52: (gimp-selection-none img)

 

三、原始程式碼:

l          程式碼sphere.scm分三部份

l          1~8行:註解

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

l          59~71行:(script-fu-register "script-fu-sphere"  )

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

l          sphere.scm程式碼,有一半的程式碼是在計算球體的圓心、半徑、光源的位置、陰影的位置與大小。

l          我將這些變數計算後紀錄在下面的欄位中。

1: ;  Create a 3D sphere with optional shadow

2: ;  The sphere's principle color will be the foreground

3: ;  Parameters:

4: ;   bg-color: background color

5: ;   sphere-color: color of sphere

6: ;   radius: radius of the sphere in pixels

7: ;   light:  angle of light source in degrees

8: ;   shadow: whather to create a shadow as well

 

 

預設輸入參數的值

Radius=100

Lighting (degrees)=45

Shadow=" TRUE

Background Color= '(255 255 255)

Sphere Color='(255 0 0))

9: (define (script-fu-sphere2 radius light shadow bg-color sphere-color)

10:   (let* (

11:         (width (* radius 3.75))

12:         (height (* radius 2.5))

13:          (img (car (gimp-image-new width height RGB)))

14:          (drawable (car (gimp-layer-new img width height RGB_IMAGE "Sphere Layer" 100 NORMAL)))

15:          (radians (/ (* light *pi*) 180))

16:          (cx (/ width 2))

17:          (cy (/ height 2))

18:         (light-x (+ cx (* radius (* 0.6 (cos radians)))))

19:          (light-y (- cy (* radius (* 0.6 (sin radians)))))

20:          (light-end-x (+ cx (* radius (cos (+ *pi* radians)))))

21:          (light-end-y (- cy (* radius (sin (+ *pi* radians)))))

22:          (offset (* radius 0.1))

23:          (old-fg (car (gimp-palette-get-foreground)))

24:          (old-bg (car (gimp-palette-get-background)))

25       )

26:      (gimp-image-undo-disable img)

27:      (gimp-image-add-layer img drawable 0)

28:      (gimp-palette-set-foreground sphere-color)

29:      (gimp-palette-set-background bg-color)

30:      (gimp-edit-fill drawable BG-IMAGE-FILL)

31:      (gimp-palette-set-background '(20 20 20))

32:      (if (and

33:           (or (and (>= light 45) (<= light 75)) (and (<= light 135) (>= light 105)))

34:           (= shadow TRUE))

35:          (let (

36:             (shadow-w (* (* radius 2.5) (cos (+ *pi* radians))))

37:               (shadow-h (* radius 0.5))

38:               (shadow-x cx)

39:               (shadow-y (+ cy (* radius 0.65)))

40:           )

41:              (if (< shadow-w 0)

42:                 (prog1 (set! shadow-x (+ cx shadow-w))

43:                           (set! shadow-w (- shadow-w))

44:               )

45:            )

46:              (gimp-ellipse-select img shadow-x shadow-y shadow-w shadow-h REPLACE TRUE TRUE 7.5)

47:              (gimp-bucket-fill drawable BG-BUCKET-FILL MULTIPLY 100 0 FALSE 0 0)

48:        )

49:      )

50:      (gimp-ellipse-select img (- cx radius) (- cy radius) (* 2 radius) (* 2 radius) REPLACE TRUE FALSE 0)

51:      (gimp-blend drawable FG-BG-RGB NORMAL RADIAL 100 offset REPEAT-NONE FALSE 0 0 light-x light-y light-end-x light-end-y)

52:    (gimp-selection-none img)

53:    (gimp-palette-set-background old-bg)

54:    (gimp-palette-set-foreground old-fg)

55:    (gimp-image-undo-enable img)

56:    (gimp-display-new img)

57:   )

58: )

 

 

Radius=100;Lighting (degrees)=45

width =3.75× radius

height=2.5× radius

 

*pi*為Scheme的內部變數表圓周率。

radians=*pi*×light÷180;

cx=width÷2

cy=height÷2

light-x=cx+0.6×radius×cos(radians)

light-y=cy-0.6×radius×sin(radians)

light-x-end=cx+radius×cos(*pi*+radians)

light-y-end=cy-radius×sin(*pi*+radians)

offset=0.1×radius

width =375

height=250

 

 

radians=*pi*/4

cx=187.5

cy=125

light-x=230

light-y=82.57

light-x-end=116.8

light-y-end=195.7

offset=10

以(187.5,125)為圓心,光從(230,82.6)處到(116.8,195.7)處,從圓心45度角處到圓心225度角處。

 

 

 

 

 

 

32行到34行的條件式是為限制光的角度,

限定光的角度是為了避免產生的影子太大或太小。

 

let與let*有何不同?

 

shadow-w=2.5× radius×cos (*pi*+radians)

shadow-h=0.5×radius

shadow-x=cx

shadow-y=cy+0.65×radius

shadow-w=-176.8

shadow-h=50

shadow-x=187.5

shadow-y=190

 

shadow-w=-176.8 <0

shadow-x=cx+shadow-w

shadow-w=-shadow-w

shadow-x=10.7

shadow-w=176.8

 

prog1是什麼?

59: (script-fu-register "script-fu-sphere2"

60:                    _"<Toolbox>/Xtns/Script-Fu/Misc/Sphere2..."

61:                    "Simple sphere with a drop shadow"

62:                   "Spencer Kimball"

63:                    "Spencer Kimball"

64:                    "1996"

65:                    ""

66:                    SF-ADJUSTMENT _"Radius (pixels)" '(100 5 500 1 10 0 1)

67:                    SF-ADJUSTMENT _"Lighting (degrees)" '(45 0 360 1 10 0 0)

68:                    SF-TOGGLE _"Shadow" TRUE

69:                    SF-COLOR  _"Background Color" '(255 255 255)

70:                    SF-COLOR  _"Sphere Color" '(255 0 0)

71:  )

 

 

四、其他函數的說明:

gimp-ellipse-select函數

46:(gimp-ellipse-select img shadow-x shadow-y shadow-w shadow-h REPLACE TRUE 7.5)

50: (gimp-ellipse-select img (- cx radius) (- cy radius) (* 2 radius) (* 2 radius) REPLACE TRUE FALSE 0)

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