You are here

Cut, Copy, and Paste Multiple Layers

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
Rate this item!
AttachmentSize
deep-float-copy.scm6.39 KB

(Updated May 1, 2010)

Description:

This plugin contains three Script-Fu scripts: "Float Linked Layers (Cut)", "Float Linked Layers (Copy)", and "Merge Linked Layers (Paste)". The scripts will appear under "Script-Fu->Multi-Layer-Cut-Copy-Paste" menu. These scripts allow you to cut or copy a selection from multiple layers, manipulate the resulting multi-layer selection, and then paste the data from each layer back down into its original layer. I use it in creating sprites. I create one multiple layer image, perhaps 64x128 pixels in size, in which one layer might be the head, then the torso in another layer, a layer for each arm, a layer for each leg, etc. I then link the layers together and select the whole image. I then change the canvas size to be, e.g., 8 times as wide as it originally was. I then us "Copy" to create a copy of all layers at once, use the move tool to move it over 64 pixels, and use "Paste" to paste all of the data from the temporary copies into their original layers. I then repeat the process six more times (making sure to only have the original 64x128 space selected. I end up with 8 perfect, multi-layer replicas. At this point I unlink all of the layers. I can then manipulate individual parts of each of the "frames" without altering other parts of the image (since the other parts remain in other layers. If I wish to work on two parts at once (say rotate both an upper and lower arm around a common origin), I can link those two layers, create a selection that encompases only the area I wish to manipulate, "Cut" that section, and then operate on both layers independent of any other parts of those layers, and "Paste" them back to their proper layers when I am done. You, of course, can use it however you like.

Usage:

To use this plugin, link together the layers you wish to manipulate, create a selection that encompasses all or part of the linked layers (whichever part you want to operate on), and then choose either "Float Linked Layers (Cut)" or "Float Linked Layers (Copy)" from the "Script-Fu->Multi-Layer-Cut-Copy-Paste" menu.

Assuming that you linked together the desired layers and made a selection, you will now have new, floating layers above each of the linked layers. The original layers will be unlinked as a result. Instead, these new floating layers will be linked together and can be manipulated jointly as though they were one layer using various transformation tools such as the move tool, the rotation tool, and the scaling tool. Other operations that work on linked layers should also work on these temporary layers.

When you have finished the desired operations, select "Merge Down Linked Layers (Paste)" from the "Script-Fu->Multi-Layer-Cut-Copy-Paste" menu. Provided that you have not unlinked any of the temporary layers that were created, created any new layers in the interim, or deleted any layers in the interim, the image data contained in each of the temporary layers which were created will be moved back into the layer from which it originally came, the temporary layers will be automatically deleted, and the layers which were originally linked will be re-linked. The results may vary if you create new layers or delete existing layers between the time that you originally cut/copy the selection from the linked layers and the time that you paste the selected material back down.

The "Cut" and "Paste" scripts were created by Saul Goode, dated 12/16/2006, and released under the terms of the GPLv2. I have made minor cosmetic changes to those scripts (essentially limited to renaming them and moving them into a sub-menu under Script-Fu). The "Copy" script is a derivative work of the "Cut" script which I originally created on April 3, 2010. It is, of course, released under the terms of the GPLv2.

The scripts have been tested in Gimp v2.6.8. There is nothing peculiar to them that should proclude their use in the 2.4 series but I haven't tested them in it so I cannot provide assurances that they will work as expected. They may also work in earlier versions of Gimp but there are no guarantees at all.

Installation Instructions:

Download the "deep-float-copy.scm" file and place it in the "scripts" directory of your Gimp installation. If you are unsure as to where the "scripts" directory resides, open Gimp, select "Edit->Preferences" choose "Folders" in the scroll down menu on the left and click to expand it (there should be a small '+' or similar such marking which you can click), and then select the "Scripts" item. On the right you should be presented with a list of one or more places in which Gimp will look for Script-Fu scripts. You may choose to add an additional folder here if, for instance, the system you are using restricts your account from copying items into the folder(s) in which Gimp already looks for scripts.

About the Update:

This update restores the original "Cut" script, renames all three scripts, and moves them into a submenu off of the main "Script-Fu" menu. Upon working further with the script I realized that there were instances in which the original "cut" script is extremely useful.

Common Problems:

"Error: reverse: argument 1 must be: pair". If you see this message it means that you have neglected to link any layers. You must link layers together - to do so, in the Layers dialog, next to the "eye" that tells you whether or not a layer is visible is a blank space. Clicking this blank space will show "chain links". The script will technically work with only one layer "linked" though in that case it operates in essentially the same way that an ordinary cut or copy would.

Scaling. Moving. Etc. If you experience any problems with scaling, moving, rotating, etc., undo the attempted action and ensure that you have one of the new temporary layers selected. If you are trying to scale to a larger size, note that the temporary layers are only created to the size of the selection. So while the scaling operation will appear normal, the results will be clipped to the size of the layer. To fix this, simply select each of the temporary layers (identifiable by the fact that they are the linked layers), and for each one, go to the menu and select "Layer->Layer to Image Size". Note also that while any transformations which show you a preview of their results (e.g. scale and rotate) will operate on all linked layers, only the layer that is selected will appear to be being transformed in the preview of the results. So you will need to choose which layer you want to see a preview for.

Adding/Deleting Layers. Selecting "Merge Down Linked Layers (Paste)" without having done a corresponding "Cut" or "Copy". If you add a layer between a layer which was floated and the temporary layer that is created by "Cut" or "Copy", the subsequent "Paste" operating will paste the data into that newly added layer and not the original layer from which it came. If you have two layers linked and, without choosing "Cut" or "Copy", simply choose "Paste", the two layers will be combined into whichever layer exists below them. The bottom layer will remain unaffected. If more than two layers are linked, an error will occur if you try to paste in most cases. If there is at least one unlinked layer between each linked layer, no error will result and the contents of each of the linked layers will be merged down into the layer below it.

Code License: 
GIMP Version: 
Scripting Engine: 

Comments

Than you for this useful script!

It needed some corrections to work with Gimp 2.8.4 (Ubuntu 13.04)

First i got "non-list argument to append" -errors (like Hymer did)
They got fixed by changing all
(linked 0), (select 0), (layer 0), (floated 0) and (mode 0) -lines
to
(linked '()), (select '()), (layer '()), (floated '()) and (mode '()) -lines. (with tip from saulgoode) [also restarted GIMP after altering the script]
Not tested this widely, but at least I used the script to copy-paste a multilayer picture once.

- nikop

I use Gimp 2.8.2 in Win7. I cannot select multiple layers and I get this message when I try to use "Execution error for 'Float Linked Layers (Copy)':
Error: ( : 25988250) non-list argument to append "

The subroutine collectListAllLayers probably has an error in it.

Check for: (listLayers 0)
This should read: (listLayers ())

The complete subroutine should read as follows:

(define (collectListAllLayers image)
    (let* (
            (all-layers (gimp-image-get-layers image))
			(num-layers (car all-layers))
            (i num-layers)
            (listLayers ())
        )
        (set! all-layers (cadr all-layers))
        (while (> i 0)
            (set! listLayers (append listLayers (list (vector-ref all-layers (- i 1)))))
            (set! i (- i 1))
        )
        (set! listLayers (cons num-layers (reverse listLayers)))
        listLayers
    )
)

If the above is not the case check your script for other "append" calls like the one above:
(set! listLayers (append listLayers (list (vector-ref all-layers (- i 1)))))
Then check the declaration of the target list.

Cheers!

There are a couple of lines in the file that contain

(linked 0)

These should be changed to

(linked '())

I tried that, but It still comes up with that error....

Here, I uploaded the edited file.....
https://www.dropbox.com/s/a2khku2b58w2rpe/deep-float-copy.scm

What's wrong?

This is absolutely fantastic. Exactly what I needed for my own sprite production. Thank you!

Some time ago I sent the following mail to the author of mig-gimp-layer-groups. I did not get any reaction yet, but maybe you might find it useful.

Subject: mig-gimp-layer-groups

Hello Miguel,

The other day I found myself in a situation where I had to modify some stuf in rather large files (over 120 layers). I came across this “deep float” plugin which looked promising. It lacked a few things so I corrected that and then again I found that there were things which were allready in your plugin and it seemed a good idea to use those instead, put everything in one menu, etc, etc, ….

Anyhow, a few days later I ended up with some stuff which did the job for me. There might still be a few bugs in it and it’s badly documented but it might be worth to smooth it up and incorporate it in your plugin. The file can be installed next to yours but I found this a bit unstable when handling large files so I combined the two on my machine. Just let me know what you think of it.

Now try to find a way to do more transformations over multiple layers :-).

Cheers,

Klaas

********************************************************************
Unfortunately I can't figure out right now how to attach something, so I'll just cut and paste.
It might screw up the indentation ;-{
********************************************************************

; 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.

;===============================================
(define TempUnlinkedLayersList '())

;===============================================
(define (collectListAllLayers image)
(let* (
(all-layers (gimp-image-get-layers image))
(num-layers (car all-layers))
(i num-layers)
(listLayers 0)
)
(set! all-layers (cadr all-layers))
(while (> i 0)
(set! listLayers (append listLayers (list (vector-ref all-layers (- i 1)))))
(set! i (- i 1))
)
; (reverse listLayers)
(set! listLayers (cons num-layers (reverse listLayers)))
listLayers
)
)

;===============================================
(define (script-fu-gimp-layer-group-togglelink-all image)
(let* (
(layers (gimp-image-get-layers image))
(num-layers (car layers))
(layer-array (cadr layers))
(new-link-setting FALSE)
(ii 0)
(layer 0)
)

(gimp-image-undo-disable image)

(set! ii 0)
(while (< ii num-layers)
(set! layer (aref layer-array ii))
(if (= (car (gimp-drawable-get-linked layer)) FALSE)
(set! new-link-setting TRUE)
(set! new-link-setting FALSE)
)
(gimp-layer-set-linked layer new-link-setting)
(set! ii (+ ii 1))
)
(gimp-displays-flush)
(gimp-image-undo-enable image)
)
)

;===============================================
(define (script-fu-gimp-layer-group-synchlink-all image)
(let* (
(layers (gimp-image-get-layers image))
(num-layers (car layers))
(layer-array (cadr layers))
; (new-link-setting (not (car (gimp-drawable-get-linked (car (gimp-image-get-active-drawable image))))))
(new-link-setting FALSE)
(ii 0)
(layer 0)
)

(gimp-image-undo-disable image)
(if (= (car (gimp-drawable-get-linked (car (gimp-image-get-active-drawable image)))) TRUE)
(set! new-link-setting TRUE)
(set! new-link-setting FALSE)
)

(set! ii 0)
(while (< ii num-layers)
(set! layer (aref layer-array ii))
(gimp-layer-set-linked layer new-link-setting)
(set! ii (+ ii 1))
)
(gimp-displays-flush)
(gimp-image-undo-enable image)
)
)

;===============================================
(define (script-fu-float-selection-linked image drawable retain-ori)
(let* (
(linked (cdr (collectListLinkedLayers image)))
(select 0)
(layer 0)
(floated 0)
)
(gimp-image-undo-group-start image)
(set! select (car (gimp-selection-save image)))
(while (pair? linked)
(gimp-drawable-set-linked (car linked) FALSE)
(gimp-selection-load select)
(if (= (car (gimp-drawable-mask-intersect (car linked))) TRUE)
(begin
(set! floated (car (gimp-selection-float (car linked) 0 0)))
(set! layer (car (gimp-layer-new-from-drawable floated image)))
(if (= retain-ori TRUE)
(gimp-floating-sel-anchor floated)
(gimp-image-remove-layer image floated)
)
(gimp-image-add-layer image layer -1)
(gimp-drawable-set-linked layer TRUE)
(gimp-layer-set-opacity layer (car (gimp-layer-get-opacity (car linked))))
(gimp-drawable-set-visible layer (car (gimp-drawable-get-visible (car linked))))
(gimp-layer-set-mode layer (car (gimp-layer-get-mode (car linked))))
)
(set! TempUnlinkedLayersList (append TempUnlinkedLayersList (list (car linked))))
)
(set! linked (cdr linked))
)
(gimp-selection-load select)
(gimp-image-remove-channel image select)
(gimp-image-undo-group-end image)
(gimp-displays-flush)
)
)

;===============================================
(define (script-fu-float-selection-linked-with-retention image drawable)
(script-fu-float-selection-linked image drawable TRUE)
)

;===============================================
(define (script-fu-float-selection-linked-without-retention image drawable)
(script-fu-float-selection-linked image drawable FALSE)
)

;===============================================
(define (script-fu-merge-each-linked image drawable)
(let* (
(layers (collectListAllLayers image))
(linked (cdr (collectListLinkedLayers image)))
(layer 0)
(tmode 0)
(topacity 0)
(tvisible 0)
)
(gimp-image-undo-group-start image)
(while (pair? linked)
(set! layer (member (car linked) layers))
(if (pair? (cdr layer))
(begin
(set! layer (cadr layer))
(set! tmode (car (gimp-layer-get-mode layer)))
(set! topacity (car (gimp-layer-get-opacity layer)))
(set! tvisible (car (gimp-drawable-get-visible layer)))
(gimp-drawable-set-visible (car linked) TRUE)
(gimp-layer-set-opacity (car linked) 100)
(gimp-layer-set-opacity layer 100)
(gimp-drawable-set-visible layer TRUE)
(set! layer (car (gimp-image-merge-down image (car linked) EXPAND-AS-NECESSARY)))
(gimp-layer-set-opacity layer topacity)
(gimp-drawable-set-visible layer tvisible)
(gimp-layer-set-mode layer tmode)
(gimp-drawable-set-linked layer TRUE)
)
)
(set! linked (cdr linked))
)
(while (pair? TempUnlinkedLayersList)
(gimp-drawable-set-linked (car TempUnlinkedLayersList) TRUE)
(set! TempUnlinkedLayersList (cdr TempUnlinkedLayersList))
)
(gimp-image-undo-group-end image)
(gimp-displays-flush)
)
)

; ------------ group of LINK activities --------
;===============================================
(script-fu-register
"script-fu-gimp-layer-group-togglelink-all"
(@gimpMenuLocation "/LayerGroups/3 - Link/Link: (91) Toggle All")
"TOGGLE all linked layers"
"Joseph Miller /Klaas van Rijt"
"Licensed GPL V2.0, 2011, Klaas van Rijt"
"January 29, 2011"
"RGBA RGB INDEXED*"
SF-IMAGE "Image" 0
)

(script-fu-register
"script-fu-gimp-layer-group-synchlink-all"
(@gimpMenuLocation "/LayerGroups/3 - Link/Link: (92) Synchronize All with Current")
"SYNCHRONIZE all layers with the link setting of the current active layer"
"Joseph Miller /Klaas van Rijt"
"Licensed GPL V2.0, 2011, Klaas van Rijt"
"January 29, 2011"
"RGBA RGB INDEXED*"
SF-IMAGE "Image" 0
)
;------------------------------------- SELECTION ----------------------------------------------

;===============================================
(script-fu-register
"script-fu-float-selection-linked-with-retention"
(@gimpMenuLocation "/LayerGroups/7 - Selection/Selection: (1) Float Linked Layers ( Copy)")
"Float the selection on each linked layer - retaining a copy in the original.\n\Inspired by Michael B. McLaughlin's float-each-linked-with-retention (04/03/2010)"
"Klaas van Rijt"
"Licensed GPL V2.0, 2011, Klaas van Rijt"
"January 29, 2011"
"RGBA RGB INDEXED*"
SF-IMAGE "Image" 0
SF-DRAWABLE "Drawable" 0
)

;===============================================
(script-fu-register "script-fu-float-selection-linked-without-retention"
(@gimpMenuLocation "/LayerGroups/7 - Selection/Selection: (2) Float Linked Layers (Cut)")
"Float the selection on each linked layer, creating a new one above it.\n\ Adaptation of Saul Goode's float-each-linked (12/16/2006) with added anchor option"
"Klaas van Rijt"
"Licensed GPL V2.0, 2011, Klaas van Rijt"
"January 29, 2011"
"RGBA RGB INDEXED*"
SF-IMAGE "Image" 0
SF-DRAWABLE "Drawable" 0
)

;===============================================
(script-fu-register
"script-fu-merge-each-linked"
(@gimpMenuLocation "/LayerGroups/7 - Selection/Selection: (3) Merge Down Floated Layers (Paste)")
"Merge each floated layer with the one beneath it.\n\Adaption of Saul Goode's Float Linked Layers (12/16/2006) preserving initial layer settings"
"Klaas van Rijt"
"Licensed GPL V2.0, 2011, Klaas van Rijt"
"January 29, 2011"
"*"
SF-IMAGE "Image" 0
SF-DRAWABLE "Drawable" 0
)

I don't think you may add attachments in replies ...but you are a registred member so you may well upload your own content
That may be well a new version of other one scripts, nothing wrong with that, even more when the chages are useful as in this case

about the author maybe he didn't monitor much this page because this script may loose his utility at soon gimp 2.8 will be out, already now gimp 2.7 may group layers out of the box (but the function is not complete yet, as example grouped layers don't support well layer mask )

anyway time may pass before gimp 2.8 and in the while good layer grouping script remain quite useful

PS as alternative to attachments for script
you may use something as www.pastebin.com and just post the link
(still i think the best if changes are relevant use your "create content" button to submit revised versions)

In this case I think people who would be interested could easily get it going with a "copy-paste" action but I really would have been up shit creek when would have tried to get some python code posted. I really appreciate your advice. Thanks!

This plugin seems to reset the opacity of not only the copied layers but also of the original ones.

That's why if you have 20+ layers, 10 of which have custom opacity value, it would be actually easier to copy them manually one by one.

Subscribe to Comments for "Cut, Copy, and Paste Multiple Layers"