You are here

Moving and pasting new layers--driving me crazy!

Heya,

I've got a situation where I need to make a minute correction to several hundred images.

The process of doing this by hand is incredibly time consuming, so I've been trying to look into some method of batch processing in order to handle this efficiently. I've never done this before, admittedly, but I spent a lot of time reading the tutorials here on Gimp.org and in the Procedure Browser trying to figure out how to do this via the command line.

I've run into a wall of "batch command experienced an execution error" crapouts and I've spent most of today trying to figure out where the code is breaking down and why. That's proven to be futile for me, because it seems like the code breaks in different ways depending on what's commented out and not ...

This is what my code currently looks like, with comments.

(define (batch-rw-resizer pattern)

(let* (
(filelist (cadr (file-glob pattern 1))))

(while (not (null? filelist))
(let* (
(filename (car filelist))
(image (car (gimp-file-load RUN-NONINTERACTIVE filename filename)))
(drawable (car (gimp-image-get-active-layer image))))

; Making a new layer out of the image.
(gimp-layer-new-from-drawable drawable image)

; Adding the layer to the image.
(gimp-image-add-layer image new-layer 0)

; Naming new layer.
(gimp-layer-set-name new-layer "Comic")

; Selecting the top part of the image.
(gimp-rect-select image 0 0 459 163 REPLACE 0 0)

; Cutting out the top part of the image.
(gimp-edit-cut drawable)

; Moving the remainder of the image down two pixels.
(gimp-layer-translate drawable 0 -2)

; Resizing entire image to fit the shifted layer
(gimp-image-resize-to-layers)

; Re-pasting the selection from the top
(gimp-edit-paste image drawable 1)

; Flattening the image.
(gimp-image-flatten image)

; Saving the file.
(gimp-file-save RUN-NONINTERACTIVE image drawable filename filename)
(gimp-image-delete image))
(set! filelist (cdr filelist))))
)

; End script

Hopefully the commented lines can help give you guys an idea of what I was meaning to do with each command; I am at a loss at what needs to be done for Gimp to properly process this batch script.

1) you need to assign the layerID of your newly create layer to your 'new-layer' variable:

(define (batch-rw-resizer pattern)

  (let* ((filelist (cadr (file-glob pattern 1))))
    (while (not (null? filelist))
      (let* ((filename (car filelist))
             (image (car (gimp-file-load RUN-NONINTERACTIVE filename filename)))
             (drawable (car (gimp-image-get-active-layer image)))
             (new-layer 0) )
        
        ; Making a new layer out of the image.
        (set! new-layer (car (gimp-layer-new-from-drawable drawable image)))
        
        ; Adding the layer to the image.
        (gimp-image-add-layer image new-layer 0)

2) You need to pass the imageID as an argument to 'gimp-image-resize-to-layers'

(gimp-image-resize-to-layers image)

3) You should not pass the imageID as an argument to 'gimp-edit-paste'

(gimp-edit-paste drawable 1)

Also, it is not entirely clear to me what your goal is, but you should double-check whether you wish to be pasting to the bottom layer ('drawable'), where your paste would seem to have no effect on the resulting flattened image. Perhaps you should pasting to the top layer ('new-layer')? If you end up changing this, you might also reconsider whether you want to be pasting into the selection -- it is more typical to pass "0" as the second argument to 'gimp-edit-paste', especially since you haven't modified the selection.

Well, my goal is to separate two parts of the images from each other by several pixels, increasing the size of the image in the process.

I was trying to use commands the way I would use them if I were doing this by hand in the GIMP itself; copying the image to a new layer, cutting out the top half of the new layer, shifting it down a few pixels, then pasting the selection back into the image as another new layer so that the top half remains where it was, resizing the canvas to fit the layers, then flattening the entire image.

I've modified the script to correct the problems you pointed out, but when I tested the script I recieved another error message:

"GIMP-Error: Calling error for procedure 'gimp-file-save':
Procedure 'gimp-file-save' has been called with an invalid ID for argument 'drawable'. Most likely a plug-in is trying to work on a layer that doesn't exist any longer.

batch command experienced an execution error"

I don't understand what's going on here. Shouldn't the "drawable" be the remaining layer after flattening the image?

Thank you for your help so far!

I don't understand what's going on here. Shouldn't the "drawable" be the remaining layer after flattening the image?

You are correct (I should have caught that); however, that remaining layer is not the same layer with which you started.

Flattening your image results in a new layer being created, and similarly to how you had to assign the result of 'gimp-layer-new-from-drawable' to a variable so that you could later reference it, you have to assign the result of 'gimp-image-flatten' to a variable (you can re-use either 'drawable' or 'new-layer' since neither one references an existing layer after the operation).

    (set! drawable (car (gimp-image-flatten image)))

    ; Saving the file.
    (gimp-file-save RUN-NONINTERACTIVE image drawable filename filename)

Aha! I see now ... I didn't know that had to be done.

Thank you for all the help! The script works perfectly!

...if I were doing this by hand in the GIMP itself; copying the image to a new layer, cutting out the top half of the new layer, shifting it down a few pixels, then pasting the selection back into the image as another new layer so that the top half remains where it was, resizing the canvas to fit the layers, then flattening the entire image.

In that case you can simplify your script a little bit by using 'gimp-edit-copy' instead of 'gimp-edit-cut' (thus alleviating the need to duplicate your original layer).

(define (batch-rw-resizer pattern)
  (let* ((filelist (cadr (file-glob pattern 1))))
    (while (not (null? filelist))
      (let* ((filename (car filelist))
             (image (car (gimp-file-load RUN-NONINTERACTIVE filename filename)))
             (drawable (car (gimp-image-get-active-layer image)))
             (floated-layer 0)
             )
        (gimp-rect-select image 0 0 459 163 REPLACE 0 0)
        (gimp-edit-copy drawable)
        (set! floated-layer (car (gimp-edit-paste drawable 0)))
        (gimp-layer-translate floated-layer 0 -2)
        (gimp-image-resize-to-layers image)
        (gimp-floating-sel-to-layer floated-layer)
        (set! drawable (car (gimp-image-flatten image)))
        (gimp-file-save RUN-NONINTERACTIVE image drawable filename filename)
        (gimp-image-delete image)
        )
      (set! filelist (cdr filelist))
      )
    )
  )
Subscribe to Comments for "Moving and pasting new layers--driving me crazy!"