Tuesday, January 23, 2007

Screen shots with Gimp

I kept going with the gimp scripting. Yesterday I had planned on adding another script that would be quick and easy. Ha ha. No such luck.

When I take a screen shot and want to highlight certain areas, I add a layer on top, set the opacity to like 30-50, then use an eraser to uncover the part. Then I set the layer to "difference" and put the opacity at like 20-25.

Here's an example...

Does a pretty good job. Not a particularly pretty thing, but works. What looks a little better? Add some texture to the outline. I add a drop shadow, 2x, 2y, 3px radius. However, I only want it on the exposed area inside the outline. The drop shadow, however, darkens the whole thing...

To deal with this, take the original cutout layer, and paste it as a mask on the drop shadow layer. You need to invert the original layer first. Its complicated, however the output looks like the following...

The accent is minor, but I really like it. However, the steps involved to produce it are more than I'd like to do every time I want to do a screen shot. But hey, I just learned gimp scripting, so this should be easy? Right?

It is and it isn't. The problem I had was getting the layer into the mask of another layer. In theory I needed a channel object, then could plug that in as the mask. However, for the life of me, I couldn't figure out how to get a reference to a channel of the layer. I still don't know how. I spent (ie. wasted) much of yesterday working on it. Finally, instead of doing that, I just copy the layer, and paste it into the mask. I had tried this and couldn't get that to work either. A couple hours later I realized I need to invert the colors first, then it worked. Here's the interesting part of the code...

(gimp-invert inDrawable)
(gimp-layer-set-opacity inDrawable 100)

(set! shadowMask (car(gimp-layer-create-mask shadowLayer ADD-ALPHA-MASK)))
(gimp-layer-add-mask shadowLayer shadowMask)

(gimp-selection-all inImage)
(gimp-edit-copy inDrawable)
(set! floatingSel (car (gimp-edit-paste shadowMask FALSE)))
(gimp-floating-sel-anchor floatingSel)

(gimp-layer-remove-mask shadowLayer MASK-APPLY)

(gimp-invert inDrawable)
(gimp-layer-set-opacity inDrawable 20)
(gimp-layer-set-mode inDrawable DIFFERENCE-MODE)

I had to do a few other tricks. I'll post the full code at the end. One included a general function to get the layer below the selected layer. That kind of thing.

Anyway, using the plug in works as follows. Get a screen shot into gimp. Add a layer, all white. Set the opacity to whatever you want so you can see through. Use the eraser to cut out parts. (By the way, how to draw straight lines in gimp). Once that's done, just run the script. Make sure the cut out layer is selected. That's it. Make sure its white and selected. The script handles setting the opacity, putting it in "difference" mode, etc.

Put it together with my script from yesterday and you've got one fancy screen shot for web pages...


Full code...


(define (internal-getLayerBelow
inImage
inLayer
)

(set! layerArray (car(cdr(gimp-image-get-layers inImage))))
(internal-getLayerBelowRecurse
inLayer
layerArray
0
)
)

(define (internal-getLayerBelowRecurse
inLayer
layerArray
index
)

(set! currentLayer (aref layerArray index))

(if (= currentLayer inLayer)

(aref layerArray (+ index 1))

(internal-getLayerBelowRecurse
inLayer
layerArray
(+ index 1)
)
)
)


(define (script-fu-kev-style-cutout
inImage
inDrawable
)

(script-fu-drop-shadow
inImage
inDrawable
2
2
3
'(0 0 0)
80
0)

(set! shadowLayer (internal-getLayerBelow
inImage
inDrawable
)
)

(gimp-invert inDrawable)
(gimp-layer-set-opacity inDrawable 100)

(set! shadowMask (car(gimp-layer-create-mask shadowLayer ADD-ALPHA-MASK)))
(gimp-layer-add-mask shadowLayer shadowMask)

(gimp-selection-all inImage)
(gimp-edit-copy inDrawable)
(set! floatingSel (car (gimp-edit-paste shadowMask FALSE)))
(gimp-floating-sel-anchor floatingSel)

(gimp-layer-remove-mask shadowLayer MASK-APPLY)

(gimp-invert inDrawable)
(gimp-layer-set-opacity inDrawable 20)
(gimp-layer-set-mode inDrawable DIFFERENCE-MODE)

;(gimp-selection-all inImage)
;(gimp-edit-copy inDrawable)

;(set! floatingSel (car (gimp-edit-paste shadowMask FALSE)))
;(gimp-floating-sel-anchor floatingSel)


;(gimp-image-remove-layer inImage (internal-getLayerBelow
; inImage
; inDrawable
; )
;)
)

(script-fu-register
"script-fu-kev-style-cutout" ;func name
"Kev Styleize Cutout" ;menu label
"Make the cutout areas pretty" ;description
"Kevin Galligan" ;author
"copyright 2007, Kevin Galligan" ;copyright notice
"January 21, 2007" ;date created
"*"
SF-IMAGE "Input image" 0
SF-DRAWABLE "Input drawable" 0
)
(script-fu-menu-register "script-fu-kev-style-cutout" "/Script-Fu/Kev")

No comments: