Issue #9790: reimplement gimp_drawable_[gs]et_pixel().

These 2 functions were removed in commit 89c359ce. They were in fact used and
clearly this historical API seems interesting (though we can likely do the same
thing using the drawable GeglBuffer, but this way is much easier).

This is now reimplemented using GeglColor instead of raw data.
This commit is contained in:
Jehan 2023-11-03 21:42:11 +01:00
parent 7814f011d0
commit 75efbf77d3
6 changed files with 364 additions and 1 deletions

View File

@ -120,6 +120,97 @@ drawable_get_thumbnail_format_invoker (GimpProcedure *procedure,
return return_vals;
}
static GimpValueArray *
drawable_get_pixel_invoker (GimpProcedure *procedure,
Gimp *gimp,
GimpContext *context,
GimpProgress *progress,
const GimpValueArray *args,
GError **error)
{
gboolean success = TRUE;
GimpValueArray *return_vals;
GimpDrawable *drawable;
gint x_coord;
gint y_coord;
GeglColor *color = NULL;
drawable = g_value_get_object (gimp_value_array_index (args, 0));
x_coord = g_value_get_int (gimp_value_array_index (args, 1));
y_coord = g_value_get_int (gimp_value_array_index (args, 2));
if (success)
{
const Babl *format = gimp_drawable_get_format (drawable);
if (x_coord < gimp_item_get_width (GIMP_ITEM (drawable)) &&
y_coord < gimp_item_get_height (GIMP_ITEM (drawable)))
{
gint n_bytes = babl_format_get_bytes_per_pixel (format);
gpointer pixel;
pixel = g_malloc0 (n_bytes);
gegl_buffer_sample (gimp_drawable_get_buffer (drawable),
x_coord, y_coord, NULL, pixel, format,
GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE);
color = gegl_color_new ("black");
gegl_color_set_pixel (color, format, pixel);
g_free (pixel);
}
else
success = FALSE;
}
return_vals = gimp_procedure_get_return_values (procedure, success,
error ? *error : NULL);
if (success)
g_value_take_object (gimp_value_array_index (return_vals, 1), color);
return return_vals;
}
static GimpValueArray *
drawable_set_pixel_invoker (GimpProcedure *procedure,
Gimp *gimp,
GimpContext *context,
GimpProgress *progress,
const GimpValueArray *args,
GError **error)
{
gboolean success = TRUE;
GimpDrawable *drawable;
gint x_coord;
gint y_coord;
GeglColor *color;
drawable = g_value_get_object (gimp_value_array_index (args, 0));
x_coord = g_value_get_int (gimp_value_array_index (args, 1));
y_coord = g_value_get_int (gimp_value_array_index (args, 2));
color = g_value_get_object (gimp_value_array_index (args, 3));
if (success)
{
if (gimp_pdb_item_is_modifiable (GIMP_ITEM (drawable),
GIMP_PDB_ITEM_CONTENT, error) &&
gimp_pdb_item_is_not_group (GIMP_ITEM (drawable), error) &&
x_coord < gimp_item_get_width (GIMP_ITEM (drawable)) &&
y_coord < gimp_item_get_height (GIMP_ITEM (drawable)))
{
gegl_buffer_set_color (gimp_drawable_get_buffer (drawable),
GEGL_RECTANGLE (x_coord, y_coord, 1, 1),
color);
}
else
success = FALSE;
}
return gimp_procedure_get_return_values (procedure, success,
error ? *error : NULL);
}
static GimpValueArray *
drawable_type_invoker (GimpProcedure *procedure,
Gimp *gimp,
@ -966,6 +1057,88 @@ register_drawable_procs (GimpPDB *pdb)
gimp_pdb_register_procedure (pdb, procedure);
g_object_unref (procedure);
/*
* gimp-drawable-get-pixel
*/
procedure = gimp_procedure_new (drawable_get_pixel_invoker);
gimp_object_set_static_name (GIMP_OBJECT (procedure),
"gimp-drawable-get-pixel");
gimp_procedure_set_static_help (procedure,
"Gets the value of the pixel at the specified coordinates.",
"This procedure gets the pixel value at the specified coordinates.",
NULL);
gimp_procedure_set_static_attribution (procedure,
"Spencer Kimball & Peter Mattis",
"Spencer Kimball & Peter Mattis",
"1997");
gimp_procedure_add_argument (procedure,
gimp_param_spec_drawable ("drawable",
"drawable",
"The drawable",
FALSE,
GIMP_PARAM_READWRITE));
gimp_procedure_add_argument (procedure,
g_param_spec_int ("x-coord",
"x coord",
"The x coordinate",
0, G_MAXINT32, 0,
GIMP_PARAM_READWRITE));
gimp_procedure_add_argument (procedure,
g_param_spec_int ("y-coord",
"y coord",
"The y coordinate",
0, G_MAXINT32, 0,
GIMP_PARAM_READWRITE));
gimp_procedure_add_return_value (procedure,
gegl_param_spec_color ("color",
"color",
"The pixel color",
NULL,
GIMP_PARAM_READWRITE));
gimp_pdb_register_procedure (pdb, procedure);
g_object_unref (procedure);
/*
* gimp-drawable-set-pixel
*/
procedure = gimp_procedure_new (drawable_set_pixel_invoker);
gimp_object_set_static_name (GIMP_OBJECT (procedure),
"gimp-drawable-set-pixel");
gimp_procedure_set_static_help (procedure,
"Sets the value of the pixel at the specified coordinates.",
"This procedure sets the pixel value at the specified coordinates. Note that this function is not undoable, you should use it only on drawables you just created yourself.",
NULL);
gimp_procedure_set_static_attribution (procedure,
"Spencer Kimball & Peter Mattis",
"Spencer Kimball & Peter Mattis",
"1997");
gimp_procedure_add_argument (procedure,
gimp_param_spec_drawable ("drawable",
"drawable",
"The drawable",
FALSE,
GIMP_PARAM_READWRITE));
gimp_procedure_add_argument (procedure,
g_param_spec_int ("x-coord",
"x coord",
"The x coordinate",
0, G_MAXINT32, 0,
GIMP_PARAM_READWRITE));
gimp_procedure_add_argument (procedure,
g_param_spec_int ("y-coord",
"y coord",
"The y coordinate",
0, G_MAXINT32, 0,
GIMP_PARAM_READWRITE));
gimp_procedure_add_argument (procedure,
gegl_param_spec_color ("color",
"color",
"The pixel color",
NULL,
GIMP_PARAM_READWRITE));
gimp_pdb_register_procedure (pdb, procedure);
g_object_unref (procedure);
/*
* gimp-drawable-type
*/

View File

@ -30,7 +30,7 @@
#include "internal-procs.h"
/* 782 procedures registered total */
/* 784 procedures registered total */
void
internal_procs_init (GimpPDB *pdb)

View File

@ -217,6 +217,7 @@ EXPORTS
gimp_drawable_get_format
gimp_drawable_get_height
gimp_drawable_get_offsets
gimp_drawable_get_pixel
gimp_drawable_get_shadow_buffer
gimp_drawable_get_sub_thumbnail
gimp_drawable_get_sub_thumbnail_data
@ -240,6 +241,7 @@ EXPORTS
gimp_drawable_merge_shadow
gimp_drawable_offset
gimp_drawable_posterize
gimp_drawable_set_pixel
gimp_drawable_shadows_highlights
gimp_drawable_threshold
gimp_drawable_type

View File

@ -115,6 +115,90 @@ _gimp_drawable_get_thumbnail_format (GimpDrawable *drawable)
return format;
}
/**
* gimp_drawable_get_pixel:
* @drawable: The drawable.
* @x_coord: The x coordinate.
* @y_coord: The y coordinate.
*
* Gets the value of the pixel at the specified coordinates.
*
* This procedure gets the pixel value at the specified coordinates.
*
* Returns: (transfer full): The pixel color.
**/
GeglColor *
gimp_drawable_get_pixel (GimpDrawable *drawable,
gint x_coord,
gint y_coord)
{
GimpValueArray *args;
GimpValueArray *return_vals;
GeglColor *color = NULL;
args = gimp_value_array_new_from_types (NULL,
GIMP_TYPE_DRAWABLE, drawable,
G_TYPE_INT, x_coord,
G_TYPE_INT, y_coord,
G_TYPE_NONE);
return_vals = _gimp_pdb_run_procedure_array (gimp_get_pdb (),
"gimp-drawable-get-pixel",
args);
gimp_value_array_unref (args);
if (GIMP_VALUES_GET_ENUM (return_vals, 0) == GIMP_PDB_SUCCESS)
color = g_value_dup_object (gimp_value_array_index (return_vals, 1));
gimp_value_array_unref (return_vals);
return color;
}
/**
* gimp_drawable_set_pixel:
* @drawable: The drawable.
* @x_coord: The x coordinate.
* @y_coord: The y coordinate.
* @color: The pixel color.
*
* Sets the value of the pixel at the specified coordinates.
*
* This procedure sets the pixel value at the specified coordinates.
* Note that this function is not undoable, you should use it only on
* drawables you just created yourself.
*
* Returns: TRUE on success.
**/
gboolean
gimp_drawable_set_pixel (GimpDrawable *drawable,
gint x_coord,
gint y_coord,
GeglColor *color)
{
GimpValueArray *args;
GimpValueArray *return_vals;
gboolean success = TRUE;
args = gimp_value_array_new_from_types (NULL,
GIMP_TYPE_DRAWABLE, drawable,
G_TYPE_INT, x_coord,
G_TYPE_INT, y_coord,
GEGL_TYPE_COLOR, color,
G_TYPE_NONE);
return_vals = _gimp_pdb_run_procedure_array (gimp_get_pdb (),
"gimp-drawable-set-pixel",
args);
gimp_value_array_unref (args);
success = GIMP_VALUES_GET_ENUM (return_vals, 0) == GIMP_PDB_SUCCESS;
gimp_value_array_unref (return_vals);
return success;
}
/**
* gimp_drawable_type:
* @drawable: The drawable.

View File

@ -34,6 +34,13 @@ G_BEGIN_DECLS
G_GNUC_INTERNAL gchar* _gimp_drawable_get_format (GimpDrawable *drawable);
G_GNUC_INTERNAL gchar* _gimp_drawable_get_thumbnail_format (GimpDrawable *drawable);
GeglColor* gimp_drawable_get_pixel (GimpDrawable *drawable,
gint x_coord,
gint y_coord);
gboolean gimp_drawable_set_pixel (GimpDrawable *drawable,
gint x_coord,
gint y_coord,
GeglColor *color);
GimpImageType gimp_drawable_type (GimpDrawable *drawable);
GimpImageType gimp_drawable_type_with_alpha (GimpDrawable *drawable);
gboolean gimp_drawable_has_alpha (GimpDrawable *drawable);

View File

@ -16,6 +16,101 @@
# "Perlized" from C source by Manish Singh <yosh@gimp.org>
sub drawable_get_pixel {
$blurb = 'Gets the value of the pixel at the specified coordinates.';
$help = <<'HELP';
This procedure gets the pixel value at the specified coordinates.
HELP
&std_pdb_misc;
$date = '1997';
@inargs = (
{ name => 'drawable', type => 'drawable',
desc => 'The drawable' },
{ name => 'x_coord', type => '0 <= int32',
desc => 'The x coordinate' },
{ name => 'y_coord', type => '0 <= int32',
desc => 'The y coordinate' }
);
@outargs = (
{ name => 'color', type => 'geglcolor',
desc => 'The pixel color' }
);
%invoke = (
code => <<'CODE'
{
const Babl *format = gimp_drawable_get_format (drawable);
if (x_coord < gimp_item_get_width (GIMP_ITEM (drawable)) &&
y_coord < gimp_item_get_height (GIMP_ITEM (drawable)))
{
gint n_bytes = babl_format_get_bytes_per_pixel (format);
gpointer pixel;
pixel = g_malloc0 (n_bytes);
gegl_buffer_sample (gimp_drawable_get_buffer (drawable),
x_coord, y_coord, NULL, pixel, format,
GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE);
color = gegl_color_new ("black");
gegl_color_set_pixel (color, format, pixel);
g_free (pixel);
}
else
success = FALSE;
}
CODE
);
}
sub drawable_set_pixel {
$blurb = 'Sets the value of the pixel at the specified coordinates.';
$help = <<'HELP';
This procedure sets the pixel value at the specified coordinates.
Note that this function is not undoable, you should use it only on drawables you
just created yourself.
HELP
&std_pdb_misc;
$date = '1997';
@inargs = (
{ name => 'drawable', type => 'drawable',
desc => 'The drawable' },
{ name => 'x_coord', type => '0 <= int32',
desc => 'The x coordinate' },
{ name => 'y_coord', type => '0 <= int32',
desc => 'The y coordinate' },
{ name => 'color', type => 'geglcolor',
desc => 'The pixel color' }
);
%invoke = (
code => <<'CODE'
{
if (gimp_pdb_item_is_modifiable (GIMP_ITEM (drawable),
GIMP_PDB_ITEM_CONTENT, error) &&
gimp_pdb_item_is_not_group (GIMP_ITEM (drawable), error) &&
x_coord < gimp_item_get_width (GIMP_ITEM (drawable)) &&
y_coord < gimp_item_get_height (GIMP_ITEM (drawable)))
{
gegl_buffer_set_color (gimp_drawable_get_buffer (drawable),
GEGL_RECTANGLE (x_coord, y_coord, 1, 1),
color);
}
else
success = FALSE;
}
CODE
);
}
sub drawable_merge_filters {
$blurb = 'Merge the layer effect filters to the specified drawable.';
@ -941,6 +1036,8 @@ CODE
@procs = qw(drawable_get_format
drawable_get_thumbnail_format
drawable_get_pixel
drawable_set_pixel
drawable_type
drawable_type_with_alpha
drawable_has_alpha