Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get sublayers from group layer with Python in Gimp

I have an XCD file with a nested layers structure:

image
    front-layer
    content-layer
        content-layer-name-1
        content-layer-name-2
        content-layer-name-3
    back-layer

I open the file with image = pdb.gimp_file_load(xcf_file, xcf_file) and can get front-layer, content-layer and back-layer as image.layers[0], image.layers[1] and image.layers[2]. But Gimp can't get sublayers in content-layer by list index.

I can use pdb.gimp_image_get_layer_by_name(image, 'content-layer-name-3'), but I don't known the layers' names.

I try pdb.gimp_item_get_children(image.layers[1]), but this method return INT32ARRAY with the item's list of children and I haven't found how retrieve the item by its id.

How can I get sublayers from a group layer with Python in Gimp (2.8)?

like image 506
tbicr Avatar asked Apr 19 '12 05:04

tbicr


People also ask

How to create layer groups in GIMP using Python-Fu?

The support to layer groups on Python-fu was added on the last minutes before 2.8 release, and is rather incomplete. So, the only way to create a proper layer group in GIMP 2.8 is to use the pdb call: group = pdb.gimp_layer_group_new (img) group.name = "my group"

How do I show or hide a layer in GIMP?

Each individual layer in GIMP has a show/hide icon that allows you to show or hide that layer. The same applies to layer groups, though clicking the show/hide icon for a layer group (red arrow) will hide all of the layers in that layer group (outlined in green).

How do I duplicate a layer group?

Duplicate a Layer Group You can duplicate a layer group: click on the Create a duplicate of the layerbutton or right-click and select the Duplicate Layercommand in the pop up context menu. Move Layer Groups

What are nested layer groups in GIMP?

Layer groups in GIMP add a ton of functionality to your compositions, allowing you to create complex effects – especially when combined with layer masks and layer group masks. Nested layer groups further expand these capabilities, opening up GIMP to a world of potential for photo editing and photo manipulation.


2 Answers

GIMP Python went mostly unmaintained over this development cycle (you can blame much of that on myself).

One of the few updates done was the creation of the "Item" class - and the implementation of a class method on it that allows one to use the numeric ID returned by the PDB methods to retreive an item.

So, you can use, like you found out pdb.gimp_item_get_children(group_layer), and on the returned ID for the children use gimp.Item.from_id to retrieve the actual layer.

Here is a GIMP console section where I retrieve a sublayer "by hand":

>>> img = gimp.image_list()[0]
>>> c = img.layers[0]
>>> c
<gimp.Layer 'Layer Group'>
>>> pdb.gimp_item_get_children(c)
(1, (4,))
>>> c2 = gimp.Item.from_id(4)
>>> c2
<gimp.Layer 'cam2'>
>>> 

** update **

I spent some hacking hours, and GIMP 2.8 final will come with proper support for Layer Groups - you will need the hack above up to gimp 2.8 RC 1, but if you build the project from git master right now, layer groups show as instances of "GroupLayer", and feature a "layers" attribute which works just like the "layers" attribute in an image.

commit 75242a03e45ce751656384480e747ca30d728206

 Date:   Fri Apr 20 04:49:16 2012 -0300

     pygimp: adds proper support for layer groups

     Layer groups where barely supported using numeric IDs and
     by calling gimp.Item.from_id. This adds a Python
     GroupLayer class.
like image 136
jsbueno Avatar answered Sep 21 '22 15:09

jsbueno


Thanks for the breakdown, I was struggling with the same issue as I am in the process of updating my plug-ins from 2.6 to 2.7~2.8. Here is the edited function:

def find_layer_by_name (image, name):
for layer in image.layers:
    #check if layer is a group and drill down if it is
    if pdb.gimp_item_is_group(layer):
        gr = layer
        gr_items = pdb.gimp_item_get_children(layer)
        for index in gr_items[1]:
            item = gimp.Item.from_id(index)
            if item.name == name:
                return item

    # if layer is on the first level     
    if layer.name == name:
        return layer
        return None
like image 42
Andrei Avatar answered Sep 24 '22 15:09

Andrei