You are here

Paste as new layer

Greetings
I have an image with 78 layers where I need to cut the right hand half of the layer and paste it as a new layer immediately above the layer I am cutting it from. The selection needs also to be pasted at the very left of the new layer. Doing this manually it works perfectly by making my selection, cut then Edit>Paste As>New Layer. So if I cut from layer 9 the new layer will be inserted between the existing 9 and 10 and become the new layer 10.

By stealing others' code I have got my script to successfully cut but I'm having big problems getting it to paste as a new layer at the correct layer level and at the correct origin within the layer. At present it creates a new layer at the top of the stack and the pasted selection is in the same position as the layer from which it was cut rather than at the complete left as I would like it.

What would be great would be if I could, via the script access the menu item Edit>Paste As>New Layer but it doesn't seem possible to do that - or is it?

This is what I have so far:
; An attempt at cutting and pasting.

(define (script-fu-sel-cut2 img

drawable)

(gimp-undo-push-group-start img)

(gimp-edit-cut drawable)

;Paste into a new layer

; (gimp-edit-paste-as-new-layer) ;doesn't work drat!

(gimp-image-undo-group-start img)

(let* ((draw (car (gimp-image-get-active-drawable img))))

(cond

((= (car (gimp-drawable-is-layer draw)) 1)

(gimp-floating-sel-to-layer (car (gimp-edit-paste draw 1))))

((= (car (gimp-drawable-is-layer-mask draw)) 1)

(gimp-floating-sel-to-layer (car (gimp-edit-paste (car (gimp-image-get-active-layer img)) 1))))

((= (car (gimp-drawable-is-channel draw)) 1)

(gimp-floating-sel-to-layer (car (gimp-edit-paste (vector-ref (cadr (gimp-image-get-layers img)) 0) 1))))

)

)

; Complete the undo group

(gimp-undo-push-group-end img)

; Flush output

(gimp-displays-flush)

(gimp-image-undo-group-end img)

)

(script-fu-register "script-fu-sel-cut2"

"Selection Cut 2"

"Copy the selection into the same layer"

"Dov Grobgeld"

"Dov Grobgeld"

"2002-02-12"

"RGB*, GRAY*"

SF-IMAGE "Image" 0

SF-DRAWABLE "Layer" 0)

(script-fu-menu-register "script-fu-sel-cut2"

"/Edit/My/Script")

Or would it be better to do it in python-fu? I haven't found any examples of python-fu scripts I can steal from to do even this so far yet.

TIA, Karl

Since the new layer appears at the top of the stack, you will have to lower it to the appropriate stack position.

First you need to add a couple of new variables to your let* -- I chose the names 'new-draw' and 'position'

Then for a layer, you just have to note the original layer's stack position and then lower the newly pasted layer appropriately (note that in all of the following I also added a 'gimp-layer-set-offsets' call to move the floated layer to the left edge per your description).

(set! position (car (gimp-image-get-layer-position image draw)))
(set! new-draw (car (gimp-floating-sel-to-layer (car (gimp-edit-paste draw 1)))))
(gimp-layer-set-offsets new-draw 0 (cadr (gimp-drawable-offsets new-draw)))
(while (> position 0)
(gimp-image-lower-layer image new-draw)))

For a layermask, the process is similar except that you must obtain the layer associated with the layermask (the other steps are unchanged).

(set! pos (car (gimp-image-get-layer-position image (car (gimp-layer-from-mask draw)))))

For a channel, things need to be handled differently because the PDB does not provide a way to directly convert a floated layer to a channel (at least, I haven't discovered one). I chose to create a new channel filled with black and then anchor the pasted selection into that channel. (I chose to create the channel by copying the original and filling it, though you can create it using 'gimp-channel-new' if you wished.)

(set! draw (car (gimp-channel-copy draw)))
(gimp-image-add-channel img draw -1)
(gimp-context-push) (gimp-context-set-foreground '(0 0 0))
(gimp-drawable-fill draw FOREGROUND-FILL)
(gimp-context-pop)
(set! new-draw (car (gimp-edit-paste draw FALSE)))
(gimp-layer-set-offsets new-draw 0 (cadr (gimp-drawable-offsets new-draw)))
(gimp-floating-sel-anchor new-draw)
)

I'm curious... How does GIMP know its the left when using offsets in the script, is it by default? What in the script tells GIMP to move the floated layer to the left, specifically? The position 0? If it were to be floated right, the correct syntax would be what?

(while (< position 0))?

I've been working on a Python script forever, but I keep getting lost in syntax translation because the procedures are loosely defined. For instance in the above code, looking in the procedure browser,"gimp-layer-set-offsets" is defined as such:

Set the layer offsets.
Parameters: layer LAYER the layer
offx INT32 offset in x direction
offy INT32 offset in y direction

Is the greater than symbol (>) indicative to which way the layer offsets?

The procedure browser gives no indication as to what exactly is taking place in the offset, unless of course its a channel and its automatically returned as 0.

I keep picking apart scripts hoping something will finally click and have it all make sense for me. Nonetheless, I'm a sponge for learning these things. Someone should do some online GIMP scripting instructing, I'd sign up.

The drawable offsets are the position of the pixel in the upper-left corner of the drawable relative to image coordinates (the upper-left corner of the image are always at location x=0, y=0). The offsets can be fetched as follows:

(set! x (car (gimp-drawable-offsets drawable)))
(set! y (cadr (gimp-drawable-offsets drawable)))

You can find out the width and height of the drawable:

(set! w (car (gimp-drawable-width image)))
(set! h (car (gimp-drawable-height image)))

You can find out the width and height of the image:

(set! W (car (gimp-image-width image)))
(set! H (car (gimp-image-height image)))

"If it were to be floated right, the correct syntax would be what?"

You would have to compute the new location of the drawable's upper-left corner such that the drawable's right edge coincides with the image's right edge. Using the above variables, this is represented by the formula x+w=W, so we want the x-offset of the drawable to be at position (W-w).

(gimp-layer-set-offsets drawable (- W w) y) ; align right edge, but keep vertical position

Going just a little further, if we wanted to center the layer horizontally in the image then we need the x-offset to be located such that the drawable's horizontal center is aligned with the image's horizontal center (W/2 = w/2).

(gimp-layer-set-offsets drawable (- (/ W 2) (/ w 2)) y)

This is good to know. I would have never guessed. Thanks Saul.

Is it even remotely possible to plot the four corner points of a perspective transformation and call them in a script to say, run duplication transformation on pattern layers? I've been scouring the internet on this very subject.

This is the posting that got me started in this direction:
http://registry.gimp.org/node/23889

Late to this discussion, but I have always created a new layer then used gimp-image-add-layer with the position -1 which insets it above the active layer.

Regarding the mapping, determining the matrix coefficients to transform a unit square to an arbitrary quadrilateral van be found at the bottom page 4 of this document:

http://graphics.cs.cmu.edu/courses/15-463/2008_fall/Papers/proj.pdf

-Rob A>

Wow, sweetness! I've been reading the Transformation Matrix/Perspective wiki for the last few hours. This pdf file needs to be added to the wiki. I'll email the co-author and send him the link.

fixed the link

Subscribe to Comments for "Paste as new layer"