(or how to draw an arrow with an outline)
As part of a project that I’m working on, I found myself drawing lots of red arrows with yellow outlines. To do this I was using the GIMP image editor.
This was tedious. I would draw a yellow arrow for the outline, then draw a red arrow slightly smaller, then merge down so I had one layer. I started wondering about scripting it.
First I started by just calling the FU_arrow.scm script with my values. It wasn’t hard to write a script that did that. In my case, I did:
(FU-arrow image drawable 80.0 25 TRUE 75 500 ; brush thickness FALSE ; use forst point as head FALSE ; delete path after arrow was drawn TRUE ; use new layer for arrow FALSE ; draw double headed arrow FALSE ; useless )
In other words, my plugin just called the FU-arrow plugin. Next I added a little bit of code around that:
(gimp-image-undo-group-start image) (gimp-context-push) (gimp-palette-set-foreground '(255 255 0)) ; yellow (FU_arrow image drawable 80.0 ...) ; draw outer (bottom) layer (gimp-palette-set-foreground '(255 0 0)) ; red (FU_arrow image drawable 80.0 ...) ; draw inner (top) layer (gimp-context-pop) (gimp-image-undo-group-end image)
This saved the state and set the foreground colours appropriately so I didn’t have to, and also made it easy to undo in a single action.
You can see that I called FU_arrow twice. Next I needed to merge them down. For that, I used the facility in the arrow plugin that lets you create the arrow as a new layer. New layers are added at the top of the layer stack, so it’s fairly easy to grab that and work with it. The interesting code is:
(set! current-layers (cadr (gimp-image-get-layers image))) (set! arrow-foreground-layer (vector-ref current-layers 0))
Once I have a handle on the foreground layer, I can use gimp-image-merge-down with CLIP-TO-BOTTOM-LAYER to merge the two layers:
(gimp-image-merge-down image arrow-foreground-layer CLIP-TO-BOTTOM-LAYER)
Because I know nobody else created a layer between the two layers I created, it’s easy to get a handle on the new layers the FU-arrow plugin made.
My total plugin is:
(define (script-fu-quick-arrow image drawable) (let * ( (arrow-background-layer -1) (arrow-foreground-layer -1) (current-layers -1) ) (gimp-image-undo-group-start image) (gimp-context-push) (gimp-palette-set-foreground '(255 255 0)) (FU-arrow image drawable 80.0 25 TRUE 75 500 ; brush thickness FALSE ; use forst point as head FALSE ; delete path after arrow was drawn TRUE ; use new layer for arrow FALSE ; draw double headed arrow FALSE ; useless ) (set! current-layers (cadr (gimp-image-get-layers image))) (set! arrow-background-layer (vector-ref current-layers 0)) (gimp-palette-set-foreground '(255 0 0)) (FU-arrow image drawable 80.0 25 TRUE 75 1 ; brush thickness FALSE ; use first path as head TRUE ; delete path after arrow was drawn TRUE ; use new layer for arrow FALSE ; draw double headed arrow FALSE ; useless ) ;script-fu-draw-arrow function call (set! current-layers (cadr (gimp-image-get-layers image))) (set! arrow-foreground-layer (vector-ref current-layers 0)) (if (= -1 arrow-foreground-layer) (gimp-message "Foreground is -1")) (if (= -1 arrow-background-layer) (gimp-message "Background is -1")) (gimp-image-merge-down image arrow-foreground-layer CLIP-TO-BOTTOM-LAYER ) (gimp-context-pop) (gimp-image-undo-group-end image) ) ; let ) ;define ; Register with GIMP: (script-fu-register "script-fu-quick-arrow" _"Quick Arrow" _"Draw a nearly arbitrary arrow in your image in red with a yellow outline. Arrow will be created in a separate layer. Needs FU_arrow.scm" "Andrew" "2016, Andrew" "2016-09-01" "*" SF-IMAGE "The image" 0 SF-DRAWABLE "The drawable" 0 ) (script-fu-menu-register "script-fu-quick-arrow" "/Script-Fu/")
Quick edit: to install the script, copy it to the scripts directory. You can find that with Edit -> Preferences -> Folders -> Scripts (I used the user folder rather than the system folder). Then Filters -> Script-Fu -> Refresh Scripts. Et voilà!