It is currently Fri May 24, 2013 5:17 am


Latest GIMP Scripts & Plug-ins

All times are UTC - 5 hours [ DST ]




Post new topic Reply to topic  [ 7 posts ] 
Author Message
 Post subject: Request for help with Gimp Scripting nuts and bolts..
PostPosted: Wed Jul 18, 2012 11:55 pm  (#1) 
Offline
GimpChat Member

Joined: Jun 22, 2012
Posts: 107
Sorry up front if this is a rambling post, I have quite a few questions and this was the best way I could think of framing them in one post. Here's a little PythonFu Console session with questions highlighted..

(If any of the experts could take the time to plough through this it would be much appreciated. I reckon it will be instructive to other scripting noobs too, as there's some fundamental stuff here)


GIMP 2.6.11 Python Console
Python 2.6.6 (r266:84297, Aug 24 2010, 18:46:32) [MSC v.1500 32 bit (Intel)]

>>> #I want to create and display a new image..
>>> img = gimp.Image(100,100,RGB)
>>> gimp.Display(img)
<display>
>>> #Ok that worked, I wonder what that display object that's been returned really is? I'll worry about that later. I want to get a few details of my image..
>>> img.ID
1
>>> img.name
'Untitled'
>>> #I wonder how Gimp assigns IDs to objects? Nevermind that for now, that ID will come in handy when Gimp throws error messages and quotes object IDs at me. I'm not happy with the name, I'll change it..
>>> img.name = "First.xcf"
Traceback (most recent call last):
File "<input>", line 1, in <module>
AttributeError: attribute 'name' of 'gimp.Image' objects is not writable

>>> #Oops why didn't that work? (It does on layers) I wonder what method I use to assign a name to an image file then? I'll add another image so I've got something to play with, then review the images I've got..
>>> img2 = gimp.Image(100,100,RGB)
>>> gimp.image_list()
[<gimp.Image 'Untitled'>, <gimp.Image 'Untitled'>]
>>> #OK now that's a bit confusing, I now have two "Untitled" images. I'll pop into Gimp and save the first image I created under a new name (I wonder how I'd do that in script?). Oops Gimp won't let me save it, most likely as there's nothing in the image! I'll fix that and add a layer..
>>> eggLayer = gimp.Layer(img,"Egg",100,100,RGB_IMAGE,100,NORMAL_MODE)
>>> img.add_layer(eggLayer,0)
>>> #That worked OK and I've saved the image as "Original.xcf", I'll update my images list..
>>> gimp.image_list()
[<gimp.Image 'Untitled'>, <gimp.Image 'Original.xcf'>]
>>> #That's curious, the first image I created appears at the end of the list. I wonder why? Oh well as long as I'm aware of it I can work with it. Now I'll make another layer to play with by copying the first layer I made it and adding it to the Original Image..
>>> brickLayer = eggLayer.copy()
>>> img.add_layer(brickLayer,0)
>>> #Ok that worked and Gimp kindly renamed it to "Egg Copy". For fun I'll add it again..
>>> img.add_layer(brickLayer,0)
Traceback (most recent call last):
File "<input>", line 1, in <module>
error: could not add layer (ID 5) to image (ID 1)

>>> #Oh dear. I wonder why that didn't work? It looks like my brickLayer is somehow bound to the one in the image. Question is what did I actually create with the command "brickLayer = eggLayer.copy()"? I'll try a trick..
>>> brickLayer.ID
5
>>> brickLayer = brickLayer.copy()
>>> brickLayer.ID
6
>>> img.add_layer(brickLayer,0)
>>> #Not sure how but that worked. Gimp has created a third layer and called it "Egg copy#1". I wonder what really went on there? I'll try and copy one of my Egg layers to the second Image I created..
>>> spamLayer = eggLayer.copy()
>>> img2.add_layer(spamLayer,0)
Traceback (most recent call last):
File "<input>", line 1, in <module>
error: could not add layer (ID 7) to image (ID 2)

>>> #Well that went horribly wrong. Had a message from Gimp saying "Calling error for procedure 'gimp-image-add-layer':
>>> #Trying to add item 'Egg copy' (7) to wrong image" as well as the console error. What does that message mean? Is my new Spam object somehow bound to the Original Image? How do I copy layers between images then? Using some sort of copy/paste method would probably be slow and generally seems a bit lame.

>>> #
>>> #I'll try the trick I used earlier..
>>> spamLayer.ID
7
>>> spamLayer = spamLayer.copy()
>>> spamLayer.ID
8
>>> img2.add_layer(spamLayer,0)
Traceback (most recent call last):
File "<input>", line 1, in <module>

error: could not add layer (ID 8) to image (ID 2)
>>> #Nope that doesn't work either :(


Share on Facebook Share on Twitter Share on Orkut Share on Digg Share on MySpace Share on Delicious Share on Technorati
Top
 Profile  
 

 Post subject: Re: Request for help with Gimp Scripting nuts and bolts..
PostPosted: Thu Jul 19, 2012 1:07 am  (#2) 
Offline
GimpChat Member
User avatar

Joined: Apr 23, 2010
Posts: 820
Location: not from Guildford after all
step7 wrote:
>>> gimp.Display(img)
<display>
>>> #Ok that worked, I wonder what that display object that's been returned really is? I'll worry about that later. I want to get a few details of my image..

Any image can have more than one display showing at a time. For example, one display might be actual size while another is zoomed in. Plug-ins generally do not need to worry about more than one display (and sometimes not even that).

step7 wrote:
>>> img.ID
1
>>> img.name
'Untitled'
>>> #I wonder how Gimp assigns IDs to objects?

Image IDs start at "1" and increase sequentially during each GIMP session. GIMP refers to all images, drawables, and paths by their ID. GIMP does not assign IDs to the Python objects (this is done by Python Fu); all Python objects are handled by Python Fu.
step7 wrote:
>>> img.name = "First.xcf"
Traceback (most recent call last):
File "<input>", line 1, in <module>
AttributeError: attribute 'name' of 'gimp.Image' objects is not writable

>>> [i]#Oops why didn't that work? (It does on layers)

Welcome to the joys of learning the inconsistencies of Python Fu. It won't be the last time you encounter such enigmas (e.g., why are the names of object methods like 'gimp.Layer' nouns?).

step7 wrote:
I wonder what method I use to assign a name to an image file then?

Try 'pdb.gimp_image_set_filename(img, "First.xcf")


step7 wrote:
Now I'll make another layer to play with by copying the first layer I made it and adding it to the Original Image..
>>> brickLayer = eggLayer.copy()
>>> img.add_layer(brickLayer,0)
>>> #Ok that worked and Gimp kindly renamed it to "Egg Copy". For fun I'll add it again..
>>> img.add_layer(brickLayer,0)
Traceback (most recent call last):
File "<input>", line 1, in <module>
error: could not add layer (ID 5) to image (ID 1)

>>> #Oh dear. I wonder why that didn't work?

You've only created one layer ("Egg copy"). After you've added it to the image, it is not possible (nor is it necessary) to add it again.

step7 wrote:
It looks like my brickLayer is somehow bound to the one in the image. Question is what did I actually create with the command "brickLayer = eggLayer.copy()"? I'll try a trick..
>>> brickLayer.ID
5
>>> brickLayer = brickLayer.copy()
>>> brickLayer.ID
6
>>> img.add_layer(brickLayer,0)
>>> #Not sure how but that worked. Gimp has created a third layer and called it "Egg copy#1". I wonder what really went on there?

You created a third layer, which you were then able to add to the image. You then created a fourth layer, which you were then able to add to the image.


The creation of a layer is a separate operation from adding the layer to the image. I would guess that this was originally done so that the layer could be filled with some color or transparency before it appears on the screen, otherwise the user might see a flash of garbage graphics while the layer was being initialized. (In fact, about the only thing you can do to a layer before it has been added to an image is to use 'gimp-drawable-fill', change its name, or change its offsets.)

step7 wrote:
I'll try and copy one of my Egg layers to the second Image I created..
>>> spamLayer = eggLayer.copy()
>>> img2.add_layer(spamLayer,0)
Traceback (most recent call last):
File "<input>", line 1, in <module>
error: could not add layer (ID 7) to image (ID 2)

>>> #Well that went horribly wrong. Had a message from Gimp saying "Calling error for procedure 'gimp-image-add-layer':
>>> #Trying to add item 'Egg copy' (7) to wrong image" as well as the console error. What does that message mean? Is my new Spam object somehow bound to the Original Image? How do I copy layers between images then? Using some sort of copy/paste method would probably be slow and generally seems a bit lame.

'gimp-layer-copy' can only be used to copy layers to the same image. If you want to copy a layer to another image then use 'gimp-layer-new-from-drawable' (in Python, 'pdb.gimp_layer_new_from_drawable' or somesuch).

_________________
Any sufficiently primitive technology is indistinguishable from a rock.


Top
 Profile  
 
 Post subject: Re: Request for help with Gimp Scripting nuts and bolts..
PostPosted: Thu Jul 19, 2012 3:19 am  (#3) 
Offline
GimpChat Member

Joined: Jun 22, 2012
Posts: 107
Thanks for taking the time to enlighten me! Things are a little clearer now, I'll have to have another play in the console :)

Just to pick up on a few of your points..
Quote:
Any image can have more than one display showing at a time. For example, one display might be actual size while another is zoomed in. Plug-ins generally do not need to worry about more than one display (and sometimes not even that).

I understood that, I know I could have opened several display windows:
gimp.Display(img)
gimp.Display(img)
gimp.Display(img)


My question was specifically about the object I was getting back. What is it? An instance of the Class "Gimp.Display"? Same when a Layer or an Image is returned from a function to my code - what am I actually dealing with?

Quote:
why are the names of object methods like 'gimp.Layer' nouns?

This and the fact that some methods are spelled like this "gimp.image_list()" really puzzled me (and led to some annoyance on the consistency front). I'm too new to Python to be sure but I think the inconsistencies can be explained like this (experienced Pythoneers put me straight please!).
"Layer" is a class (hence the noun). To create an instance of that class you just refer to it:
eggLayer = gimp.Layer(img,"Egg",100,100,RGB_IMAGE,100,NORMAL_MODE)

This is inconsistent, where's the verb to say we're instantiating? This inconsistency would be in Python rather than PythonFu though.
I'm used to seeing constructs like this:
eggLayer = new gimp.Layer(img,"Egg",100,100,RGB_IMAGE,100,NORMAL_MODE)

or..
eggLayer = gimp.Layer.instantiate(img,"Egg",100,100,RGB_IMAGE,100,NORMAL_MODE)

"Explicit is better than implicit" : The Zen Of Python [PEP20] :lol

This all ties in with my first question, hopefully when Amazon deliver the books I've ordered the answers will present themselves :)

Quote:
You've only created one layer ("Egg copy"). After you've added it to the image, it is not possible (nor is it necessary) to add it again.
You created a third layer, which you were then able to add to the image. You then created a fourth layer, which you were then able to add to the image.

Doh. I should have realised this when I printed the ID after making a copy of my layer. It's nonsensical to try and add another layer with same ID :roll:

Quote:
The creation of a layer is a separate operation from adding the layer to the image. I would guess that this was originally done so that the layer could be filled with some color or transparency before it appears on the screen, otherwise the user might see a flash of garbage graphics while the layer was being initialized. (In fact, about the only thing you can do to a layer before it has been added to an image is to use 'gimp-drawable-fill', change its name, or change its offsets.)

I think historically you could operate on a Layer without adding it to an image but that facility was removed. I can't see why - but I'm sure there must have been a good reason - I'll have to go read up.

Quote:
'gimp-layer-copy' can only be used to copy layers to the same image. If you want to copy a layer to another image then use 'gimp-layer-new-from-drawable' (in Python, 'pdb.gimp_layer_new_from_drawable' or somesuch).

Thanks, that would have taken me an age to find as I was stuck on "copy layer" rather than thinking "new layer from" :clap
I wonder if "Layer" has an in built method to do this? My instinct is telling me to avoid accessing the PDB where I can as it's probably going to be slower and I don't know how robust the PDB-PyFu interface is really is. I don't know if this thinking is flawed and being new to Python I'll admit I'm over conscious of data types.

Thanks again for taking the time to respond, it's good to be able to discuss these things as the lack of accurate/current documentation is driving me nuts!


Top
 Profile  
 
 Post subject: Re: Request for help with Gimp Scripting nuts and bolts..
PostPosted: Thu Jul 19, 2012 4:36 am  (#4) 
Offline
GimpChat Member
User avatar

Joined: Oct 25, 2010
Posts: 1301
step7 wrote:
Thanks again for taking the time to respond, it's good to be able to discuss these things as the lack of accurate/current documentation is driving me nuts!

Using PDB functions or object methods is completely equivalent, object methods are just wrappers over the PDB. But there are often shorter to type and more readable.

The official python-fu docs are a bit outdated, if you use dir() on the various objects you'll see undocumented methods, but you'll have no trouble mapping them to the equivalent PDB functions and finding how to use them.

_________________
Image


Top
 Profile  
 
 Post subject: Re: Request for help with Gimp Scripting nuts and bolts..
PostPosted: Thu Jul 19, 2012 5:07 am  (#5) 
Offline
GimpChat Member

Joined: Jun 22, 2012
Posts: 107
Quote:
Using PDB functions or object methods is completely equivalent, object methods are just wrappers over the PDB. But there are often shorter to type and more readable.

That's interesting. I'd got it in to my head I was bypassing the PDB and accessing the Gimp application core directly by using object methods :oops:. I got into this thinking because objects appear to be part of the Gimp class (e.g. gimp.Image) not some PythonFu class, but I guess the Gimp here relates to Gimp.pyd not the Gimp application. So to be clear you're telling me it's the other way around, I'm actually a little further away from the core as the methods are executed via some wrapper code that just accesses the PDB for me? (So methods will be a little slower but more likely to ensure argument/return data are good for PythonFu?)

Quote:
The official python-fu docs are a bit outdated, if you use dir() on the various objects you'll see undocumented methods, but you'll have no trouble mapping them to the equivalent PDB functions and finding how to use them.

I've been using dir() to gently probe around as I'm trying to find my way. Now you've told me there are undocumented methods which PDB functions effectively document I'll probe a little deeper ;) Great tip - Thanks!


Top
 Profile  
 
 Post subject: Re: Request for help with Gimp Scripting nuts and bolts..
PostPosted: Thu Jul 19, 2012 9:07 am  (#6) 
Offline
GimpChat Member
User avatar

Joined: Apr 23, 2010
Posts: 820
Location: not from Guildford after all
step7 wrote:
Quote:
Using PDB functions or object methods is completely equivalent, object methods are just wrappers over the PDB. But there are often shorter to type and more readable.

That's interesting. I'd got it in to my head I was bypassing the PDB and accessing the Gimp application core directly by using object methods :oops:. I got into this thinking because objects appear to be part of the Gimp class (e.g. gimp.Image) not some PythonFu class, but I guess the Gimp here relates to Gimp.pyd not the Gimp application. So to be clear you're telling me it's the other way around, I'm actually a little further away from the core as the methods are executed via some wrapper code that just accesses the PDB for me? (So methods will be a little slower but more likely to ensure argument/return data are good for PythonFu?)

The bulk of what you say here is true; however, plug-ins never access the GIMP application core directly. They either go through the PDB or through libgimp. More precisely (to my understanding), plug-ins always access GIMP core functionality through libgimp, with some of the libgimp functionality invoking PDB procedures. The only time a plug-in will invoke PDB procedures directly is for user-registered (non-GIMP core) procedures.

    Example 1: a plug-in creating a new layer would call the libgimp function 'gimp_layer_new'; this libgimp function would invoke the PDB procedure 'gimp-layer-new'.

    Example 2: a plug-in working with pixel regions would employ libgimp's pixel region API; the Procedural DataBase is not involved.

    Example 3: a plug-in invoking another plug-in would interface to it through the PDB directly (except when a Python Fu plug-in invokes another Python Fu plug-in, in which case the PDB is bypassed).

Python Fu's 'gimp' object is not directly correlated to either libgimp or the PDB; it is the top-level Python class that encapsulates them both (the Python Fu 'pdb' object is actually just a shorthand notation for the 'gimp.pdb' object). The 'gimp' object is implemented through bindings to 'libgimp', but also includes some objects and methods written solely in Python (but still related to GIMP).

For the most part, you won't need to worry about any of this, but since you expressed interest... (and since you seem smarter than the average bear) -- an understanding of what is happening under-the-hood might help in addressing some of the inconsistencies you are likely to encounter.

step7 wrote:
I've been using dir() to gently probe around as I'm trying to find my way. Now you've told me there are undocumented methods which PDB functions effectively document I'll probe a little deeper ;) Great tip - Thanks!

help(someobj) will also provide detailed information about Python Fu objects.

_________________
Any sufficiently primitive technology is indistinguishable from a rock.


Top
 Profile  
 
 Post subject: Re: Request for help with Gimp Scripting nuts and bolts..
PostPosted: Thu Jul 19, 2012 2:58 pm  (#7) 
Offline
GimpChat Member

Joined: Jun 22, 2012
Posts: 107
Some good info thanks! Cheers for the link to http://developer.gimp.org, I'll spend some time there:)


Top
 Profile  
 

Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 7 posts ] 

All times are UTC - 5 hours [ DST ]


Who is online

Users browsing this forum: No registered users and 4 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  

* Login   * Subscribe to RSS Feed


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group