app, libgimp, libgimpbase, pdb: GimpColorArray as a typedef to…

… NULL-terminated array of GeglColor is now a boxed type usable in PDB.
This commit is contained in:
Jehan 2023-12-27 01:07:19 +09:00
parent cfd0389c37
commit 65f8afee68
13 changed files with 399 additions and 62 deletions

View File

@ -147,27 +147,24 @@ palette_get_colors_invoker (GimpProcedure *procedure,
gboolean success = TRUE;
GimpValueArray *return_vals;
GimpPalette *palette;
gint num_colors = 0;
GimpRGB *colors = NULL;
GeglColor **colors = NULL;
palette = g_value_get_object (gimp_value_array_index (args, 0));
if (success)
{
GList *list = gimp_palette_get_colors (palette);
gint num_colors;
gint i;
num_colors = gimp_palette_get_n_colors (palette);
colors = g_new (GimpRGB, num_colors);
colors = g_new0 (GeglColor *, num_colors + 1);
for (i = 0; i < num_colors; i++, list = g_list_next (list))
{
GimpPaletteEntry *entry = list->data;
GimpRGB rgb;
/* TODO: we need a geglcolorarray type! */
gegl_color_get_pixel (entry->color, babl_format ("R'G'B'A double"), &rgb);
colors[i] = rgb;
colors[i] = gegl_color_duplicate (entry->color);
}
}
@ -175,10 +172,7 @@ palette_get_colors_invoker (GimpProcedure *procedure,
error ? *error : NULL);
if (success)
{
g_value_set_int (gimp_value_array_index (return_vals, 1), num_colors);
gimp_value_take_rgb_array (gimp_value_array_index (return_vals, 2), colors, num_colors);
}
g_value_take_boxed (gimp_value_array_index (return_vals, 1), colors);
return return_vals;
}
@ -558,7 +552,7 @@ register_palette_procs (GimpPDB *pdb)
"gimp-palette-get-colors");
gimp_procedure_set_static_help (procedure,
"Gets colors in the palette.",
"Returns an array of colors in the palette.",
"Returns an array of colors in the palette. Free the returned array with 'gimp-color-array-free'.",
NULL);
gimp_procedure_set_static_attribution (procedure,
"Sven Neumann <sven@gimp.org>",
@ -571,16 +565,11 @@ register_palette_procs (GimpPDB *pdb)
FALSE,
GIMP_PARAM_READWRITE));
gimp_procedure_add_return_value (procedure,
g_param_spec_int ("num-colors",
"num colors",
"Length of the colors array",
0, G_MAXINT32, 0,
GIMP_PARAM_READWRITE));
gimp_procedure_add_return_value (procedure,
gimp_param_spec_rgb_array ("colors",
"colors",
"The colors in the palette",
GIMP_PARAM_READWRITE));
g_param_spec_boxed ("colors",
"colors",
"The colors in the palette",
GIMP_TYPE_COLOR_ARRAY,
GIMP_PARAM_READWRITE));
gimp_pdb_register_procedure (pdb, procedure);
g_object_unref (procedure);

View File

@ -689,6 +689,58 @@ gimp_gp_param_to_value (gpointer gimp,
param->data.d_array.size /
sizeof (GimpRGB));
}
else if (GIMP_VALUE_HOLDS_COLOR_ARRAY (value))
{
GeglColor **colors;
colors = g_new0 (GeglColor *, param->data.d_color_array.size + 1);
for (gint i = 0; i < param->data.d_color_array.size; i++)
{
GeglColor *color;
const Babl *format = NULL;
const Babl *space = NULL;
GimpColorProfile *profile = NULL;
const gchar *encoding;
gint bpp;
encoding = param->data.d_color_array.colors[i].encoding;
if (param->data.d_color_array.colors[i].profile_size > 0)
profile = gimp_color_profile_new_from_icc_profile (param->data.d_color_array.colors[i].profile_data,
param->data.d_color_array.colors[i].profile_size,
NULL);
if (profile)
{
GError *error = NULL;
space = gimp_color_profile_get_space (profile,
GIMP_COLOR_RENDERING_INTENT_RELATIVE_COLORIMETRIC,
&error);
if (! space)
{
g_printerr ("%s: failed to create Babl space from profile: %s\n",
G_STRFUNC, error->message);
g_clear_error (&error);
}
g_object_unref (profile);
}
format = babl_format_with_space (encoding, space);
color = gegl_color_new ("black");
bpp = babl_format_get_bytes_per_pixel (format);
if (bpp != param->data.d_color_array.colors[i].size)
g_printerr ("%s: encoding \"%s\" expects %d bpp but data size is %d bpp.\n",
G_STRFUNC, encoding, bpp, param->data.d_color_array.colors[i].size);
else
gegl_color_set_pixel (color, format, param->data.d_color_array.colors[i].data);
colors[i] = color;
}
g_value_take_boxed (value, colors);
}
else if (GIMP_VALUE_HOLDS_OBJECT_ARRAY (value))
{
GType object_type;
@ -1004,6 +1056,41 @@ gimp_value_to_gp_param (const GValue *value,
param->data.d_array.data = NULL;
}
}
else if (GIMP_VALUE_HOLDS_COLOR_ARRAY (value))
{
GeglColor **colors = g_value_get_boxed (value);
param->param_type = GP_PARAM_TYPE_COLOR_ARRAY;
if (colors != NULL)
{
param->data.d_color_array.size = gimp_color_array_get_length (colors);
param->data.d_color_array.colors = g_new0 (GPParamColor,
param->data.d_color_array.size);
for (gint i = 0; i < param->data.d_color_array.size; i++)
{
const Babl *format;
int icc_length = 0;
format = gegl_color_get_format (colors[i]);
param->data.d_color_array.colors[i].size = babl_format_get_bytes_per_pixel (format);
gegl_color_get_pixel (colors[i], format, &param->data.d_color_array.colors[i].data);
param->data.d_color_array.colors[i].encoding = (gchar *) babl_format_get_encoding (format);
if (babl_format_get_space (format) != babl_space ("sRGB"))
param->data.d_color_array.colors[i].profile_data = (guint8 *) babl_space_get_icc (babl_format_get_space (format),
&icc_length);
param->data.d_gegl_color.profile_size = icc_length;
}
}
else
{
param->data.d_color_array.size = 0;
param->data.d_color_array.colors = NULL;
}
}
else if (G_VALUE_HOLDS (value, G_TYPE_BYTES))
{
GBytes *bytes = g_value_get_boxed (value);
@ -1188,6 +1275,10 @@ _gimp_gp_params_free (GPParam *params,
case GP_PARAM_TYPE_GEGL_COLOR:
break;
case GP_PARAM_TYPE_COLOR_ARRAY:
g_free (params[i].data.d_color_array.colors);
break;
case GP_PARAM_TYPE_ARRAY:
if (full_copy)
g_free (params[i].data.d_array.data);

View File

@ -150,25 +150,23 @@ gimp_palette_get_color_count (GimpPalette *palette)
/**
* gimp_palette_get_colors:
* @palette: The palette.
* @num_colors: (out): Length of the colors array.
*
* Gets colors in the palette.
*
* Returns an array of colors in the palette.
* Returns an array of colors in the palette. Free the returned array
* with gimp_color_array_free().
*
* Returns: (array length=num_colors) (element-type GimpRGB) (transfer full):
* Returns: (array zero-terminated=1) (transfer full):
* The colors in the palette.
* The returned value must be freed with g_free().
*
* Since: 2.6
**/
GimpRGB *
gimp_palette_get_colors (GimpPalette *palette,
gint *num_colors)
GeglColor **
gimp_palette_get_colors (GimpPalette *palette)
{
GimpValueArray *args;
GimpValueArray *return_vals;
GimpRGB *colors = NULL;
GeglColor **colors = NULL;
args = gimp_value_array_new_from_types (NULL,
GIMP_TYPE_PALETTE, palette,
@ -179,13 +177,8 @@ gimp_palette_get_colors (GimpPalette *palette,
args);
gimp_value_array_unref (args);
*num_colors = 0;
if (GIMP_VALUES_GET_ENUM (return_vals, 0) == GIMP_PDB_SUCCESS)
{
*num_colors = GIMP_VALUES_GET_INT (return_vals, 1);
colors = GIMP_VALUES_DUP_RGB_ARRAY (return_vals, 2);
}
colors = gimp_color_array_copy (g_value_get_boxed (gimp_value_array_index (return_vals, 1)));
gimp_value_array_unref (return_vals);

View File

@ -35,8 +35,7 @@ G_BEGIN_DECLS
GimpPalette* gimp_palette_new (const gchar *name);
GimpPalette* gimp_palette_get_by_name (const gchar *name);
gint gimp_palette_get_color_count (GimpPalette *palette);
GimpRGB* gimp_palette_get_colors (GimpPalette *palette,
gint *num_colors);
GeglColor** gimp_palette_get_colors (GimpPalette *palette);
gint gimp_palette_get_columns (GimpPalette *palette);
gboolean gimp_palette_set_columns (GimpPalette *palette,
gint columns);

View File

@ -29,6 +29,10 @@ EXPORTS
gimp_choice_new_with_values
gimp_choice_set_sensitive
gimp_clone_type_get_type
gimp_color_array_copy
gimp_color_array_free
gimp_color_array_get_length
gimp_color_array_get_type
gimp_color_tag_get_type
gimp_component_type_get_type
gimp_convert_palette_type_get_type

View File

@ -20,6 +20,7 @@
#include "config.h"
#include <gegl.h>
#include <glib-object.h>
#include "gimpbasetypes.h"

View File

@ -756,6 +756,87 @@ gimp_value_take_float_array (GValue *value,
length * sizeof (gdouble));
}
/*
* GIMP_TYPE_COLOR_ARRAY
*/
GType
gimp_color_array_get_type (void)
{
static gsize static_g_define_type_id = 0;
if (g_once_init_enter (&static_g_define_type_id))
{
GType g_define_type_id =
g_boxed_type_register_static (g_intern_static_string ("GimpColorArray"),
(GBoxedCopyFunc) gimp_color_array_copy,
(GBoxedFreeFunc) gimp_color_array_free);
g_once_init_leave (&static_g_define_type_id, g_define_type_id);
}
return static_g_define_type_id;
}
/**
* gimp_color_array_copy:
* @array: an array of colors.
*
* Creates a new #GimpColorArray containing a deep copy of a %NULL-terminated
* array of [class@Gegl.Color].
*
* Returns: (transfer full): a new #GimpColorArray.
**/
GimpColorArray
gimp_color_array_copy (GimpColorArray array)
{
GeglColor **copy;
gint length = gimp_color_array_get_length (array);
copy = g_malloc0 (sizeof (GeglColor *) * (length + 1));
for (gint i = 0; i < length; i++)
copy[i] = gegl_color_duplicate (array[i]);
return copy;
}
/**
* gimp_color_array_free:
* @array: an array of colors.
*
* Frees a %NULL-terminated array of [class@Gegl.Color].
**/
void
gimp_color_array_free (GimpColorArray array)
{
gint i = 0;
while (array[i] != NULL)
g_object_unref (array[i++]);
g_free (array);
}
/**
* gimp_color_array_get_length:
* @array: an array of colors.
*
* Returns: the number of [class@Gegl.Color] in @array.
**/
gint
gimp_color_array_get_length (GimpColorArray array)
{
gint length = 0;
while (array[length] != NULL)
length++;
return length;
}
/*
* GIMP_TYPE_RGB_ARRAY
*/

View File

@ -246,6 +246,50 @@ void gimp_value_take_float_array (GValue *value,
gsize length);
/**
* GIMP_TYPE_COLOR_ARRAY:
*
* The #GType for a boxed type holding a %NULL-terminated array of GeglColor.
*
* The code fragments in the following example show the use of a property of
* type %GIMP_TYPE_COLORV with g_object_class_install_property(), g_object_set()
* and g_object_get().
*
* ```C
* g_object_class_install_property (object_class,
* PROP_COLORS,
* g_param_spec_boxed ("colors",
* _("Colors"),
* _("List of colors"),
* GIMP_TYPE_COLOR_ARRAY,
* G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
*
* GeglColor *colors[] = { gegl_color_new ("red"), gegl_color_new ("blue"), NULL };
*
* g_object_set (obj, "colors", colors, NULL);
*
* GeglColors **colors;
*
* g_object_get (obj, "colors", &colors, NULL);
* gimp_color_array_free (colors);
* ```
*
* Since: 3.0
*/
typedef GeglColor** GimpColorArray;
#define GIMP_TYPE_COLOR_ARRAY (gimp_color_array_get_type ())
#define GIMP_VALUE_HOLDS_COLOR_ARRAY(value) (G_TYPE_CHECK_VALUE_TYPE ((value), GIMP_TYPE_COLOR_ARRAY))
GType gimp_color_array_get_type (void) G_GNUC_CONST;
GimpColorArray gimp_color_array_copy (GimpColorArray array);
void gimp_color_array_free (GimpColorArray array);
gint gimp_color_array_get_length (GimpColorArray array);
/*
* GIMP_TYPE_RGB_ARRAY
*/

View File

@ -18,6 +18,7 @@
#include "config.h"
#include <gegl.h>
#include <glib-object.h>
#include "gimpbasetypes.h"
@ -1778,6 +1779,97 @@ _gp_params_read (GIOChannel *channel,
break;
case GP_PARAM_TYPE_COLOR_ARRAY:
if (! _gimp_wire_read_int32 (channel,
&(*params)[i].data.d_color_array.size, 1,
user_data))
goto cleanup;
(*params)[i].data.d_color_array.colors = g_new0 (GPParamColor,
(*params)[i].data.d_color_array.size);
for (gint j = 0; j < (*params)[i].data.d_color_array.size; j++)
{
/* Read the color data. */
if (! _gimp_wire_read_int32 (channel,
&(*params)[i].data.d_color_array.colors[j].size, 1,
user_data))
{
for (gint k = 0; k < j; j++)
{
g_free ((*params)[i].data.d_color_array.colors[k].encoding);
g_free ((*params)[i].data.d_color_array.colors[k].profile_data);
}
g_clear_pointer (&(*params)[i].data.d_color_array.colors, g_free);
goto cleanup;
}
if ((*params)[i].data.d_color_array.colors[j].size > 40 ||
! _gimp_wire_read_int8 (channel,
(*params)[i].data.d_color_array.colors[j].data,
(*params)[i].data.d_color_array.colors[j].size,
user_data))
{
for (gint k = 0; k < j; j++)
{
g_free ((*params)[i].data.d_color_array.colors[k].encoding);
g_free ((*params)[i].data.d_color_array.colors[k].profile_data);
}
g_clear_pointer (&(*params)[i].data.d_color_array.colors, g_free);
goto cleanup;
}
/* Read encoding. */
if (! _gimp_wire_read_string (channel,
&(*params)[i].data.d_color_array.colors[j].encoding, 1,
user_data))
{
for (gint k = 0; k < j; j++)
{
g_free ((*params)[i].data.d_color_array.colors[k].encoding);
g_free ((*params)[i].data.d_color_array.colors[k].profile_data);
}
g_clear_pointer (&(*params)[i].data.d_color_array.colors, g_free);
goto cleanup;
}
/* Read space (profile data). */
if (! _gimp_wire_read_int32 (channel,
&(*params)[i].data.d_color_array.colors[j].profile_size, 1,
user_data))
{
for (gint k = 0; k < j; j++)
{
g_free ((*params)[i].data.d_color_array.colors[k].encoding);
g_free ((*params)[i].data.d_color_array.colors[k].profile_data);
}
g_clear_pointer (&(*params)[i].data.d_color_array.colors[j].encoding, g_free);
g_clear_pointer (&(*params)[i].data.d_color_array.colors, g_free);
goto cleanup;
}
if ((*params)[i].data.d_color_array.colors[j].profile_size > 0)
{
(*params)[i].data.d_color_array.colors[j].profile_data = g_new0 (guint8, (*params)[i].data.d_color_array.colors[j].profile_size);
if (! _gimp_wire_read_int8 (channel,
(*params)[i].data.d_color_array.colors[j].profile_data,
(*params)[i].data.d_color_array.colors[j].profile_size,
user_data))
{
for (gint k = 0; k < j; j++)
{
g_free ((*params)[i].data.d_color_array.colors[k].encoding);
g_free ((*params)[i].data.d_color_array.colors[k].profile_data);
}
g_clear_pointer (&(*params)[i].data.d_color_array.colors[j].encoding, g_free);
g_clear_pointer (&(*params)[i].data.d_color_array.colors[j].profile_data, g_free);
g_clear_pointer (&(*params)[i].data.d_color_array.colors, g_free);
goto cleanup;
}
}
}
break;
case GP_PARAM_TYPE_ARRAY:
if (! _gimp_wire_read_int32 (channel,
&(*params)[i].data.d_array.size, 1,
@ -1993,6 +2085,35 @@ _gp_params_write (GIOChannel *channel,
return;
break;
case GP_PARAM_TYPE_COLOR_ARRAY:
if (! _gimp_wire_write_int32 (channel,
(const guint32 *) &params[i].data.d_color_array.size, 1,
user_data))
return;
for (gint j = 0; j < params[i].data.d_color_array.size; j++)
{
if (! _gimp_wire_write_int32 (channel,
(const guint32 *) &params[i].data.d_color_array.colors[j].size, 1,
user_data) ||
! _gimp_wire_write_int8 (channel,
(const guint8 *) params[i].data.d_color_array.colors[j].data,
params[i].data.d_color_array.colors[j].size,
user_data) ||
! _gimp_wire_write_string (channel,
&params[i].data.d_color_array.colors[j].encoding, 1,
user_data) ||
! _gimp_wire_write_int32 (channel,
(const guint32 *) &params[i].data.d_color_array.colors[j].profile_size, 1,
user_data) ||
! _gimp_wire_write_int8 (channel,
(const guint8 *) params[i].data.d_color_array.colors[j].profile_data,
params[i].data.d_color_array.colors[j].profile_size,
user_data))
return;
}
break;
case GP_PARAM_TYPE_ARRAY:
if (! _gimp_wire_write_int32 (channel,
(const guint32 *) &params[i].data.d_array.size, 1,
@ -2120,6 +2241,15 @@ _gp_params_destroy (GPParam *params,
g_free (params[i].data.d_gegl_color.profile_data);
break;
case GP_PARAM_TYPE_COLOR_ARRAY:
for (gint j = 0; j < params[i].data.d_color_array.size; j++)
{
g_free (params[i].data.d_color_array.colors[j].encoding);
g_free (params[i].data.d_color_array.colors[j].profile_data);
}
g_free (params[i].data.d_color_array.colors);
break;
case GP_PARAM_TYPE_ARRAY:
g_free (params[i].data.d_array.data);
break;

View File

@ -71,6 +71,7 @@ typedef enum
GP_PARAM_TYPE_FILE,
GP_PARAM_TYPE_COLOR,
GP_PARAM_TYPE_GEGL_COLOR,
GP_PARAM_TYPE_COLOR_ARRAY,
GP_PARAM_TYPE_PARASITE,
GP_PARAM_TYPE_ARRAY,
GP_PARAM_TYPE_ID_ARRAY,
@ -98,6 +99,7 @@ typedef struct _GPParam GPParam;
typedef struct _GPParamArray GPParamArray;
typedef struct _GPParamIDArray GPParamIDArray;
typedef struct _GPParamColor GPParamColor;
typedef struct _GPParamColorArray GPParamColorArray;
typedef struct _GPProcRun GPProcRun;
typedef struct _GPProcReturn GPProcReturn;
typedef struct _GPProcInstall GPProcInstall;
@ -271,6 +273,12 @@ struct _GPParamColor
guint8 *profile_data;
};
struct _GPParamColorArray
{
guint32 size;
GPParamColor *colors;
};
struct _GPParam
{
GPParamType param_type;
@ -284,6 +292,7 @@ struct _GPParam
gchar **d_strv;
GBytes *d_bytes;
GPParamColor d_gegl_color;
GPParamColorArray d_color_array;
GimpRGB d_color;
GimpParasite d_parasite;
GPParamArray d_array;

View File

@ -654,10 +654,11 @@ CODE
}
elsif ($pdbtype eq 'colorarray') {
$pspec = <<CODE;
gimp_param_spec_rgb_array ("$name",
"$nick",
"$blurb",
$flags)
g_param_spec_boxed ("$name",
"$nick",
"$blurb",
GIMP_TYPE_COLOR_ARRAY,
$flags)
CODE
}
elsif ($pdbtype eq 'imagearray') {

View File

@ -111,7 +111,7 @@ CODE
sub palette_get_colors {
$blurb = 'Gets colors in the palette.';
$help = "Returns an array of colors in the palette.";
$help = "Returns an array of colors in the palette. Free the returned array with gimp_color_array_free().";
&neo_pdb_misc('2006', '2.6');
@ -121,28 +121,24 @@ sub palette_get_colors {
@outargs = (
{ name => 'colors', type => 'colorarray',
desc => 'The colors in the palette',
array => { name => 'num_colors',
desc => 'Length of the colors array' } }
desc => 'The colors in the palette' }
);
%invoke = (
code => <<'CODE'
{
GList *list = gimp_palette_get_colors (palette);
gint num_colors;
gint i;
num_colors = gimp_palette_get_n_colors (palette);
colors = g_new (GimpRGB, num_colors);
colors = g_new0 (GeglColor *, num_colors + 1);
for (i = 0; i < num_colors; i++, list = g_list_next (list))
{
GimpPaletteEntry *entry = list->data;
GimpRGB rgb;
/* TODO: we need a geglcolorarray type! */
gegl_color_get_pixel (entry->color, babl_format ("R'G'B'A double"), &rgb);
colors[i] = rgb;
colors[i] = gegl_color_duplicate (entry->color);
}
}
CODE

View File

@ -107,18 +107,17 @@ package Gimp::CodeGen::pdb;
set_value_func => 'gimp_value_set_float_array ($value, $var, $var_len)',
take_value_func => 'gimp_value_take_float_array ($value, $var, $var_len)' },
colorarray => { name => 'COLORARRAY',
gtype => 'GIMP_TYPE_RGB_ARRAY',
type => 'GimpRGB *',
const_type => 'const GimpRGB *',
array => 1,
colorarray => { name => 'COLOR_ARRAY',
gtype => 'GIMP_TYPE_COLOR_ARRAY',
type => 'GeglColor **',
const_type => 'const GeglColor **',
init_value => 'NULL',
in_annotate => '(element-type GimpRGB)',
out_annotate => '(element-type GimpRGB) (transfer full)',
get_value_func => '$var = gimp_value_get_rgb_array ($value)',
dup_value_func => '$var = GIMP_VALUES_DUP_RGB_ARRAY ($value)',
set_value_func => 'gimp_value_set_rgb_array ($value, $var, $var_len)',
take_value_func => 'gimp_value_take_rgb_array ($value, $var, $var_len)' },
in_annotate => '(array zero-terminated=1)',
out_annotate => '(array zero-terminated=1) (transfer full)',
get_value_func => '$var = g_value_get_boxed ($value)',
dup_value_func => '$var = gimp_color_array_copy (g_value_get_boxed (gimp_value_array_index ($value)))',
set_value_func => 'g_value_set_boxed ($value, $var)',
take_value_func => 'g_value_take_boxed ($value, $var)' },
imagearray => { name => 'IMAGEARRAY',
gtype => 'GIMP_TYPE_OBJECT_ARRAY',