RSS/Atom feed Twitter
Site is read-only, email is disabled

Optimizing border-like selection in python

This discussion is connected to the gimp-developer-list.gnome.org mailing list which is provided by the GIMP developers and not related to gimpusers.com.

This is a read-only list on gimpusers.com so this discussion thread is read-only, too.

14 of 14 messages available
Toggle history

Please log in to manage your subscriptions.

Optimizing border-like selection in python Ofnuts 24 Sep 16:19
  Optimizing border-like selection in python Joao S. O. Bueno 24 Sep 17:05
   Optimizing border-like selection in python Ofnuts 24 Sep 19:44
    Optimizing border-like selection in python Ofnuts 24 Sep 22:57
     Optimizing border-like selection in python Rob Antonishen 24 Sep 23:03
   Optimizing border-like selection in python Ofnuts 27 Sep 08:45
    Optimizing border-like selection in python Joao S. O. Bueno 27 Sep 13:58
     Optimizing border-like selection in python Sven Neumann 27 Sep 17:55
  Optimizing border-like selection in python Jerry Baker 25 Sep 00:18
   Optimizing border-like selection in python Jerry Baker 25 Sep 00:27
    Optimizing border-like selection in python Ofnuts 25 Sep 00:37
     Optimizing border-like selection in python Jerry Baker 25 Sep 00:40
  Optimizing border-like selection in python saulgoode@flashingtwelve.brickfilms.com 27 Sep 18:47
   Optimizing border-like selection in python Ofnuts 29 Sep 21:55
Ofnuts
2010-09-24 16:19:25 UTC (over 14 years ago)

Optimizing border-like selection in python

Hi,

My code needs to do a one-pixel-wide selection, at distance "x" from the current selection. This looks a lot like a border selection except that the border selection creates at best a two-pixel wide ribbon and I only want one (but if I'm wrong, please tell me how to :-)

So far my code goes like this:

# Selects pixels that are between x and x+1 pixels from # the original selection. Bumping the selection by one # each time doesn't work, a small circle degenerates into # a square with rounded corners instead of a big circle. def select_ribbon(self,image,selection,dist): pdb.gimp_selection_load(selection) pdb.gimp_selection_grow(image,dist+1) outer=pdb.gimp_selection_save(image) pdb.gimp_selection_load(selection) pdb.gimp_selection_grow(image,dist) inner=pdb.gimp_selection_save(image) pdb.gimp_channel_combine_masks(outer,inner,CHANNEL_OP_SUBTRACT,0,0) pdb.gimp_selection_load(outer) image.remove_channel(outer) image.remove_channel(inner)

That works, but can be slow (especially since it's at the core of a loop). Is there any better way? Or useless code to jettison?

Next improvement is to create a 3-pixels selection and feather it one pixel. Anything to be wary of?

-- Ofnuts

Joao S. O. Bueno
2010-09-24 17:05:16 UTC (over 14 years ago)

Optimizing border-like selection in python

On Fri, Sep 24, 2010 at 11:19 AM, Ofnuts wrote:

 Hi,

My code needs to do a one-pixel-wide selection, at distance "x" from the current selection.  This looks a lot like a border selection except that the border selection creates at best a two-pixel wide ribbon and I only want one (but if I'm wrong, please tell me how to :-)

So far my code goes like this:

# Selects pixels that are between x and x+1 pixels from # the original selection. Bumping the selection by one # each time doesn't work, a small circle degenerates into # a square with rounded corners instead of a big circle.     def select_ribbon(self,image,selection,dist):         pdb.gimp_selection_load(selection)         pdb.gimp_selection_grow(image,dist+1)         outer=pdb.gimp_selection_save(image)         pdb.gimp_selection_load(selection)         pdb.gimp_selection_grow(image,dist)         inner=pdb.gimp_selection_save(image)         pdb.gimp_channel_combine_masks(outer,inner,CHANNEL_OP_SUBTRACT,0,0)         pdb.gimp_selection_load(outer)         image.remove_channel(outer)
        image.remove_channel(inner)

That works, but can be slow (especially since it's at the core of a loop). Is there any better way? Or useless code to jettison?

Next improvement is to create a 3-pixels selection and feather it one pixel. Anything to be wary of?

Hmm..this _will_ be slow. :-)

You can speed it up by making a copy of your drawable to another image, disable the undo system on this new image and perform your cations above, before copying the results back to the original image - but it is about it.
Maybe you can perform the whole loop in the copy with undo disabled - but I don't know your intent.

js ->

--
Ofnuts

Ofnuts
2010-09-24 19:44:33 UTC (over 14 years ago)

Optimizing border-like selection in python

On 24/09/2010 17:05, Joao S. O. Bueno wrote:

On Fri, Sep 24, 2010 at 11:19 AM, Ofnuts wrote:

Hi,

My code needs to do a one-pixel-wide selection, at distance "x" from the current selection. This looks a lot like a border selection except that the border selection creates at best a two-pixel wide ribbon and I only want one (but if I'm wrong, please tell me how to :-)

So far my code goes like this:

# Selects pixels that are between x and x+1 pixels from # the original selection. Bumping the selection by one # each time doesn't work, a small circle degenerates into # a square with rounded corners instead of a big circle. def select_ribbon(self,image,selection,dist): pdb.gimp_selection_load(selection) pdb.gimp_selection_grow(image,dist+1) outer=pdb.gimp_selection_save(image) pdb.gimp_selection_load(selection) pdb.gimp_selection_grow(image,dist) inner=pdb.gimp_selection_save(image) pdb.gimp_channel_combine_masks(outer,inner,CHANNEL_OP_SUBTRACT,0,0) pdb.gimp_selection_load(outer) image.remove_channel(outer) image.remove_channel(inner)

That works, but can be slow (especially since it's at the core of a loop). Is there any better way? Or useless code to jettison?

Next improvement is to create a 3-pixels selection and feather it one pixel. Anything to be wary of?

Hmm..this _will_ be slow. :-)

You can speed it up by making a copy of your drawable to another image, disable the undo system on this new image and perform your cations above, before copying the results back to the original image - but it is about it.
Maybe you can perform the whole loop in the copy with undo disabled - but I don't know your intent.

The whole plugin paints successive concentric uniform 1-pixel ribbons around the original selection (pixel values a obtained from another layer). On my laptop (T2400, 1.83GHz) it takes roughly 10 seconds to draw 20 concentric ribbons around a 500-pixels circular selection.

The whole thing runs within a undo_group_start()/image.undo_group_end() so I don't expect any more undos?

Ofnuts
2010-09-24 22:57:05 UTC (over 14 years ago)

Optimizing border-like selection in python

On 24/09/2010 19:44, Ofnuts wrote:

The whole plugin paints successive concentric uniform 1-pixel ribbons around the original selection (pixel values a obtained from another layer). On my laptop (T2400, 1.83GHz) it takes roughly 10 seconds to draw 20 concentric ribbons around a 500-pixels circular selection.

The whole thing runs within a undo_group_start()/image.undo_group_end() so I don't expect any more undos?

By the way, when my plug-in runs, the "marching ants" go into a frenzy, as if each selection change caused a screen update (though the bucket-fills don't show until the whole thing is finished). Would disabling these updates speed things up? (if so how is it done?)

Rob Antonishen
2010-09-24 23:03:35 UTC (over 14 years ago)

Optimizing border-like selection in python

You can't disable the border selection programatically. In such cases what I've done is duplicate the image without displaying it and perform all the selection work on the duplicate then copy and paste it in as a channel into the original image. Then channel to Selection and delete the channel.

-Rob A>

On 9/24/10, Ofnuts wrote:

On 24/09/2010 19:44, Ofnuts wrote:

The whole plugin paints successive concentric uniform 1-pixel ribbons around the original selection (pixel values a obtained from another layer). On my laptop (T2400, 1.83GHz) it takes roughly 10 seconds to draw 20 concentric ribbons around a 500-pixels circular selection.

The whole thing runs within a undo_group_start()/image.undo_group_end() so I don't expect any more undos?

By the way, when my plug-in runs, the "marching ants" go into a frenzy, as if each selection change caused a screen update (though the bucket-fills don't show until the whole thing is finished). Would disabling these updates speed things up? (if so how is it done?)

-- Ofnuts

Jerry Baker
2010-09-25 00:18:59 UTC (over 14 years ago)

Optimizing border-like selection in python

Calculating a new selection from the current selection would be faster (I think):

def create_border(image, selection_type='rectangle', size=1): is_selection, x1, y1, x2, y2 = pdb.gimp_selection_bounds(image)

if is_selection: if size < 1:
size = 1
if selection_type =='rectangle': pdb.gimp_rect_select(image, x1+size, y1+size, (x2-x1)-(size*2), (y2-y1)-(size*2), CHANNEL_OP_SUBTRACT, False, 0) elif selection_type == 'ellipse': pdb.gimp_ellipse_select(image, x1+size, y1+size, (x2-x1)-(size*2), (y2-y1)-(size*2), CHANNEL_OP_SUBTRACT, True, False, 0) else:
gimp.message("Please make a selection...")

def test_plugin(image, drawable): image.undo_group_start()

create_border(image) # A rectangular selecion with default settings...
#create_border(image, selection_type='ellipse', size=3) # Or Ellipse with custom settings...

# Fill pdb.gimp_edit_fill(drawable, 0) pdb.gimp_selection_none(image)

image.undo_group_end()

On 09/24/2010 10:19 AM, Ofnuts wrote:

Hi,

My code needs to do a one-pixel-wide selection, at distance "x" from the current selection. This looks a lot like a border selection except that the border selection creates at best a two-pixel wide ribbon and I only want one (but if I'm wrong, please tell me how to :-)

So far my code goes like this:

# Selects pixels that are between x and x+1 pixels from # the original selection. Bumping the selection by one # each time doesn't work, a small circle degenerates into # a square with rounded corners instead of a big circle. def select_ribbon(self,image,selection,dist): pdb.gimp_selection_load(selection) pdb.gimp_selection_grow(image,dist+1) outer=pdb.gimp_selection_save(image) pdb.gimp_selection_load(selection) pdb.gimp_selection_grow(image,dist) inner=pdb.gimp_selection_save(image) pdb.gimp_channel_combine_masks(outer,inner,CHANNEL_OP_SUBTRACT,0,0) pdb.gimp_selection_load(outer) image.remove_channel(outer) image.remove_channel(inner)

That works, but can be slow (especially since it's at the core of a loop). Is there any better way? Or useless code to jettison?

Next improvement is to create a 3-pixels selection and feather it one pixel. Anything to be wary of?

-- Ofnuts

Jerry Baker
2010-09-25 00:27:18 UTC (over 14 years ago)

Optimizing border-like selection in python

Ahh... autoformatting... this should be easier to read... (sorry)

def create_border(image, selection_type='rectangle', size=1): is_selection, x1, y1, x2, y2 = pdb.gimp_selection_bounds(image)

if is_selection: if size < 1:
size = 1
if selection_type =='rectangle': pdb.gimp_rect_select(image, x1+size, y1+size, (x2-x1)-(size*2), (y2-y1)-(size*2), CHANNEL_OP_SUBTRACT, False, 0)
elif selection_type == 'ellipse': pdb.gimp_ellipse_select(image, x1+size, y1+size, (x2-x1)-(size*2), (y2-y1)-(size*2), CHANNEL_OP_SUBTRACT, True, False, 0) else:
gimp.message("Please make a selection...")

def test_plugin(image, drawable): image.undo_group_start()

# A rectangular selecion with default settings... create_border(image)

# Ellipse with custom settings... Uncomment to activate #create_border(image, selection_type='ellipse', size=3)

# Fill pdb.gimp_edit_fill(drawable, 0) pdb.gimp_selection_none(image)

image.undo_group_end()

On 09/24/2010 06:18 PM, Jerry Baker wrote:

Calculating a new selection from the current selection would be faster (I think):

def create_border(image, selection_type='rectangle', size=1): is_selection, x1, y1, x2, y2 = pdb.gimp_selection_bounds(image)

if is_selection: if size< 1:
size = 1
if selection_type =='rectangle': pdb.gimp_rect_select(image, x1+size, y1+size, (x2-x1)-(size*2), (y2-y1)-(size*2), CHANNEL_OP_SUBTRACT, False, 0) elif selection_type == 'ellipse': pdb.gimp_ellipse_select(image, x1+size, y1+size, (x2-x1)-(size*2), (y2-y1)-(size*2), CHANNEL_OP_SUBTRACT, True, False, 0) else:
gimp.message("Please make a selection...")

def test_plugin(image, drawable): image.undo_group_start()

create_border(image) # A rectangular selecion with default settings...
#create_border(image, selection_type='ellipse', size=3) # Or Ellipse with custom settings...

# Fill pdb.gimp_edit_fill(drawable, 0) pdb.gimp_selection_none(image)

image.undo_group_end()

On 09/24/2010 10:19 AM, Ofnuts wrote:

Hi,

My code needs to do a one-pixel-wide selection, at distance "x" from the current selection. This looks a lot like a border selection except that the border selection creates at best a two-pixel wide ribbon and I only want one (but if I'm wrong, please tell me how to :-)

So far my code goes like this:

# Selects pixels that are between x and x+1 pixels from # the original selection. Bumping the selection by one # each time doesn't work, a small circle degenerates into # a square with rounded corners instead of a big circle. def select_ribbon(self,image,selection,dist): pdb.gimp_selection_load(selection) pdb.gimp_selection_grow(image,dist+1) outer=pdb.gimp_selection_save(image) pdb.gimp_selection_load(selection) pdb.gimp_selection_grow(image,dist) inner=pdb.gimp_selection_save(image) pdb.gimp_channel_combine_masks(outer,inner,CHANNEL_OP_SUBTRACT,0,0) pdb.gimp_selection_load(outer) image.remove_channel(outer) image.remove_channel(inner)

That works, but can be slow (especially since it's at the core of a loop). Is there any better way? Or useless code to jettison?

Next improvement is to create a 3-pixels selection and feather it one pixel. Anything to be wary of?

-- Ofnuts

Ofnuts
2010-09-25 00:37:31 UTC (over 14 years ago)

Optimizing border-like selection in python

The code should work for any shape of selection (for instance after a text-to-selection). Actually the plugin this routine is part of hasn't got much merit on rectangular/circular selections...

On 25/09/2010 00:27, Jerry Baker wrote:

Ahh... autoformatting... this should be easier to read... (sorry)

def create_border(image, selection_type='rectangle', size=1): is_selection, x1, y1, x2, y2 = pdb.gimp_selection_bounds(image)

if is_selection: if size < 1:
size = 1
if selection_type =='rectangle':
pdb.gimp_rect_select(image,
x1+size,
y1+size,
(x2-x1)-(size*2),
(y2-y1)-(size*2),
CHANNEL_OP_SUBTRACT,
False,
0)
elif selection_type == 'ellipse':
pdb.gimp_ellipse_select(image,
x1+size,
y1+size,
(x2-x1)-(size*2),
(y2-y1)-(size*2),
CHANNEL_OP_SUBTRACT,
True,
False,
0)
else:
gimp.message("Please make a selection...")

def test_plugin(image, drawable): image.undo_group_start()

# A rectangular selecion with default settings... create_border(image)

# Ellipse with custom settings... Uncomment to activate #create_border(image, selection_type='ellipse', size=3)

# Fill pdb.gimp_edit_fill(drawable, 0)
pdb.gimp_selection_none(image)

image.undo_group_end()

On 09/24/2010 06:18 PM, Jerry Baker wrote:

Calculating a new selection from the current selection would be faster (I think):

def create_border(image, selection_type='rectangle', size=1): is_selection, x1, y1, x2, y2 = pdb.gimp_selection_bounds(image)

if is_selection: if size< 1:
size = 1
if selection_type =='rectangle':
pdb.gimp_rect_select(image, x1+size, y1+size, (x2-x1)-(size*2), (y2-y1)-(size*2), CHANNEL_OP_SUBTRACT, False, 0) elif selection_type == 'ellipse':
pdb.gimp_ellipse_select(image, x1+size, y1+size, (x2-x1)-(size*2), (y2-y1)-(size*2), CHANNEL_OP_SUBTRACT, True, False, 0) else:
gimp.message("Please make a selection...")

def test_plugin(image, drawable): image.undo_group_start()

create_border(image) # A rectangular selecion with default settings...
#create_border(image, selection_type='ellipse', size=3) # Or Ellipse with custom settings...

# Fill pdb.gimp_edit_fill(drawable, 0)
pdb.gimp_selection_none(image)

image.undo_group_end()

Jerry Baker
2010-09-25 00:40:44 UTC (over 14 years ago)

Optimizing border-like selection in python

You'll have to keep an eye on the parameter count. The ellipse select requires one more parameter than the rectangle one. But yes, some of them should work...

On 09/24/2010 06:37 PM, Ofnuts wrote:

The code should work for any shape of selection (for instance after a text-to-selection). Actually the plugin this routine is part of hasn't got much merit on rectangular/circular selections...

On 25/09/2010 00:27, Jerry Baker wrote:

Ahh... autoformatting... this should be easier to read... (sorry)

def create_border(image, selection_type='rectangle', size=1): is_selection, x1, y1, x2, y2 = pdb.gimp_selection_bounds(image)

if is_selection: if size< 1:
size = 1
if selection_type =='rectangle':
pdb.gimp_rect_select(image,
x1+size,
y1+size,
(x2-x1)-(size*2),
(y2-y1)-(size*2),
CHANNEL_OP_SUBTRACT,
False,
0)
elif selection_type == 'ellipse':
pdb.gimp_ellipse_select(image,
x1+size,
y1+size,
(x2-x1)-(size*2),
(y2-y1)-(size*2),
CHANNEL_OP_SUBTRACT,
True,
False,
0)
else:
gimp.message("Please make a selection...")

def test_plugin(image, drawable): image.undo_group_start()

# A rectangular selecion with default settings... create_border(image)

# Ellipse with custom settings... Uncomment to activate #create_border(image, selection_type='ellipse', size=3)

# Fill pdb.gimp_edit_fill(drawable, 0)
pdb.gimp_selection_none(image)

image.undo_group_end()

On 09/24/2010 06:18 PM, Jerry Baker wrote:

Calculating a new selection from the current selection would be faster (I think):

def create_border(image, selection_type='rectangle', size=1): is_selection, x1, y1, x2, y2 = pdb.gimp_selection_bounds(image)

if is_selection: if size< 1:
size = 1
if selection_type =='rectangle':
pdb.gimp_rect_select(image, x1+size, y1+size, (x2-x1)-(size*2), (y2-y1)-(size*2), CHANNEL_OP_SUBTRACT, False, 0) elif selection_type == 'ellipse':
pdb.gimp_ellipse_select(image, x1+size, y1+size, (x2-x1)-(size*2), (y2-y1)-(size*2), CHANNEL_OP_SUBTRACT, True, False, 0) else:
gimp.message("Please make a selection...")

def test_plugin(image, drawable): image.undo_group_start()

create_border(image) # A rectangular selecion with default settings...
#create_border(image, selection_type='ellipse', size=3) # Or Ellipse with custom settings...

# Fill pdb.gimp_edit_fill(drawable, 0)
pdb.gimp_selection_none(image)

image.undo_group_end()

Ofnuts
2010-09-27 08:45:52 UTC (over 14 years ago)

Optimizing border-like selection in python

On 24/09/2010 17:05, Joao S. O. Bueno wrote:

On Fri, Sep 24, 2010 at 11:19 AM, Ofnuts wrote:

Hi,

My code needs to do a one-pixel-wide selection, at distance "x" from the current selection. This looks a lot like a border selection except that the border selection creates at best a two-pixel wide ribbon and I only want one (but if I'm wrong, please tell me how to :-)

So far my code goes like this:

# Selects pixels that are between x and x+1 pixels from # the original selection. Bumping the selection by one # each time doesn't work, a small circle degenerates into # a square with rounded corners instead of a big circle. def select_ribbon(self,image,selection,dist): pdb.gimp_selection_load(selection) pdb.gimp_selection_grow(image,dist+1) outer=pdb.gimp_selection_save(image) pdb.gimp_selection_load(selection) pdb.gimp_selection_grow(image,dist) inner=pdb.gimp_selection_save(image) pdb.gimp_channel_combine_masks(outer,inner,CHANNEL_OP_SUBTRACT,0,0) pdb.gimp_selection_load(outer) image.remove_channel(outer) image.remove_channel(inner)

That works, but can be slow (especially since it's at the core of a loop). Is there any better way? Or useless code to jettison?

Next improvement is to create a 3-pixels selection and feather it one pixel. Anything to be wary of?

Hmm..this _will_ be slow. :-)

You can speed it up by making a copy of your drawable to another image, disable the undo system on this new image and perform your cations above, before copying the results back to the original image - but it is about it.
Maybe you can perform the whole loop in the copy with undo disabled - but I don't know your intent.

Disabling undo on the main image (just for tests) doesn't show much speed gain (from 2'03" to 1'56" in my test). It's only better memory-wise.

Joao S. O. Bueno
2010-09-27 13:58:10 UTC (over 14 years ago)

Optimizing border-like selection in python

On Mon, Sep 27, 2010 at 3:45 AM, Ofnuts wrote:

On 24/09/2010 17:05, Joao S. O. Bueno wrote:

On Fri, Sep 24, 2010 at 11:19 AM, Ofnuts  wrote:

  Hi,

My code needs to do a one-pixel-wide selection, at distance "x" from the current selection.  This looks a lot like a border selection except that the border selection creates at best a two-pixel wide ribbon and I only want one (but if I'm wrong, please tell me how to :-)

So far my code goes like this:

# Selects pixels that are between x and x+1 pixels from # the original selection. Bumping the selection by one # each time doesn't work, a small circle degenerates into # a square with rounded corners instead of a big circle.      def select_ribbon(self,image,selection,dist):          pdb.gimp_selection_load(selection)          pdb.gimp_selection_grow(image,dist+1)          outer=pdb.gimp_selection_save(image)          pdb.gimp_selection_load(selection)          pdb.gimp_selection_grow(image,dist)          inner=pdb.gimp_selection_save(image)          pdb.gimp_channel_combine_masks(outer,inner,CHANNEL_OP_SUBTRACT,0,0)          pdb.gimp_selection_load(outer)          image.remove_channel(outer)          image.remove_channel(inner)

That works, but can be slow (especially since it's at the core of a loop). Is there any better way? Or useless code to jettison?

Next improvement is to create a 3-pixels selection and feather it one pixel. Anything to be wary of?

Hmm..this _will_ be slow. :-)

You can speed it up by making a copy of your drawable to another image, disable the undo system on this new image  and perform your cations above, before copying the results back to the original image - but it is about it.
Maybe you can perform the whole loop in the copy with undo disabled - but I don't know your intent.

Disabling undo on the main image (just for tests) doesn't show much speed gain (from 2'03" to 1'56" in my test). It's only better memory-wise.

Hmm..maybe soem of the spped-up I experience has tod o with the new image I create on BG not being displayed - it will certainly help on this due to the marching ants that are used midway that don't need to show up.

js ->

Sven Neumann
2010-09-27 17:55:39 UTC (over 14 years ago)

Optimizing border-like selection in python

On Mon, 2010-09-27 at 08:58 -0300, Joao S. O. Bueno wrote:

Hmm..maybe soem of the spped-up I experience has tod o with the new image I create on BG not being displayed - it will certainly help on this due to the marching ants that are used midway that don't need to show up.

Shouldn't make much of a difference. The change to the selection only invalidates the view and queues a redraw. The pending redraw shouldn't slow things down considerably.

Sven

saulgoode@flashingtwelve.brickfilms.com
2010-09-27 18:47:33 UTC (over 14 years ago)

Optimizing border-like selection in python

Quoting Ofnuts :

My code needs to do a one-pixel-wide selection, at distance "x" from the current selection. This looks a lot like a border selection except that the border selection creates at best a two-pixel wide ribbon and I only want one (but if I'm wrong, please tell me how to :-)

So far my code goes like this:

# Selects pixels that are between x and x+1 pixels from # the original selection. Bumping the selection by one # each time doesn't work, a small circle degenerates into # a square with rounded corners instead of a big circle. def select_ribbon(self,image,selection,dist): pdb.gimp_selection_load(selection) pdb.gimp_selection_grow(image,dist+1) outer=pdb.gimp_selection_save(image) pdb.gimp_selection_load(selection) pdb.gimp_selection_grow(image,dist) inner=pdb.gimp_selection_save(image) pdb.gimp_channel_combine_masks(outer,inner,CHANNEL_OP_SUBTRACT,0,0) pdb.gimp_selection_load(outer) image.remove_channel(outer) image.remove_channel(inner)

That works, but can be slow (especially since it's at the core of a loop). Is there any better way? Or useless code to jettison?

There is no need to create (and later delete) the 'outer' channel. Just use the selection itself. In Script-fu, this would be done as follows:

(gimp-selection-load selection) (gimp-selection-grow image dist)
(set! inner (car (gimp-selection-save image))) (gimp-selection-load selection)
(gimp-selection-grow image (+ dist 1)) (gimp-channel-combine-masks (car (gimp-image-get-selection image)) inner CHANNEL-OP-SUBTRACT 0 0) (gimp-image-remove-channel image inner)

Ofnuts
2010-09-29 21:55:46 UTC (over 14 years ago)

Optimizing border-like selection in python

On 27/09/2010 18:47, saulgoode@flashingtwelve.brickfilms.com wrote:

Quoting Ofnuts:

My code needs to do a one-pixel-wide selection, at distance "x" from the current selection. This looks a lot like a border selection except that the border selection creates at best a two-pixel wide ribbon and I only want one (but if I'm wrong, please tell me how to :-)

So far my code goes like this:

# Selects pixels that are between x and x+1 pixels from # the original selection. Bumping the selection by one # each time doesn't work, a small circle degenerates into # a square with rounded corners instead of a big circle. def select_ribbon(self,image,selection,dist): pdb.gimp_selection_load(selection) pdb.gimp_selection_grow(image,dist+1) outer=pdb.gimp_selection_save(image) pdb.gimp_selection_load(selection) pdb.gimp_selection_grow(image,dist) inner=pdb.gimp_selection_save(image) pdb.gimp_channel_combine_masks(outer,inner,CHANNEL_OP_SUBTRACT,0,0) pdb.gimp_selection_load(outer) image.remove_channel(outer) image.remove_channel(inner)

That works, but can be slow (especially since it's at the core of a loop). Is there any better way? Or useless code to jettison?

There is no need to create (and later delete) the 'outer' channel. Just use the selection itself. In Script-fu, this would be done as follows:

(gimp-selection-load selection) (gimp-selection-grow image dist) (set! inner (car (gimp-selection-save image))) (gimp-selection-load selection)
(gimp-selection-grow image (+ dist 1)) (gimp-channel-combine-masks (car (gimp-image-get-selection image)) inner CHANNEL-OP-SUBTRACT 0 0) (gimp-image-remove-channel image inner)

Implemented your code. It runs 10 to 20% faster, and uses only half the memory... So you have been duly credited in the V0.2 history. Thx.