Switch to full style
Post all Gimp scripts and script writing questions here
Post a reply

Python plug-in works great on my machine, seems to crash others

Tue Aug 14, 2018 11:07 pm

So, I wrote this script for my girlfriend, and it works like gangbusters on my GIMP.... Doesn't take more than several seconds even with an image that's up to like 2 gigs through repeated use.

But it seems to stop responding on hers, same version and everything.

Can someone help me figure out what's causing that?

Here's the code.

Code:
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from gimpfu import *

def celenicorn_auto_mirror(image, drawable, direction = 0) :
    width = image.width
    height = image.height
    pdb.gimp_selection_all(image)
    pdb.gimp_edit_copy_visible(image)

    def process(vhflip, sizex, sizey, ofsx, ofsy, movx, movy):
        pdb.gimp_image_resize(image, sizex, sizey, ofsx, ofsy)
        newLayer = pdb.gimp_drawable_transform_flip_simple(pdb.gimp_edit_paste(drawable, False), vhflip, True, 0, False)
        pdb.gimp_selection_none(image)
        pdb.gimp_layer_resize_to_image_size(drawable)
        pdb.gimp_layer_set_offsets(newLayer, movx, movy)
        pdb.gimp_floating_sel_anchor(newLayer)

    def up():
        process(1, width, height * 2, 0, height, 0, 0)

    def down():
        process(1, width, height * 2, 0, 0, 0, height)

    def left():
        process(0, width * 2, height, width, 0, 0, 0)
   
    def right():
        process(0, width * 2, height, 0, 0, width, 0)

    switcher = {
        0: up,
        1: down,
        2: left,
        3: right
    }
    func = switcher.get(direction, lambda:"Invalid Direction")
    func()
   
register(
        "celenicorn_auto_mirror",
        "Mirror the image in a specific direction.",
        "Mirror the image in a specific direction.",
        "Arlo Horner",
        "Arlo Horner",
        "2018",
        "<Image>/Celenicorn/Cosmic Auto Mirror",
        "",
        [
                (PF_RADIO, "direction", "Mirror towards which direction: ", 0,
                (
                 ("Up", 0),
                 ("Down", 1),
                 ("Left", 2),
                 ("Right", 3)
                )
                )
        ],
        [],
        celenicorn_auto_mirror)
main()

Re: Python plug-in works great on my machine, seems to crash others

Tue Aug 14, 2018 11:49 pm

I saved as 'celenicorn_auto_mirror.py' made executable and dropped into plugins on Gimp 2.10.
Found it on top menu under "Celenicorn' > cosmic_auto_mirror.
Yes it works quite well. It resizes after applying both horizontally and vertically.
Looks like the scripting is good.
What system is your girlfriend using? Maybe underpowered?

Re: Python plug-in works great on my machine, seems to crash others

Wed Aug 15, 2018 7:14 am

On my Linux this crashes Gimp about every other execution. One of the problem can be that you are using the clipboard more than necessary. For what you do you can just duplicate the layer, flip it, move it, and then merge down. Operations with the clipboard also impact other processes, which can be slow to react.

Also, you should bracket your code with undo_group_start()/undo_group_end() so that only one undo operation is necessary.

Re: Python plug-in works great on my machine, seems to crash others

Wed Aug 15, 2018 2:15 pm

ofnuts wrote:On my Linux this crashes Gimp about every other execution. One of the problem can be that you are using the clipboard more than necessary. For what you do you can just duplicate the layer, flip it, move it, and then merge down. Operations with the clipboard also impact other processes, which can be slow to react.

Also, you should bracket your code with undo_group_start()/undo_group_end() so that only one undo operation is necessary.


OK, it seems better to me doing it that way. Is there anything else I can do to improve it?

Code:
def celenicorn_auto_mirror(image, drawable, direction = 0) :
    width = image.width
    height = image.height
    image.undo_group_start()
    newLayer = drawable.copy()
    image.add_layer(newLayer, 0)

    def process(vhflip, sizex, sizey, ofsx, ofsy, movx, movy):
        pdb.gimp_image_resize(image, sizex, sizey, ofsx, ofsy)
        pdb.gimp_drawable_transform_flip_simple(newLayer, vhflip, True, 0, False)
        pdb.gimp_layer_set_offsets(newLayer, movx, movy)
        image.flatten()

    def up():
        process(1, width, height * 2, 0, height, 0, 0)

    def down():
        process(1, width, height * 2, 0, 0, 0, height)

    def left():
        process(0, width * 2, height, width, 0, 0, 0)
   
    def right():
        process(0, width * 2, height, 0, 0, width, 0)

    switcher = {
        0: up,
        1: down,
        2: left,
        3: right
    }
    func = switcher.get(direction, lambda:"Invalid Direction")
    func()
    image.undo_group_end()


In particular, is it better to replace most of the pdb methods with image and layer methods, like so?

Code:
        image.resize(sizex, sizey, ofsx, ofsy)
        pdb.gimp_drawable_transform_flip_simple(newLayer, vhflip, True, 0, False)
        newLayer.set_offsets(movx, movy)
        image.flatten()

Re: Python plug-in works great on my machine, seems to crash others

Wed Aug 15, 2018 4:11 pm

Yes, works fine for me. I find using the object methods makes for more readable code than the pdb functions.

Gimp-wise, a latent problem with your script it that although it takes a layer as a parameter, it makes several assumptions:

1) the layer is the only one in the image (image.flatten() would destroy all other layers)
2) the layer is the size of the canvas and has a (0,0) offset.

Fine if it's for you or a specific person, but if you make it public it will come back to haunt you :)

There is another problem, it doesn't seem to be re-runnable (Filters>Repeat|Reshow last used). Some of my scripts are like that too, and I never figured out what the problem was.

Pythonically, like you I don't like if's and even more long sequences of if/elif/else but your code can be simplified to:

Code:
def celenicorn_auto_mirror(image, drawable, direction = 0) :
    image.undo_group_start()
    width = image.width
    height = image.height
    newLayer = drawable.copy()
    image.add_layer(newLayer, 0)

    dirParms={
        0: (1, width, height * 2, 0, height, 0, 0),
        1: (1, width, height * 2, 0, 0, 0, height),
        2: (0, width * 2, height, width, 0, 0, 0),
        3: (0, width * 2, height, 0, 0, width, 0)
        }

    vhflip, sizex, sizey, ofsx, ofsy, movx, movy=dirParms[direction]
    pdb.gimp_image_resize(image, sizex, sizey, ofsx, ofsy)
    pdb.gimp_drawable_transform_flip_simple(newLayer, vhflip, True, 0, False)
    pdb.gimp_layer_set_offsets(newLayer, movx, movy)
    image.flatten()

    image.undo_group_end()


Also see here for a way to avoid hardcoding integer values for user options.
Post a reply