Posts: 21
Threads: 7
Joined: Mar 2023
Reputation:
0
Gimp version:
Operating system(s): Windows Vista or 7, 8, 10 (64-bit)
Linux
I have a script that does some selects and cuts based on color.
Code:
image = pyi.file_load(r'/windows/projects/5150/Graphic Prefabs for Maps/geomorphs/hi-res/dead_parrot/legend/blank/4cb2d3ac-a815-4728-a8a1-0fac1e5e1e6f-018.png')
color = Gegl.Color.new("black")
layer = image.get_layers()[0]
pyi.layer_add_alpha(layer)
pyi.image_select_color(image, Gimp.ChannelOps.REPLACE, layer, color)
pyi.gimp_selection_invert(layer)
pyi.drawable_edit_clear(layer)
pyi.image_resize(image, 7857, 6068)
pyi.file_save(image, r'/windows/projects/5150/Graphic Prefabs for Maps/geomorphs/hi-res/dead_parrot/test/end.png')
pyi.gimp_selection_none(image)
pyi.image_delete(image)
color.do_dispose()
del color
pyi.gimp_quit(False)
When run it either reports 1 or 2 leaked buffers. I have tried to dispose of the color item but have as yet been unsuccessful. When run without any color creation like this, it runs with no buffer leaks.
Code:
image = pyi.file_load(r'/windows/projects/5150/Graphic Prefabs for Maps/geomorphs/hi-res/dead_parrot/legend/blank/4cb2d3ac-a815-4728-a8a1-0fac1e5e1e6f-018.png')
layer = image.get_layers()[0]
pyi.layer_add_alpha(layer)
pyi.image_resize(image, 7857, 6068)
pyi.file_save(image, r'/windows/projects/5150/Graphic Prefabs for Maps/geomorphs/hi-res/dead_parrot/test/end.png')
pyi.gimp_selection_none(image)
pyi.image_delete(image)
pyi.gimp_quit(False)
Hoping someone can help me find the problem. Here's the output, this time it was just one leaked buffer but sometimes it is two:
Quote:Leaked buffer allocation stack trace:
/usr/local/lib64/libgegl-0.4.so.0(+0x4eefa) [0x7f1aac639efa]
/lib64/libgobject-2.0.so.0(g_type_create_instance+0x271) [0x7f1aac867af1]
/lib64/libgobject-2.0.so.0(+0x1d684) [0x7f1aac84b684]
/usr/local/lib64/libgegl-0.4.so.0(+0x4f2a8) [0x7f1aac63a2a8]
/lib64/libgobject-2.0.so.0(+0x1dc34) [0x7f1aac84bc34]
/lib64/libgobject-2.0.so.0(g_object_new_valist+0x1a7) [0x7f1aac84e0d7]
/lib64/libgobject-2.0.so.0(g_object_new+0x99) [0x7f1aac84e849]
/usr/local/lib64/libgegl-0.4.so.0(gegl_buffer_new+0x68) [0x7f1aac63ac78]
gimp(gimp_layer_add_alpha+0x86) [0x502c46]
gimp() [0x59edb7]
gimp(gimp_procedure_execute+0x1da) [0x6271ba]
gimp(gimp_pdb_execute_procedure_by_name_args+0x159) [0x623cb9]
gimp(gimp_plug_in_handle_message+0x63b) [0x63cc9b]
gimp() [0x62c496]
/lib64/libglib-2.0.so.0(+0x5f638) [0x7f1aac737638]
/lib64/libglib-2.0.so.0(+0x61398) [0x7f1aac739398]
/lib64/libglib-2.0.so.0(g_main_loop_run+0x77) [0x7f1aac739dc7]
gimp(gimp_plug_in_manager_call_run+0x6b1) [0x63e2a1]
gimp() [0x6323de]
gimp(gimp_procedure_execute+0x1da) [0x6271ba]
gimp(gimp_pdb_execute_procedure_by_name_args+0x159) [0x623cb9]
gimp(gimp_batch_run+0x1f5) [0x67b8c5]
gimp() [0x67757b]
/lib64/libgobject-2.0.so.0(g_closure_invoke+0x138) [0x7f1aac8458f8]
/lib64/libgobject-2.0.so.0(+0x2b5d3) [0x7f1aac8595d3]
/lib64/libgobject-2.0.so.0(+0x2cfe9) [0x7f1aac85afe9]
/lib64/libgobject-2.0.so.0(g_signal_emit_valist+0x32) [0x7f1aac860ad2]
/lib64/libgobject-2.0.so.0(g_signal_emit+0x8f) [0x7f1aac860b7f]
/lib64/libgio-2.0.so.0(+0xed0a0) [0x7f1aac4b00a0]
/lib64/libgio-2.0.so.0(g_application_run+0x107) [0x7f1aac4b0237]
gimp(app_run+0x1ea) [0x677aca]
gimp(main+0x365) [0x4bde55]
/lib64/libc.so.6(+0x2b12e) [0x7f1aab02b12e]
/lib64/libc.so.6(__libc_start_main+0x8b) [0x7f1aab02b1f9]
gimp(_start+0x25) [0x4bdfa5]
EEEEeEeek! 1 GeglBuffers leaked
Thanks in advance.
Posts: 6,672
Threads: 289
Joined: Oct 2016
Reputation:
587
Gimp version:
Operating system(s): Linux
04-13-2025, 07:14 PM
(This post was last modified: 04-13-2025, 07:17 PM by Ofnuts.)
I don't think it is the Color object, In GEGL a "buffer" is a a pixel area that is exchanged between GEGL and its caller. Looking at the stack trace is comes from the add_alpha step, but given your code it could also be probably coming from the selection steps.
However, you have this strange pyi object. What is hiding behind it? Why pyi.drawable_edit_clear(layer) when you can do layer.edit_clear(). Why pyi.gimp_selection_invert(layer) instead of image.get_selection().invert(image)? (and remark that a selection is attached to an image and not to a layer). The code in that pyi thing would be my first place to search...
Posts: 21
Threads: 7
Joined: Mar 2023
Reputation:
0
Gimp version:
Operating system(s): Windows Vista or 7, 8, 10 (64-bit)
Linux
04-13-2025, 08:58 PM
(This post was last modified: 04-13-2025, 09:35 PM by silenuznowan.)
(04-13-2025, 07:14 PM)Ofnuts Wrote: I don't think it is the Color object, In GEGL a "buffer" is a a pixel area that is exchanged between GEGL and its caller. Looking at the stack trace is comes from the add_alpha step, but given your code it could also be probably coming from the selection steps.
However, you have this strange pyi object. What is hiding behind it? Why pyi.drawable_edit_clear(layer) when you can do layer.edit_clear(). Why pyi.gimp_selection_invert(layer) instead of image.get_selection().invert(image)? (and remark that a selection is attached to an image and not to a layer). The code in that pyi thing would be my first place to search...
The pyi code is just the code for the same named pdb calls:
Code:
def drawable_edit_clear(drawable: Gimp.Drawable)->bool:
"""
Clear selected area of drawable.
This procedure clears the specified drawable. If the drawable has an alpha channel, the cleared pixels will become
transparent. If the drawable does not have an alpha channel, cleared pixels will be set to the background color.
This procedure only affects regions within a selection if there is a selection active.
This procedure is affected by the following context setters: 'gimp-context-set-background'.
:param drawable:
:return:
"""
procedure = Gimp.get_pdb().lookup_procedure('gimp-drawable-edit-clear')
config = procedure.create_config()
config.set_property('drawable', drawable)
result = procedure.run(config)
success = result.index(0)
return success
That way any operations I need are in the pyi module and i can use them anywhere. I know I can use direct api calls but is easier to look things up in the console browser than use the api documentation.
But all the methods in the pyi module were generated from the console browser so there is nothing mysterious there. And the more selections I make based on color it seems the more leaked buffers. One for each selection. Here's my slect by color:
Code:
def image_select_color(image: Gimp.Image,operation:Gimp.ChannelOps,drawable: Gimp.Drawable, color: Gegl.Color) -> Gimp.Image:
"""
Create a selection by selecting all pixels (in the specified drawable) with the same (or similar) color to that specified.
This tool creates a selection over the specified image. A by-color selection is determined by the supplied color
under the constraints of the current context settings. Essentially, all pixels (in the drawable) that have color
sufficiently close to the specified color (as determined by the threshold and criterion context values) are included in the
selection. To select transparent regions, the color specified must also have minimum alpha.
This procedure is affected by the following context setters: 'gimp-context-set-antialias', 'gimp-context-set-feather',
'gimp-context-set-feather-radius', 'gimp-context-set-sample-merged', 'gimp-context-set-sample-criterion',
'gimp-context-set-sample-threshold', 'gimp-context-set-sample-transparent'.
In the case of a merged sampling, the supplied drawable is ignored.
:param image:
:param operation:
:param drawable:
:param color:
:return:
"""
procedure = Gimp.get_pdb().lookup_procedure('gimp-image-select-color')
config = procedure.create_config()
config.set_property('image', image)
config.set_property('operation', operation)
config.set_property('drawable', drawable)
config.set_property('color', color)
result = procedure.run(config)
success = result.index(0)
if not success:
print("select by color failed")
As you can see the pyi module is straight from the browser. If it's not the color itself it must be something with the selection. The more selections i do based on color the more leaks it throws. Everything works as expected it just leaks like a sieve.
When I looked at the stack trace I was wondering if was before the add alpha. Also as mentioned initially, with out the color code, there are no buffer leaks applying the alpha, and scaling the image, it only starts to happen when I create the color and start selecting by it. So I was wondering if this was the part of thee stack trace that was the problem:
'/lib64/libgobject-2.0.so.0(g_type_create_instance+0x271) [0x7f1aac867af1]'
I just tried without converting the alpha channel first and it still happens, so I don't think it's to do with the adding of the alpha layer. New stack:
Quote:Leaked buffer allocation stack trace:
/usr/local/lib64/libgegl-0.4.so.0(+0x4eefa) [0x7fcc4357befa]
/lib64/libgobject-2.0.so.0(g_type_create_instance+0x271) [0x7fcc437a9af1]
/lib64/libgobject-2.0.so.0(+0x1d684) [0x7fcc4378d684]
/usr/local/lib64/libgegl-0.4.so.0(+0x4f2a8) [0x7fcc4357c2a8]
/lib64/libgobject-2.0.so.0(+0x1dc34) [0x7fcc4378dc34]
/lib64/libgobject-2.0.so.0(g_object_new_valist+0x1a7) [0x7fcc437900d7]
/lib64/libgobject-2.0.so.0(g_object_new+0x99) [0x7fcc43790849]
/usr/local/lib64/libgegl-0.4.so.0(gegl_buffer_new+0x68) [0x7fcc4357cc78]
gimp(gimp_drawable_new+0xc3) [0x54e6a3]
gimp(gimp_layer_new+0x84) [0x4ffec4]
gimp(gimp_layer_new_from_gegl_buffer+0xdf) [0x50006f]
gimp(gimp_image_new_from_buffer+0x149) [0x5664e9]
gimp() [0x5cb4e2]
gimp(gimp_procedure_execute+0x1da) [0x6271ba]
gimp(gimp_pdb_execute_procedure_by_name_args+0x159) [0x623cb9]
gimp(gimp_plug_in_handle_message+0x63b) [0x63cc9b]
gimp() [0x62c496]
/lib64/libglib-2.0.so.0(+0x5f638) [0x7fcc43679638]
/lib64/libglib-2.0.so.0(+0x61398) [0x7fcc4367b398]
/lib64/libglib-2.0.so.0(g_main_loop_run+0x77) [0x7fcc4367bdc7]
gimp(gimp_plug_in_manager_call_run+0x6b1) [0x63e2a1]
gimp() [0x6323de]
gimp(gimp_procedure_execute+0x1da) [0x6271ba]
gimp(gimp_pdb_execute_procedure_by_name_args+0x159) [0x623cb9]
gimp(gimp_batch_run+0x1f5) [0x67b8c5]
gimp() [0x67757b]
/lib64/libgobject-2.0.so.0(g_closure_invoke+0x138) [0x7fcc437878f8]
/lib64/libgobject-2.0.so.0(+0x2b5d3) [0x7fcc4379b5d3]
/lib64/libgobject-2.0.so.0(+0x2cfe9) [0x7fcc4379cfe9]
/lib64/libgobject-2.0.so.0(g_signal_emit_valist+0x32) [0x7fcc437a2ad2]
/lib64/libgobject-2.0.so.0(g_signal_emit+0x8f) [0x7fcc437a2b7f]
/lib64/libgio-2.0.so.0(+0xed0a0) [0x7fcc433f20a0]
/lib64/libgio-2.0.so.0(g_application_run+0x107) [0x7fcc433f2237]
gimp(app_run+0x1ea) [0x677aca]
gimp(main+0x365) [0x4bde55]
/lib64/libc.so.6(+0x2b12e) [0x7fcc4202b12e]
/lib64/libc.so.6(__libc_start_main+0x8b) [0x7fcc4202b1f9]
gimp(_start+0x25) [0x4bdfa5]
EEEEeEeek! 17 GeglBuffers leaked
Just tried something different and instantiated new colors each time I needed them and it didn't effect things, so likely not to do with the color either.
Posts: 21
Threads: 7
Joined: Mar 2023
Reputation:
0
Gimp version:
Operating system(s): Windows Vista or 7, 8, 10 (64-bit)
Linux
(04-13-2025, 08:58 PM)silenuznowan Wrote: (04-13-2025, 07:14 PM)Ofnuts Wrote: I don't think it is the Color object, In GEGL a "buffer" is a a pixel area that is exchanged between GEGL and its caller. Looking at the stack trace is comes from the add_alpha step, but given your code it could also be probably coming from the selection steps.
However, you have this strange pyi object. What is hiding behind it? Why pyi.drawable_edit_clear(layer) when you can do layer.edit_clear(). Why pyi.gimp_selection_invert(layer) instead of image.get_selection().invert(image)? (and remark that a selection is attached to an image and not to a layer). The code in that pyi thing would be my first place to search...
The pyi code is just the code for the same named pdb calls:
Code:
def drawable_edit_clear(drawable: Gimp.Drawable)->bool:
"""
Clear selected area of drawable.
This procedure clears the specified drawable. If the drawable has an alpha channel, the cleared pixels will become
transparent. If the drawable does not have an alpha channel, cleared pixels will be set to the background color.
This procedure only affects regions within a selection if there is a selection active.
This procedure is affected by the following context setters: 'gimp-context-set-background'.
:param drawable:
:return:
"""
procedure = Gimp.get_pdb().lookup_procedure('gimp-drawable-edit-clear')
config = procedure.create_config()
config.set_property('drawable', drawable)
result = procedure.run(config)
success = result.index(0)
return success
That way any operations I need are in the pyi module and i can use them anywhere. I know I can use direct api calls but is easier to look things up in the console browser than use the api documentation.
But all the methods in the pyi module were generated from the console browser so there is nothing mysterious there. And the more selections I make based on color it seems the more leaked buffers. One for each selection. Here's my slect by color:
Code:
def image_select_color(image: Gimp.Image,operation:Gimp.ChannelOps,drawable: Gimp.Drawable, color: Gegl.Color) -> Gimp.Image:
"""
Create a selection by selecting all pixels (in the specified drawable) with the same (or similar) color to that specified.
This tool creates a selection over the specified image. A by-color selection is determined by the supplied color
under the constraints of the current context settings. Essentially, all pixels (in the drawable) that have color
sufficiently close to the specified color (as determined by the threshold and criterion context values) are included in the
selection. To select transparent regions, the color specified must also have minimum alpha.
This procedure is affected by the following context setters: 'gimp-context-set-antialias', 'gimp-context-set-feather',
'gimp-context-set-feather-radius', 'gimp-context-set-sample-merged', 'gimp-context-set-sample-criterion',
'gimp-context-set-sample-threshold', 'gimp-context-set-sample-transparent'.
In the case of a merged sampling, the supplied drawable is ignored.
:param image:
:param operation:
:param drawable:
:param color:
:return:
"""
procedure = Gimp.get_pdb().lookup_procedure('gimp-image-select-color')
config = procedure.create_config()
config.set_property('image', image)
config.set_property('operation', operation)
config.set_property('drawable', drawable)
config.set_property('color', color)
result = procedure.run(config)
success = result.index(0)
if not success:
print("select by color failed")
As you can see the pyi module is straight from the browser. If it's not the color itself it must be something with the selection. The more selections i do based on color the more leaks it throws. Everything works as expected it just leaks like a sieve.
When I looked at the stack trace I was wondering if was before the add alpha. Also as mentioned initially, with out the color code, there are no buffer leaks applying the alpha, and scaling the image, it only starts to happen when I create the color and start selecting by it. So I was wondering if this was the part of thee stack trace that was the problem:
'/lib64/libgobject-2.0.so.0(g_type_create_instance+0x271) [0x7f1aac867af1]'
I just tried without converting the alpha channel first and it still happens, so I don't think it's to do with the adding of the alpha layer. New stack:
Quote:Leaked buffer allocation stack trace:
/usr/local/lib64/libgegl-0.4.so.0(+0x4eefa) [0x7fcc4357befa]
/lib64/libgobject-2.0.so.0(g_type_create_instance+0x271) [0x7fcc437a9af1]
/lib64/libgobject-2.0.so.0(+0x1d684) [0x7fcc4378d684]
/usr/local/lib64/libgegl-0.4.so.0(+0x4f2a8) [0x7fcc4357c2a8]
/lib64/libgobject-2.0.so.0(+0x1dc34) [0x7fcc4378dc34]
/lib64/libgobject-2.0.so.0(g_object_new_valist+0x1a7) [0x7fcc437900d7]
/lib64/libgobject-2.0.so.0(g_object_new+0x99) [0x7fcc43790849]
/usr/local/lib64/libgegl-0.4.so.0(gegl_buffer_new+0x68) [0x7fcc4357cc78]
gimp(gimp_drawable_new+0xc3) [0x54e6a3]
gimp(gimp_layer_new+0x84) [0x4ffec4]
gimp(gimp_layer_new_from_gegl_buffer+0xdf) [0x50006f]
gimp(gimp_image_new_from_buffer+0x149) [0x5664e9]
gimp() [0x5cb4e2]
gimp(gimp_procedure_execute+0x1da) [0x6271ba]
gimp(gimp_pdb_execute_procedure_by_name_args+0x159) [0x623cb9]
gimp(gimp_plug_in_handle_message+0x63b) [0x63cc9b]
gimp() [0x62c496]
/lib64/libglib-2.0.so.0(+0x5f638) [0x7fcc43679638]
/lib64/libglib-2.0.so.0(+0x61398) [0x7fcc4367b398]
/lib64/libglib-2.0.so.0(g_main_loop_run+0x77) [0x7fcc4367bdc7]
gimp(gimp_plug_in_manager_call_run+0x6b1) [0x63e2a1]
gimp() [0x6323de]
gimp(gimp_procedure_execute+0x1da) [0x6271ba]
gimp(gimp_pdb_execute_procedure_by_name_args+0x159) [0x623cb9]
gimp(gimp_batch_run+0x1f5) [0x67b8c5]
gimp() [0x67757b]
/lib64/libgobject-2.0.so.0(g_closure_invoke+0x138) [0x7fcc437878f8]
/lib64/libgobject-2.0.so.0(+0x2b5d3) [0x7fcc4379b5d3]
/lib64/libgobject-2.0.so.0(+0x2cfe9) [0x7fcc4379cfe9]
/lib64/libgobject-2.0.so.0(g_signal_emit_valist+0x32) [0x7fcc437a2ad2]
/lib64/libgobject-2.0.so.0(g_signal_emit+0x8f) [0x7fcc437a2b7f]
/lib64/libgio-2.0.so.0(+0xed0a0) [0x7fcc433f20a0]
/lib64/libgio-2.0.so.0(g_application_run+0x107) [0x7fcc433f2237]
gimp(app_run+0x1ea) [0x677aca]
gimp(main+0x365) [0x4bde55]
/lib64/libc.so.6(+0x2b12e) [0x7fcc4202b12e]
/lib64/libc.so.6(__libc_start_main+0x8b) [0x7fcc4202b1f9]
gimp(_start+0x25) [0x4bdfa5]
EEEEeEeek! 17 GeglBuffers leaked
Just tried something different and instantiated new colors each time I needed them and it didn't effect things, so likely not to do with the color either.
So I just tried using the direct api and same result here is my code:
Code:
image = pyi.file_load(r'/windows/projects/5150/Graphic Prefabs for Maps/geomorphs/hi-res/dead_parrot/legend/blank/018.png')
layer = image.get_layers()[0]
color = Gegl.Color.new("black")
image.select_color(Gimp.ChannelOps.REPLACE,layer, color)
image.get_selection().invert(image)
layer.edit_clear()
pyi.file_save(image,r'/windows/projects/5150/Graphic Prefabs for Maps/geomorphs/hi-res/dead_parrot/test/18.png')
pyi.image_delete(image)
As you can see the code is simple but the result was 2 buffer leaks.
|