Layer Export GIMP Script

About

This is a GIMP scheme script that will export a given layer from a provided .xcf file, on the command line. While the execution of this script is slow, it works well. Combined with generategfx.py, this will allow GIMP to be an effective tool for maintaining tile-sets in your game project.

Installation

Save the script below as sg-save-all-layers.scm under /2.0/gimp/2.0/scripts/, wherever you may have The GIMP installed. For Windows users, this will most likely be: C:\Program Files\GIMP-2.0\share\gimp\2.0\scripts. Then, be sure to restart GIMP if you haven't already.

Use

The command line syntax for invoking this script leaves much to be desired. It is something best maintained in a shell script or a makefile. For brevity's sake, the invocation syntax is provided here as it would appear in a Makefile:

#NOTE: the following var will be different depending on the install location for Linux/Mac/BSD
GIMP = /Progra~1/GIMP-2.0/bin/gimp-console-2.6.exe 

#Forces GIMP to run in "headless" mode, which speeds things up a little
GFLAGS = --no-data --no-fonts --no-interface

sprites_page1.png: data/sprites.xcf
    $(GIMP) $(GFLAGS) -b "(sg-save-layer-cmd \"data/sprites.xcf\" \"sprites_page1\")" -b "(gimp-quit 0)"

Our sg-save-layer-cmd expects two arguments: the source .xcf file and the name of the layer to export. This will generate a PNG file on the current path that is based on the name of the layer. In this case, the layer "sprites_page1" in "data/sprites.xcf" is converted to "sprites_page1.png".

sg-save-all-layers.scm

Please see Installation above, for notes on where to copy this file.

; This program is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation; either version 2 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
; GNU General Public License for more details.

;; Command is installed in "File->Save all layers..."
;;
;; A template string should be provided which fits the form: prefix~~~~.ext
;; where prefix is a character string (optionally null).
;;       ~~~~ represents the digits of the frame number, one ~ per digit
;;       ext is the filename extension (which also specifies the format)
;; the tildas are optional and four digits will be assumed if omitted.
;; an extension of .png is assumed if one is not provided
;; the period is significant, if PNG is not to be assumed
;;
;; A checkbox provides the option of using the layernames for the
;; filenames. The extension given in the template is used to determine
;; the file type. Animation settings (delay and frame disposal) are not
;; included as part of the filename.
;;
;; When saving to GIF files, the GIMP's default values are used to
;; convert to INDEXED mode (255 color palette, no dithering).
;; Note: this is done on a layer-by-layer basis, so more colors may result
;; than if the entire image were converted to INDEXED before saving.


(define (sg-save-all-layers orig-image drawable layername)
  (define (get-all-layers img)
    (let* (
        (all-layers (gimp-image-get-layers img))
        (i (car all-layers))
        (bottom-to-top ())
        )
      (set! all-layers (cadr all-layers))
      (while (> i 0)
        (set! bottom-to-top (append bottom-to-top (cons (aref all-layers (- i 1)) '())))
        (set! i (- i 1))
        )
      bottom-to-top
      )
    )
  (define (save-layer orig-image layer name)
    (let* (
        (image 0)
        (buffer "")
        )
      (set! buffer (car (gimp-edit-named-copy layer "temp-copy")))
      (set! image (car (gimp-edit-named-paste-as-new buffer)))
      (when (and (not (= (car (gimp-image-base-type image)) INDEXED))
                 (string-ci=? (car (last (strbreakup name "."))) "gif"))
        (gimp-image-convert-indexed image
                                    NO-DITHER
                                    MAKE-PALETTE
                                    255
                                    FALSE
                                    FALSE
                                    "")
        )
      (gimp-file-save RUN-NONINTERACTIVE image (car (gimp-image-get-active-layer image)) name name)
      (gimp-buffer-delete buffer)
      (gimp-image-delete image)
      )
    )
  (let* (
      (layers nil)
      (fullname "")
      (framenum "")
      (settings "")
      (default-extension "png")
      (extension "png")
      (orig-selection 0)
      )
    (gimp-image-undo-disable orig-image)
    (set! orig-selection (car (gimp-selection-save orig-image)))
    (gimp-selection-none orig-image)

    (set! layers (get-all-layers orig-image))
    (while (pair? layers)
        (set! fullname (car (gimp-drawable-get-name (car layers))))
        (when (or (string=? layername "*") (string=? layername fullname))
            (set! fullname (string-append fullname "." extension))
            (save-layer orig-image (car layers) fullname)
        )
        (set! layers (cdr layers))
    )
    (gimp-selection-load orig-selection)
    (gimp-image-remove-channel orig-image orig-selection)
    (gimp-image-undo-enable orig-image)
  )
)
(script-fu-register "sg-save-all-layers"
 "Save all layers..."
 "Save each layer to a file, based on each layer's name."
 "Eric Anderton, based on code by Saul Goode"
 "Licensed GPL V2.0, Eric Anderton, Saul Goode"
 "2/8/2009"
 ""
 SF-IMAGE    "Image"    0
 SF-DRAWABLE "Drawable" 0
 )

(script-fu-menu-register "sg-save-all-layers"
                         "<Image>/File/")

(define (sg-save-layer-cmd filename layername)
   (let* ((image (car (gimp-file-load RUN-NONINTERACTIVE filename filename)))
          (drawable (car (gimp-image-get-active-layer image))))
        (sg-save-all-layers image drawable layername)
     (gimp-image-delete image))    
)