schemebatch-processinggimpscript-fu

GIMP Script-fu Batch Background Replacement


Objective

I have a bunch of .tga images that use transparency. These images are used in an application where they are sometimes rendered with their transparency and sometimes without, so the 'background' (the RGB areas corresponding to the black parts in a layer mask containing the alpha channel) is critically important.

In order to change this background for an individual image, my manual process (which may not even be the most efficient) is: Add layer mask > Transfer layer's alpha channel > copy contents of layer mask > Apply layer mask > paste new background layer into the image (same dimensions) > move new layer to bottom of stack > flatten image > Add layer mask (to resulting single layer) > Transfer layer's alpha channel > paste contents of previous layer mask from clipboard > Apply layer mask > export to .tga.

I am attempting to write a script that takes as arguments: a target file extension, a directory containing target files, a new background image, and an option to create backups of the target files. The batch script should apply the above process to every image in the directory with the target file extension.

Approach

Following the example of GIMP's scripting tutorial and their batch mode page, I wrote the following script-fu (scheme). I have not done any sort of exception handling for cases where the background and target images are different dimensions or file types. For my purposes, all target files are .tga and all backgrounds are .tga/.png/.jpg.

(script-fu-register
    "batch-background-replacement"
    "Batch Background Replacement"
    "Replace backgrounds of all images in a directory"
    "Callistonian"
    "2021, Callistonian"
    "September 28, 2021"
    ""
    SF-STRING   "File type"             "tga"
    SF-DIRNAME  "Directory"             ""
    SF-FILENAME "New background"        (string-append "" gimp-data-directory "")
    SF-TOGGLE   "Create backups?"       0
)

(script-fu-menu-register "batch-background-replacement" "<Image>/File")

(define (batch-background-replacement fileType directory background backups)
    (let*
        (
            (filelist (cadr (file-glob (string-append directory "*." fileType) 1)))
        )
        (while (not (null? filelist))
            (let*
                (
                    (filename (car filelist))
                    (image (car (gimp-file-load 1 filename filename)))
                    (layer (car (gimp-image-get-active-layer image)))
                )
                (gimp-image-undo-disable image)
                (if (equal? backups 1)
                    (gimp-file-save 1 image layer (string-append filename "_backup") (string-append filename "_backup"))
                )
                (gimp-layer-add-mask layer (car (gimp-layer-create-mask layer 3)))
                (gimp-edit-copy (car (gimp-image-get-active-drawable image)))
                (gimp-layer-set-apply-mask (car (gimp-image-get-active-layer image)) TRUE)
                (gimp-image-insert-layer image (car (gimp-file-load-layer 1 image (car (gimp-file-load 1 background background)))) 0 1)
                (gimp-image-flatten image)
                (gimp-layer-add-mask (car (gimp-image-get-active-layer image)) (car (gimp-layer-create-mask layer 3)))
                (gimp-edit-paste (car (gimp-image-get-active-drawable image)) TRUE)
                (gimp-layer-set-apply-mask (car (gimp-image-get-active-layer image)) TRUE)
                (gimp-image-undo-enable image)
                (gimp-file-save 1 image layer filename filename)
                (gimp-image-delete image)
            )
            (set! filelist (cdr filelist))
        )
    )
)

script dialogue box

Problem

After resolving some syntax errors, the script now runs but fails silently - nothing happens to the target images and there is no evidence GIMP has done anything.

Comments

I suspect there is a problem with the paths to the target images and the new background and the script simply isn't finding either of them. But I haven't found a way to print anything anywhere which makes debugging, well, impossible.

This is my first attempt at writing a GIMP script or using scheme. I know that GIMP's Batch Mode page actually suggests using the command line for batch processing, but I'd prefer for all inputs to be given in a nifty dialogue box like the one this script provides.


Solution

  • gimp-message is the command to get debug messages, either to a popup dialog or into the Error Console

    Also I think you need a directory separator, DIR-SEPARATOR in this line:

    (string-append directory "*." fileType)
    

    Otherwise you get this: "C:\\Program Files\\GIMP 2.10\\share\\gimp\\2.0*.tga" which probably won't match any of your files.

    i.e. (string-append directory DIR-SEPARATOR "*." fileType) to get this:

    "C:\\Program Files\\GIMP 2.10\\share\\gimp\\2.0\\*.tga"