Post Reply 

Python-Fu script to change only selected area

Mar 6, 2011, 21:03
Post: #1
Python-Fu script to change only selected area
Hello,

I'm struggling here to climb the learning curve in GIMP scripting. The Script-Fu syntax seems just crazy, so I immediately opted for Python. Got the basics of plug-in registration working, so now it's time to make something actually useful.

I have to admit that there are almost no decent tutorials on this topic. Perhaps that means that it's time to make one. When I master something, that is.

I have successfully written a script that reads pixel values and performs some transformation. But it is applied on the active layer, regardless what is the selected area. What I am now looking for, is how to apply the effect only to the selected area in the active layer, so pretty standard stuff. And, perhaps a fallback routine - apply to the active layer, when there is no selection. Could someone suggest either good online reading resource to learn some ropes, or perhaps paste a code here in forum?


Attached File(s)
.gz  test.py.gz (Size: 480 bytes / Downloads: 125)
Find all posts by this user
Quote this message in a reply
Mar 6, 2011, 21:25 (This post was last modified: Mar 6, 2011 21:34 by ofnuts.)
Post: #2
RE: Python-Fu script to change only selected area
Script-fu is Scheme, a Listp derivative. Crazy synatx but great power with little CPU.

If you read the small print, set_pixel() works directly in the drawable and ignores the selection (it also cannot be undone, if you write on an existing drawable) . If you want to know if a pixel is selected, the image object has a selection (image.selection in the Gimp API, otherwise pdb.gimp_image_get_selection()). This selection is a channel where each pixel has a single value, 0 for unselected pixels, and 255 for the fully selected ones. The snag is that feathered selections produce intermediate values and that you would have to handle that properly.

So, I would render the pixels in a new layer, and when done use the selection to copy the contents of that layer and paste them over the target layer (or in a empty layer).
You can restrict your pixels generation to pixels that are likely to be part of the selection by checking their coordinates against the selection bounding box obtained by pdb.gimp_selection_bounds(image)

Now answering your questions on
https://Gimp-Forum.net
Visit this user's website Find all posts by this user
Quote this message in a reply
Apr 22, 2011, 22:42
Post: #3
RE: Python-Fu script to change only selected area
Thanks for the advice. It was quite a while ago I asked this, and now I've got back to tinkering with Gimp scripting.

This is how far I've got with my experimental plugin. It now respects the selection and it's alpha channel. But I don't know how to merge that dynamically created layer to the base image. At least it seems to be the good style that typical plugin affects the active layer.
I also don't understand should I use those img.disable_undo() and img.enable_undo()? My script works without those just fine. Or perhaps I should use those related to undo groups? I have no idea what's the difference and generally suggested practice.

I think I'd be not asking here some very specific dumb questions, if I could find any decent reference online. I really tried to find some, but failed. Or perhaps I don't know how to search for it? I mean something like API documentation, where all the objects and their methods are described.

PHP Code:
from gimpfu import *
import random

def col
(xya) :
    
= (random.randint(0,(x+y)%50+200), random.randint(0,(x+y)%50+200), random.randint(0,(x+y)%50+200), a)
    return 
c

def randompix
(imglayer) :
    
# Fill the selection with random-color pixels

    # Now: spoils the main layerm not undoable.
    # Next todo: create new layer, render the effect on that, then merge to main layer, respecting the selection. Limit the processing
    # to the selection bounding box only

    
    
is_selectionx1y1x2y2 pdb.gimp_selection_bounds(img)
    if 
is_selection:
        
sel img.selection
    
else:
        
x1 0
        y1 
0
        x2 
img.width
        y2 
img.height

    
#pdb.gimp_message(str(x1) + "; " + str(y1) + "; " + str(x2) + "; " + str(y2) + "; " + ("yes" if is_selection else "no"))

    
drawLayer gimp.Layer(img"tempLayer_1"img.widthimg.heightRGBA_IMAGE100NORMAL_MODE)
    
img.add_layer(drawLayer0)
    
    
random.seed()
    for 
y in range(y1y2):
        for 
x in range(x1x2):
            
pdb.gimp_drawable_get_pixel(selxy)[1][0] if is_selection else 255
            
if 0:
                
pdb.gimp_drawable_set_pixel(drawLayerxy4col(xys))
    
pdb.gimp_drawable_update(drawLayer,,img.widthimg.height)
    
gimp.image_merge_down(

    return 
Find all posts by this user
Quote this message in a reply
Apr 23, 2011, 16:20
Post: #4
RE: Python-Fu script to change only selected area
You don't merge a layer to the image. You merge it in another layer... Typically you would position you new layer just above the layer you are supposed to transform (the current layer, usually) and when done merge down you new layer in that current layer.

Undo: the most important is undo_group start/end, that make your whole script undoable with one "undo" from a user stand point. Undo disable/enable can also be used when thing you are doing are of little interest (typically acting on temporary objects, such as your layer).

API: yes, it's a bit of a pain. The best place is really the procedure browser: Filters>Python-fu>Console and then "Browse". Enter partial names at the top. "Apply" will put a sample call in the console, so you can copy/paste it to your code. These are all the "pdb" calls. Thttp://www.gimp.org/docs/python/index.html also documents classes and methods that can be much easier to call directly. Use and abuse the dir(object) python method, you 'll discover things, the doc is not complete and there are good surprises. Of course these bonus APIs aren't much documented but they usually parallel like-named APIs in the PDB.

Now answering your questions on
https://Gimp-Forum.net
Visit this user's website Find all posts by this user
Quote this message in a reply
Apr 23, 2011, 22:47
Post: #5
RE: Python-Fu script to change only selected area
(Apr 23, 2011 16:20)ofnuts Wrote:  You don't merge a layer to the image. You merge it in another layer... Typically you would position you new layer just above the layer you are supposed to transform (the current layer, usually) and when done merge down you new layer in that current layer.

The only command I see there in te procedure browser is this:
pdb.gimp_image_merge_down(image, merge_layer, merge_type)
The description says that the layer will be merged to the next visible layer below. However, in some of the plugin scripts what I have downloaded from the plugin registry, I see this prodedure call: imageObj.merge_down(layerObj, 0)
Such merge_down method is not found in the procedure browser at all, so I assume this is one of those undocumented "surprise" methods. But anyway, I still don't know of any method that lets you merge layer A down to layer B, instead of just "to the next layer below", what fells like it might cause some harm, when I try to act on other than topmost layer.

Thanks for explaining about the undo control methods. I now implemented img.undo_group_start() and img.undo_group_end(). However, I read that for more complex operations it is wiser to create a new image object, disable undo on it, do all the operations, paste the result back to the active image, and discard the dynamically created image.

Regarding the API: how about establishing some community-supported wiki for this? At least plain list of modules, objects and method signatures would be a good start. While I can browse the procedure browser, it still is very clear that there are many aliases for most of the "pdb" methods, at least some of them are available as methods of the respective objects (as seen in http://www.gimp.org/docs/python/index.html, but that hardly feels like exhaustive list). Of course, performing dir() on those objects sheds some little light, but man, this is pretty wild way to explore the terrain indeed.
Find all posts by this user
Quote this message in a reply
Apr 24, 2011, 07:25
Post: #6
RE: Python-Fu script to change only selected area
(Apr 23, 2011 22:47)Passiday Wrote:  The only command I see there in te procedure browser is this:
pdb.gimp_image_merge_down(image, merge_layer, merge_type)
The description says that the layer will be merged to the next visible layer below. However, in some of the plugin scripts what I have downloaded from the plugin registry, I see this prodedure call: imageObj.merge_down(layerObj, 0)
Such merge_down method is not found in the procedure browser at all, so I assume this is one of those undocumented "surprise" methods. But anyway, I still don't know of any method that lets you merge layer A down to layer B, instead of just "to the next layer below", what fells like it might cause some harm, when I try to act on other than topmost layer.
Yes, pdb.gimp_image_merge_down(image, merge_layer, merge_type) and imageObj.merge_down(layerObj, 0) (where '0' is limely some NORMAL_MODE) are very likely the same thing). You don' t merge a layer on another random layer, it's normally on the layer below, like in the human interface. However you can position your layer, either at creation (an argument is the position of the layer) or afterwards (image.raise_layer(layer),or image.lower_layer()). I don't see call to obtain directly the position of some given mayer, but I guess that iterating the list could also do the job. Also, I never ventured in that neck of the API forest, but I see documented an image.merge_visible_layers(type) where you see a image.merge_down(layer, type)....

(Apr 23, 2011 22:47)Passiday Wrote:  Regarding the API: how about establishing some community-supported wiki for this? At least plain list of modules, objects and method signatures would be a good start. While I can browse the procedure browser, it still is very clear that there are many aliases for most of the "pdb" methods, at least some of them are available as methods of the respective objects (as seen in http://www.gimp.org/docs/python/index.html, but that hardly feels like exhaustive list). Of course, performing dir() on those objects sheds some little light, but man, this is pretty wild way to explore the terrain indeed.
A wiki would be overdoing it a bit. This isn't completely uncharted territory, all these calls come from some source code, its only that the authors found it more fun to update the code than to update the docs.

Now answering your questions on
https://Gimp-Forum.net
Visit this user's website Find all posts by this user
Quote this message in a reply
Apr 24, 2011, 07:41
Post: #7
RE: Python-Fu script to change only selected area
PS: just had a look at the source code for the interface... finding the existing methods is quite easy. There are indeed two variants for the merge: merge_down and merge_visible.

Now answering your questions on
https://Gimp-Forum.net
Visit this user's website Find all posts by this user
Quote this message in a reply
Apr 24, 2011, 09:58
Post: #8
RE: Python-Fu script to change only selected area
(Apr 24, 2011 07:41)ofnuts Wrote:  PS: just had a look at the source code for the interface... finding the existing methods is quite easy. There are indeed two variants for the merge: merge_down and merge_visible.

Where in the source files you would look for the Python objects interface? Do you mean the /usr/lib/gimp/2.0/python/gimpfu.py and related modules?

I could not agree that wiki would be overkill. I mean, look at the present state of documentation available online, that's ridiculous. And that's completely understood that coders enjoy adding another useful feature rather than writing docs. But that's what community is for. If the Gimp scripting would be more documented, we could definitely see wider adoption of Gimp, as community would embrace the expansion possibilities.
Find all posts by this user
Quote this message in a reply
Apr 24, 2011, 11:11
Post: #9
RE: Python-Fu script to change only selected area
(Apr 24, 2011 09:58)Passiday Wrote:  
(Apr 24, 2011 07:41)ofnuts Wrote:  PS: just had a look at the source code for the interface... finding the existing methods is quite easy. There are indeed two variants for the merge: merge_down and merge_visible.

Where in the source files you would look for the Python objects interface? Do you mean the /usr/lib/gimp/2.0/python/gimpfu.py and related modules?
No, this isn't the source code. The source for this stuff is in the plug-ins/pygimp/pygimp-*.c files in the source code tarbal. For instance in pygimp-drawable.c you will find:
Code:
static PyMethodDef lay_methods[] = {
    {"copy",    (PyCFunction)lay_copy,  METH_VARARGS | METH_KEYWORDS},
    {"add_alpha",       (PyCFunction)lay_add_alpha,     METH_NOARGS},
    {"add_mask",        (PyCFunction)lay_add_mask,      METH_VARARGS},
    {"create_mask",     (PyCFunction)lay_create_mask,   METH_VARARGS},
    {"remove_mask",     (PyCFunction)lay_remove_mask,   METH_VARARGS},
    {"resize",  (PyCFunction)lay_resize,        METH_VARARGS | METH_KEYWORDS},
    {"resize_to_image_size",    (PyCFunction)lay_resize_to_image_size,  METH_NOARGS},
    {"scale",   (PyCFunction)lay_scale, METH_VARARGS | METH_KEYWORDS},
    {"translate",       (PyCFunction)lay_translate,     METH_VARARGS | METH_KEYWORDS},
    {"set_offsets",     (PyCFunction)lay_set_offsets,   METH_VARARGS | METH_KEYWORDS},
    {NULL,              NULL}           /* sentinel */
};
that looks strangely like the known methods for the "Layer" class in the python interface.

(Apr 24, 2011 09:58)Passiday Wrote:  I could not agree that wiki would be overkill. I mean, look at the present state of documentation available online, that's ridiculous. And that's completely understood that coders enjoy adding another useful feature rather than writing docs. But that's what community is for. If the Gimp scripting would be more documented, we could definitely see wider adoption of Gimp, as community would embrace the expansion possibilities.
The python stuff is comparatively much better documented than the C one. By the way the Gimp gang has started a wiki. Subscribe to the gimp-developer mailing list for details.

Now answering your questions on
https://Gimp-Forum.net
Visit this user's website Find all posts by this user
Quote this message in a reply
Post Reply 


Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Request for script chlebna 1 171 Sep 13, 2017 09:35
Last Post: ythgilb
  Request for script - Guillotine + Watermark sunslick 1 229 Sep 4, 2017 08:51
Last Post: ythgilb
  Script-fu: How to create new, addressable layer using gimp-floating-sel-to-layer Bertholom√§us 2 230 Aug 31, 2017 14:32
Last Post: Bertholomäus
  How to modify this script-fu? Zakary81 1 195 Aug 23, 2017 12:48
Last Post: paynekj
  Loading PythonFu Plugin: ImportError for .../python/gimp.so (GIMP 2.8.22/OSX/Py2.7.9) joroek 1 315 Jul 11, 2017 07:26
Last Post: ythgilb

Forum Jump:


GIMP ForumPortalArchiveContactTermsRSS