Gimp 3 - python to edit the selection - violgamba - 05-29-2025
I'm trying to make a plugin to edit the current image's selection. I'm pretty sure I've worked out how to pull in and edit the selection at this point, but I don't know how to set the modified selection back into the image. I've a few questions:
- Is there documentation for how to handle this sort of thing? It was quite the effort to get as far as I've gotten. I am comfortable with C, if that helps.
- Can anyone provide an example of how to modify the current image's selection based on a byte array?
- Alternately, here is my current logic. If anyone can fill in the blank ("# ???" line) then I'd be very grateful:
Code:
def do_run(self, procedure, run_mode, image, n_drawables, drawables, config):
try:
selection_mask = image.get_selection()
if selection_mask is None:
Gimp.message("No selection found. This tool only works with an active selection.")
return procedure.new_return_values(Gimp.PDBStatusType.EXECUTION_ERROR, None)
old_buffer = selection_mask.get_buffer()
rect = old_buffer.get_extent()
old_buffer_bytes = old_buffer.get(rect, 1.0, "Y float", Gegl.AbyssPolicy.NONE)
src_pixels = bytearray(old_buffer_bytes)
dst_pixels = bytearray(old_buffer_bytes)
for y in range(1, rect.height - 1):
for x in range(1, rect.width - 1):
pixel_index = x + y * rect.width
if (src_pixels[pixel_index + 1] != 0 and
src_pixels[pixel_index - 1] != 0 and
src_pixels[pixel_index + rect.width] != 0 and
src_pixels[pixel_index - rect.width] != 0):
dst_pixels[pixel_index] = 0
new_buffer = Gegl.Buffer.new("Y float", rect.x, rect.y, rect.width, rect.height)
new_buffer.set(rect, "Y float", list(dst_pixels))
# ???
return procedure.new_return_values(Gimp.PDBStatusType.SUCCESS, None)
except Exception as e:
Gimp.message(f"ERR: {e}")
return procedure.new_return_values(Gimp.PDBStatusType.EXECUTION_ERROR, None)
RE: Gimp 3 - python to edit the selection - programmer_ceds - 05-29-2025
(05-29-2025, 09:36 AM)violgamba Wrote: I'm trying to make a plugin to edit the current image's selection. I'm pretty sure I've worked out how to pull in and edit the selection at this point, but I don't know how to set the modified selection back into the image. I've a few questions:
- Is there documentation for how to handle this sort of thing? It was quite the effort to get as far as I've gotten. I am comfortable with C, if that helps.
- Can anyone provide an example of how to modify the current image's selection based on a byte array?
- Alternately, here is my current logic. If anyone can fill in the blank ("# ???" line) then I'd be very grateful:
Code:
def do_run(self, procedure, run_mode, image, n_drawables, drawables, config):
try:
selection_mask = image.get_selection()
if selection_mask is None:
Gimp.message("No selection found. This tool only works with an active selection.")
return procedure.new_return_values(Gimp.PDBStatusType.EXECUTION_ERROR, None)
old_buffer = selection_mask.get_buffer()
rect = old_buffer.get_extent()
old_buffer_bytes = old_buffer.get(rect, 1.0, "Y float", Gegl.AbyssPolicy.NONE)
src_pixels = bytearray(old_buffer_bytes)
dst_pixels = bytearray(old_buffer_bytes)
for y in range(1, rect.height - 1):
for x in range(1, rect.width - 1):
pixel_index = x + y * rect.width
if (src_pixels[pixel_index + 1] != 0 and
src_pixels[pixel_index - 1] != 0 and
src_pixels[pixel_index + rect.width] != 0 and
src_pixels[pixel_index - rect.width] != 0):
dst_pixels[pixel_index] = 0
new_buffer = Gegl.Buffer.new("Y float", rect.x, rect.y, rect.width, rect.height)
new_buffer.set(rect, "Y float", list(dst_pixels))
# ???
return procedure.new_return_values(Gimp.PDBStatusType.SUCCESS, None)
except Exception as e:
Gimp.message(f"ERR: {e}")
return procedure.new_return_values(Gimp.PDBStatusType.EXECUTION_ERROR, None)
If you type gimp-image-select into the PDB browser you will find a number of procedures for selecting parts of the image e.g. gimp-image-select-rectangle()
RE: Gimp 3 - python to edit the selection - violgamba - 05-31-2025
Quote:If you type gimp-image-select into the PDB browser you will find a number of procedures for selecting parts of the image e.g. gimp-image-select-rectangle()
This is useful in a general sense, but I'm not seeing any option here to set the selection based on a byte array, or anything that a byte array can be transformed into. "gimp-image-select-rectangle" is the nearest match, and it doesn't seem very efficient to turn my byte array into a series of selection rectangles, then call the procedure once for each.
RE: Gimp 3 - python to edit the selection - Ofnuts - 05-31-2025
(05-29-2025, 09:36 AM)violgamba Wrote: I'm trying to make a plugin to edit the current image's selection. I'm pretty sure I've worked out how to pull in and edit the selection at this point, but I don't know how to set the modified selection back into the image. I've a few questions:
- Is there documentation for how to handle this sort of thing? It was quite the effort to get as far as I've gotten. I am comfortable with C, if that helps.
- Can anyone provide an example of how to modify the current image's selection based on a byte array?
- Alternately, here is my current logic. If anyone can fill in the blank ("# ???" line) then I'd be very grateful:
Code:
def do_run(self, procedure, run_mode, image, n_drawables, drawables, config):
try:
selection_mask = image.get_selection()
if selection_mask is None:
Gimp.message("No selection found. This tool only works with an active selection.")
return procedure.new_return_values(Gimp.PDBStatusType.EXECUTION_ERROR, None)
old_buffer = selection_mask.get_buffer()
rect = old_buffer.get_extent()
old_buffer_bytes = old_buffer.get(rect, 1.0, "Y float", Gegl.AbyssPolicy.NONE)
src_pixels = bytearray(old_buffer_bytes)
dst_pixels = bytearray(old_buffer_bytes)
for y in range(1, rect.height - 1):
for x in range(1, rect.width - 1):
pixel_index = x + y * rect.width
if (src_pixels[pixel_index + 1] != 0 and
src_pixels[pixel_index - 1] != 0 and
src_pixels[pixel_index + rect.width] != 0 and
src_pixels[pixel_index - rect.width] != 0):
dst_pixels[pixel_index] = 0
new_buffer = Gegl.Buffer.new("Y float", rect.x, rect.y, rect.width, rect.height)
new_buffer.set(rect, "Y float", list(dst_pixels))
# ???
return procedure.new_return_values(Gimp.PDBStatusType.SUCCESS, None)
except Exception as e:
Gimp.message(f"ERR: {e}")
return procedure.new_return_values(Gimp.PDBStatusType.EXECUTION_ERROR, None)
As I understand the doc, you would get a buffer form the drawable (the selection, here) (which is how you get old_buffer) and then write to it. When you close it, the contents are copied to the original drawable. So instead of copying dst_pixels to a new buffer you would just copy them to the original buffer.
|