I've been working on a project that required some relatively simple, but time consuming image hacking. Specifically, I needed to generate a CSS sprite image from an image that has to be rotated a number of times. The result are the following two Script-Fu functions.
bs-spin-layer: This plugin takes the currently selected layer and duplicates it, then rotates it a number of degrees. It will prompt you for the starting and ending rotation, as well as the step value to use. Nothing fancy here.
bs-layers-to-sprite-ribbon: This plugin is a bit sexier, and may turn out to be a generally useful tool. Supposing you've got a file named foo.xcf, the plugin creates a brand new image named foo.sprite.xcf which consists of each of the layers in foo.xcf, though, they are laid out side by side to create a sprite ribbon. At the same time the foo.sprite.xcf is created, foo.sprite.css is created, which contains the basic CSS you'd need to power the generated sprite. The correct background-position offsets and the appropriate height and width for each layer are calculated and stored in this file.
Every time I use it, I like Script-Fu just a little bit more. I may be the only fan left, but I'm a big one.
Download the code at: utils.scm (needed by both plugins), sprite-ribbon.scm and spin-layer.scm.
And here are the functions plugins minus the required utility functions:
;; ;; The spin-layer module is responsible for spinning (rotating) a layer a number ;; of times to create new layers. ;; (define (bs-spin-layer img drawable start end step) (gimp-image-undo-group-start img) (let loop ((angle start)) (cond ((<= angle end) (let ((layer (car (gimp-layer-new-from-drawable drawable img)))) (gimp-image-add-layer img layer -1) (gimp-drawable-set-name layer (number->string angle)) (gimp-drawable-transform-rotate layer (d->r angle) TRUE 0 0 TRANSFORM-FORWARD INTERPOLATION-CUBIC FALSE 3 TRANSFORM-RESIZE-ADJUST) (loop (+ angle step)))) (else 'done))) (gimp-image-undo-group-end img) (gimp-displays-flush)) (script-fu-register "bs-spin-layer" "Spin Layer" "Spin (rotate) a layer a bunch of times" "Ben Simon" "Copyright 2011, Ideas2Executables" "2011/12/29" "RGB* GRAY*" SF-IMAGE "Image to Spin" 0 SF-DRAWABLE "Layer to Spin" 0 SF-VALUE "Start Angle" "15" SF-VALUE "End Angle" "360" SF-VALUE "Step" "15") (script-fu-menu-register "bs-spin-layer" "<Image>/Filters/Util") ;; ;; The sprite-ribbon is responsible for generating a CSS sprite image. ;; Inspired by: http://registry.gimp.org/node/24538 ;; (define (bs-layers-to-sprite-ribbon img drawable css-selector sprite-prefix) (define (sprite-css-header file-name) (display (&& css-selector " { " "background-repeat: no-repeat; " "background-image: url(" file-name "); " "}\n"))) (define (sprite-css-entry layer x-off) (display (&& css-selector "." sprite-prefix (car (gimp-drawable-get-name layer)) " {" "width: " (car (gimp-drawable-width layer)) "px; " "height: " (car (gimp-drawable-height layer)) "px; " "background-position: " (* -1 x-off) "px 0px; " "}\n"))) (gimp-image-undo-group-start img) (let ((layers (bas-image-layer-list img)) (file-name (car (gimp-image-get-filename img)))) (let ((width (foldr (lambda (w layer) (+ w (car (gimp-drawable-width layer)) 2)) 0 layers)) (height (foldr (lambda (h layer) (max h (car (gimp-drawable-height layer)))) 0 layers))) (let ((sprite (car (gimp-image-new width height RGB)))) (with-output-to-file (morph-filename file-name "sprite.css") (lambda () (sprite-css-header (morph-filename file-name "sprite.png")) (let loop ((layers (reverse layers)) (x-off 0)) (cond ((null? layers) 'done) (else (let ((clone (car (gimp-layer-new-from-drawable (car layers) sprite)))) (gimp-image-add-layer sprite clone -1) (gimp-drawable-set-name clone (car (gimp-drawable-get-name (car layers)))) (gimp-layer-set-offsets clone x-off 0) (sprite-css-entry clone x-off) (loop (cdr layers) (+ x-off (car (gimp-drawable-width (car layers))) 2)))))))) (gimp-image-set-filename sprite (morph-filename file-name "sprite.xcf")) (gimp-display-new sprite) (gimp-image-undo-group-end img))))) (script-fu-register "bs-layers-to-sprite-ribbon" "Layers > Sprite Ribbon" "Create a CSS spirte ribbon from the layers in the image" "Ben Simon" "Copyright 2011, Ideas2Executables" "2011/12/29" "RGB* GRAY*" SF-IMAGE "Image to process" 0 SF-DRAWABLE "Active layer" 0 SF-STRING "Sprite CSS Selector" "" SF-STRING "CSS Layer Prefix" "") (script-fu-menu-register "bs-layers-to-sprite-ribbon" "<Image>/Filters/Util")