[Part I. GIMP基礎功]

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

22.6 單步執行「印刷文字」之「第一種方式」

單步追蹤1. 更新Scripts,更新資料庫
  • 整合式的軟體開發工具多有提供單步執行,讓程式能一次一行地執行,便於追蹤錯誤。可惜沒有人為Script-Fu發展更好的除錯工具。
  • 以下我用很原始的方法,呈現news-text2.scm這個Script-Fu完整的執行過程,透過這個方法,讀者應該會更瞭解這支程式。
  • 下圖展示了「Refresh Scripts」所在的位置,執行後,會更新GIMP的程序資料庫內的資料。



  • 若還未執行GIMP程式,請啟動GIMP程式,這樣也能更新程序資料庫。
  • 單步測試程式時,需要一直更新程序資料庫,因此讓Script-Fu選單是一個獨立的選單視窗,這樣可以加快測試的速度。
  • 下圖展示了獨立的「Script-Fu」選單,此時選單是一個視窗,「Refresh Scripts」就位在「Script-Fu」選單內。



單步追蹤2. 修改Scripts,增減程式碼
  • 完整的原始程式碼加上行號,表請參考前一節「news-text.scm 分三部份」。
  • 使用文字編輯器修改news-text2.scm檔
  • 刪除news-text2.scm程式碼第36行到第69行,儲存檔案。
  • Newsprint Text2對話盒中,預設的字串Newsprint,更改為Gimp。讓影像視窗小一些,方便展示說明。
  • 保留第35行、第70行、第72行,這是為了執行Script-Fu之後,能有影像視窗與作圖區。
  • 執行「Refresh Scripts」【註a】,更新GIMP的程序資料庫內的資料。
  • 執行「Newsprint Text2」【註b】,會出現下圖的影像視窗。
  • 下圖,影像視窗標題顯示「0 layers」,表示目前沒有。但並非此時真的不存在「圖層」,只是「圖層」還未與「影像」結合。


本小段之中,選單及項目名稱的英文:
【註a】[Image] / Filters / Script-Fu / Refresh Scripts
【註b】[Image] / File / Create / Logos / Newsprint Text2。Logos 在GIMP 2.2版譯成「標誌」。


單步追蹤3. 第24到第33行:變數與新影像
28: (img (car (gimp-image-new width height RGB)))
  • 產生新影像,影像尺寸根據文字圖層尺寸,將新影像存在img變數內。29: (bg-layer (car (gimp-layer-new img width height RGB-IMAGE "Background" 100 NORMAL-MODE)))
  • 產生新圖層,作為背景,圖層存在bg-layer變數內。在圖層面版內,圖層名稱為Background。

30: (text-layer (car (gimp-layer-new img width height RGBA-IMAGE "Text layer"
100 NORMAL-MODE)))
  • 產生新圖層,作為文字圖層,將文字圖層存在text-layer變數內。在圖層面版內,圖層名稱為Text layer。

注意:
(let* ( )
( )
……
)

  • 從第24行到第73行,整個程式被包在(let* )函式的括號內。
  • 第24行到第33行被包在括號內。
  • 在第24行到第33行定義的區域變數,使用範圍只到第33行之前。


單步追蹤4. 第38到第43行:加上兩個圖層
  • 在下圖的影像視窗標題上,顯示「2 layers」,表示影像已加上兩個圖層。而在圖層面版內,會發現有兩個圖層。

  • 在下圖的圖層面版內,圖層的名稱為「Text layer」與「Background」。


38: (gimp-image-add-layer img bg-layer 1)
39: (gimp-image-add-layer img text-layer -1)
40:
41: (gimp-context-set-background bg-color)
42: (gimp-edit-clear bg-layer)
43: (gimp-edit-clear text-layer)
  • 第42行,清除圖層內容後,「Background」圖層填上設定的背景色(白色)。
  • 第43行,清除圖層內容後,「Text layer」圖層顯現出透明。


單步追蹤5. 第45到第49行:圖層寫上文字
  • 使用文字編輯器,修改news-text2.scm檔。
  • 原本,已經刪除news-text2.scm程式碼的第36行到第69行。
  • 現在,加上45到49行,儲存檔案。
  • 執行「Refresh Scripts」【註a】,更新GIMP的程序資料庫內的資料。
  • 執行「Newsprint Text2」【註b】

45: (gimp-context-set-foreground text-color)
46: (gimp-floating-sel-anchor
47: (car (gimp-text-fontname img text-layer
48: (/ (+ 20 blur-radius) 2) (/ (+ 20 blur-radius) 2)
49: string 0 TRUE font-size PIXELS font)))
  • 寫上前景色(黑色)的Gimp字樣。
  • 反轉顏色為白色字的Gimp。
  • 下圖展示了,在圖層面版內,圖層已加上了遮罩。


本小段之中,選單及項目名稱的英文:
【註a】[Image] / Filters / Script-Fu / Refresh Scripts
【註b】[Image] / File / Create / Logos / Newsprint Text2。Logos 在GIMP 2.2版譯成「標誌」。


休息一下,整理一下
  • 前面,第 1 步 ~ 第 5 步 ,單步執行「印刷文字」,至寫上字體。
  • 之後,第 6 步 ~ 第 8 步 ,單步執行「印刷文字」,至產生字效。


單步追蹤6. 第51與52行:新增圖層遮罩
  • 使用文字編輯器,修改news-text2.scm檔,加上51、52行,儲存檔案。
  • 執行「Refresh Scripts」,執行「Newsprint Text2」。
51: (set! text-mask (car (gimp-layer-create-mask text-layer ADD-ALPHA-MASK)))
52: (gimp-layer-add-mask text-layer text-mask)
  • 第51行,set!是用來宣告廣域變數的函式,以「Text layer」圖層的透明色版為樣本,產生圖層遮罩,存在text-mask變數內。
  • 第52行,替「Text layer」圖層加上遮罩。

  • 下圖為「新增圖層遮罩」對話盒,第51行的ADD-ALPHA-MASK,相當於初始化為「圖層的透明色版」選項。



單步追蹤7. 第54到第56行:完成填色三步
  • 加上54行至60行,儲存檔案。
  • 執行「Refresh Scripts」,執行「Newsprint Text2」。

  • 下圖的影像視窗內,黑白相混呈現灰色。因為遮罩填上灰色,上方的黑色呈現半透明,與下方的白色相混。

54: (gimp-selection-layer-alpha text-layer)
55: (gimp-context-set-background (list grey grey grey))
56: (gimp-edit-fill text-mask BACKGROUND-FILL)
  • 54、55、56行是對遮罩填上灰色的動作。

  • Script-Fu程式碼的寫作,有一個固定的組合。
  • 填色要三個步驟、三行程式碼:
    • 設定作用中圖層,或選取一個填色範圍。
    • 設定顏色,設定前景色或背景色。
    • 填滿顏色。
  • 別忘了,把大象放到冰箱,也要三個步驟。Just a joke!


單步追蹤8. 第57到第66行:產生圓形斑點
  • 執行「報紙印刷濾鏡」產生斑點,不能在全黑的文字上。因此,遮罩的文字是灰色。可用模糊濾鏡,改變文字邊緣的灰度。
  • 下圖為最終成果圖,已執行完「報紙印刷」濾鏡。

  • 加上57行至66行,儲存檔案。
  • 執行「Refresh Scripts」,執行「Newsprint Text2」。
  • 57行,釋放選取區域。
  • 59行,模糊遮罩上的文字。
57: (gimp-selection-none img)
58: (if (> blur-radius 0)
59: (plug-in-gauss-iir RUN-NONINTERACTIVE img text-mask blur-radius 1 1)
60: )
62: (plug-in-newsprint RUN-NONINTERACTIVE img text-mask cell-size
63: 0 0 45.0 3 45.0 0 45.0 0 45.0 0 3)
64:
65: (gimp-edit-fill text-layer FOREGROUND-FILL)
66: (gimp-layer-remove-mask text-layer MASK-APPLY)