app, libgimp, pdb, plug-ins: gimp_gradient_get_uniform_samples() returns an array of GeglColor.

This commit is contained in:
Jehan 2024-11-03 13:12:33 +01:00
parent 9b23c35c30
commit 6327d1b3ef
12 changed files with 147 additions and 177 deletions

View File

@ -456,8 +456,8 @@ gimp_gradient_get_extension (GimpData *data)
* @blend_color_space: color space to use for blending RGB segments * @blend_color_space: color space to use for blending RGB segments
* @color: returns a newly allocated color * @color: returns a newly allocated color
* *
* If you are iterating over an gradient, you should pass the the * If you are iterating over an gradient, you should pass the return
* return value from the last call for @seg. * value from the last call for @seg.
* *
* Returns: the gradient segment the color is from * Returns: the gradient segment the color is from
**/ **/

View File

@ -160,8 +160,7 @@ gradient_get_uniform_samples_invoker (GimpProcedure *procedure,
GimpGradient *gradient; GimpGradient *gradient;
gint num_samples; gint num_samples;
gboolean reverse; gboolean reverse;
gsize num_color_samples = 0; GeglColor **color_samples = NULL;
gdouble *color_samples = NULL;
gradient = g_value_get_object (gimp_value_array_index (args, 0)); gradient = g_value_get_object (gimp_value_array_index (args, 0));
num_samples = g_value_get_int (gimp_value_array_index (args, 1)); num_samples = g_value_get_int (gimp_value_array_index (args, 1));
@ -174,30 +173,19 @@ gradient_get_uniform_samples_invoker (GimpProcedure *procedure,
GimpGradientSegment *seg = NULL; GimpGradientSegment *seg = NULL;
gdouble pos = 0.0; gdouble pos = 0.0;
gdouble delta = 1.0 / (num_samples - 1); gdouble delta = 1.0 / (num_samples - 1);
gdouble *sample; GeglColor **sample;
num_color_samples = num_samples * 4; sample = color_samples = g_new0 (GeglColor *, num_samples + 1);
sample = color_samples = g_new0 (gdouble, num_color_samples);
while (num_samples--) while (num_samples--)
{ {
GeglColor *color = NULL;
seg = gimp_gradient_get_color_at (gradient, context, seg, seg = gimp_gradient_get_color_at (gradient, context, seg,
pos, reverse, pos, reverse,
GIMP_GRADIENT_BLEND_RGB_PERCEPTUAL, GIMP_GRADIENT_BLEND_RGB_PERCEPTUAL,
&color); sample);
if (color)
gegl_color_get_pixel (color, babl_format ("R'G'B'A double"), sample);
/* TODO: should we really return a list of floats? What about a list
* of GeglColor?
*/
sample += 4; sample++,
pos += delta; pos += delta;
g_clear_object (&color);
} }
} }
else else
@ -208,7 +196,7 @@ gradient_get_uniform_samples_invoker (GimpProcedure *procedure,
error ? *error : NULL); error ? *error : NULL);
if (success) if (success)
gimp_value_take_double_array (gimp_value_array_index (return_vals, 1), color_samples, num_color_samples); g_value_take_boxed (gimp_value_array_index (return_vals, 1), color_samples);
return return_vals; return return_vals;
} }
@ -1353,7 +1341,7 @@ register_gradient_procs (GimpPDB *pdb)
"gimp-gradient-get-uniform-samples"); "gimp-gradient-get-uniform-samples");
gimp_procedure_set_static_help (procedure, gimp_procedure_set_static_help (procedure,
"Sample the gradient in uniform parts.", "Sample the gradient in uniform parts.",
"Samples colors uniformly across the gradient. It returns a list of floating-point values which correspond to the RGBA values for each sample. The minimum number of samples to take is 2, in which case the returned colors will correspond to the { 0.0, 1.0 } positions in the gradient. For example, if the number of samples is 3, the procedure will return the colors at positions { 0.0, 0.5, 1.0 }.", "Samples colors uniformly across the gradient. It returns a list of colors for each sample. The minimum number of samples to take is 2, in which case the returned colors will correspond to the `{ 0.0, 1.0 }` positions in the gradient. For example, if the number of samples is 3, the procedure will return the colors at positions `{ 0.0, 0.5, 1.0 }`.",
NULL); NULL);
gimp_procedure_set_static_attribution (procedure, gimp_procedure_set_static_attribution (procedure,
"Federico Mena Quintero", "Federico Mena Quintero",
@ -1380,10 +1368,11 @@ register_gradient_procs (GimpPDB *pdb)
FALSE, FALSE,
GIMP_PARAM_READWRITE)); GIMP_PARAM_READWRITE));
gimp_procedure_add_return_value (procedure, gimp_procedure_add_return_value (procedure,
gimp_param_spec_double_array ("color-samples", g_param_spec_boxed ("color-samples",
"color samples", "color samples",
"Color samples: { R1, G1, B1, A1, ..., Rn, Gn, Bn, An }", "Color samples",
GIMP_PARAM_READWRITE)); GIMP_TYPE_COLOR_ARRAY,
GIMP_PARAM_READWRITE));
gimp_pdb_register_procedure (pdb, procedure); gimp_pdb_register_procedure (pdb, procedure);
g_object_unref (procedure); g_object_unref (procedure);

View File

@ -150,32 +150,29 @@ gimp_gradient_get_number_of_segments (GimpGradient *gradient)
* @gradient: The gradient. * @gradient: The gradient.
* @num_samples: The number of samples to take. * @num_samples: The number of samples to take.
* @reverse: Use the reverse gradient. * @reverse: Use the reverse gradient.
* @num_color_samples: (out): Length of the color_samples array (4 * num_samples).
* @color_samples: (out) (array length=num_color_samples) (element-type gdouble) (transfer full): Color samples: { R1, G1, B1, A1, ..., Rn, Gn, Bn, An }.
* *
* Sample the gradient in uniform parts. * Sample the gradient in uniform parts.
* *
* Samples colors uniformly across the gradient. It returns a list of * Samples colors uniformly across the gradient. It returns a list of
* floating-point values which correspond to the RGBA values for each * colors for each sample. The minimum number of samples to take is 2,
* sample. The minimum number of samples to take is 2, in which case * in which case the returned colors will correspond to the `{ 0.0, 1.0
* the returned colors will correspond to the { 0.0, 1.0 } positions in * }` positions in the gradient. For example, if the number of samples
* the gradient. For example, if the number of samples is 3, the * is 3, the procedure will return the colors at positions `{ 0.0, 0.5,
* procedure will return the colors at positions { 0.0, 0.5, 1.0 }. * 1.0 }`.
* *
* Returns: TRUE on success. * Returns: (array zero-terminated=1) (transfer full): Color samples.
* The returned value must be freed with gimp_color_array_free().
* *
* Since: 2.2 * Since: 2.2
**/ **/
gboolean GeglColor **
gimp_gradient_get_uniform_samples (GimpGradient *gradient, gimp_gradient_get_uniform_samples (GimpGradient *gradient,
gint num_samples, gint num_samples,
gboolean reverse, gboolean reverse)
gsize *num_color_samples,
gdouble **color_samples)
{ {
GimpValueArray *args; GimpValueArray *args;
GimpValueArray *return_vals; GimpValueArray *return_vals;
gboolean success = TRUE; GeglColor **color_samples = NULL;
args = gimp_value_array_new_from_types (NULL, args = gimp_value_array_new_from_types (NULL,
GIMP_TYPE_GRADIENT, gradient, GIMP_TYPE_GRADIENT, gradient,
@ -188,19 +185,12 @@ gimp_gradient_get_uniform_samples (GimpGradient *gradient,
args); args);
gimp_value_array_unref (args); gimp_value_array_unref (args);
*num_color_samples = 0; if (GIMP_VALUES_GET_ENUM (return_vals, 0) == GIMP_PDB_SUCCESS)
*color_samples = NULL; color_samples = gimp_color_array_copy (g_value_get_boxed (gimp_value_array_index (return_vals, 1)));
success = GIMP_VALUES_GET_ENUM (return_vals, 0) == GIMP_PDB_SUCCESS;
if (success)
{
*color_samples = GIMP_VALUES_DUP_DOUBLE_ARRAY (return_vals, 1, num_color_samples);
}
gimp_value_array_unref (return_vals); gimp_value_array_unref (return_vals);
return success; return color_samples;
} }
/** /**

View File

@ -35,11 +35,9 @@ G_BEGIN_DECLS
GimpGradient* gimp_gradient_new (const gchar *name); GimpGradient* gimp_gradient_new (const gchar *name);
GimpGradient* gimp_gradient_get_by_name (const gchar *name); GimpGradient* gimp_gradient_get_by_name (const gchar *name);
gint gimp_gradient_get_number_of_segments (GimpGradient *gradient); gint gimp_gradient_get_number_of_segments (GimpGradient *gradient);
gboolean gimp_gradient_get_uniform_samples (GimpGradient *gradient, GeglColor** gimp_gradient_get_uniform_samples (GimpGradient *gradient,
gint num_samples, gint num_samples,
gboolean reverse, gboolean reverse);
gsize *num_color_samples,
gdouble **color_samples);
gboolean gimp_gradient_get_custom_samples (GimpGradient *gradient, gboolean gimp_gradient_get_custom_samples (GimpGradient *gradient,
gsize num_samples, gsize num_samples,
const gdouble *positions, const gdouble *positions,

View File

@ -216,21 +216,27 @@ get_gradient_data (GimpGradient *gradient,
gsize *sample_count, gsize *sample_count,
gdouble **sample_array) gdouble **sample_array)
{ {
gboolean result; gboolean result = FALSE;
gdouble *samples; GeglColor **samples;
gsize n_samples;
result = gimp_gradient_get_uniform_samples (gradient, samples = gimp_gradient_get_uniform_samples (gradient, allocation_width,
allocation_width, FALSE /* not reversed. */);
FALSE, /* not reversed. */
&n_samples,
&samples);
if (result) if (samples)
{ {
gdouble *dsamples;
/* Return array of samples to dereferenced handles. */ /* Return array of samples to dereferenced handles. */
*sample_array = samples; *sample_count = gimp_color_array_get_length (samples);;
*sample_count = n_samples; *sample_array = dsamples = g_new0 (gdouble, *sample_count * 4);
for (gint i = 0; samples[i] != NULL; i++)
{
gegl_color_get_pixel (samples[i], babl_format ("R'G'B'A double"), dsamples);
dsamples += 4;
}
gimp_color_array_free (samples);
result = TRUE;
} }
/* When result is true, caller must free the array. */ /* When result is true, caller must free the array. */

View File

@ -137,11 +137,11 @@ sub gradient_get_uniform_samples {
$blurb = 'Sample the gradient in uniform parts.'; $blurb = 'Sample the gradient in uniform parts.';
$help = <<'HELP'; $help = <<'HELP';
Samples colors uniformly across the gradient. It returns a list of floating-point values Samples colors uniformly across the gradient. It returns a list of
which correspond to the RGBA values for each sample. The minimum number of colors for each sample. The minimum number of samples to take is 2, in
samples to take is 2, in which case the returned colors will correspond to the which case the returned colors will correspond to the `{ 0.0, 1.0 }`
{ 0.0, 1.0 } positions in the gradient. For example, if the number of samples positions in the gradient. For example, if the number of samples is 3,
is 3, the procedure will return the colors at positions { 0.0, 0.5, 1.0 }. the procedure will return the colors at positions `{ 0.0, 0.5, 1.0 }`.
HELP HELP
&federico_pdb_misc('1997', '2.2'); &federico_pdb_misc('1997', '2.2');
@ -155,10 +155,8 @@ HELP
); );
@outargs = ( @outargs = (
{ name => 'color_samples', type => 'doublearray', void_ret => 1, { name => 'color_samples', type => 'colorarray',
desc => 'Color samples: { R1, G1, B1, A1, ..., Rn, Gn, Bn, An }', desc => 'Color samples' }
array => { desc => 'Length of the color_samples array (4 *
num_samples)' } }
); );
%invoke = ( %invoke = (
@ -169,30 +167,19 @@ HELP
GimpGradientSegment *seg = NULL; GimpGradientSegment *seg = NULL;
gdouble pos = 0.0; gdouble pos = 0.0;
gdouble delta = 1.0 / (num_samples - 1); gdouble delta = 1.0 / (num_samples - 1);
gdouble *sample; GeglColor **sample;
num_color_samples = num_samples * 4; sample = color_samples = g_new0 (GeglColor *, num_samples + 1);
sample = color_samples = g_new0 (gdouble, num_color_samples);
while (num_samples--) while (num_samples--)
{ {
GeglColor *color = NULL;
seg = gimp_gradient_get_color_at (gradient, context, seg, seg = gimp_gradient_get_color_at (gradient, context, seg,
pos, reverse, pos, reverse,
GIMP_GRADIENT_BLEND_RGB_PERCEPTUAL, GIMP_GRADIENT_BLEND_RGB_PERCEPTUAL,
&color); sample);
if (color)
gegl_color_get_pixel (color, babl_format ("R'G'B'A double"), sample);
/* TODO: should we really return a list of floats? What about a list
* of GeglColor?
*/
sample += 4; sample++,
pos += delta; pos += delta;
g_clear_object (&color);
} }
} }
else else

View File

@ -414,25 +414,34 @@ map (GeglBuffer *buffer,
static gdouble * static gdouble *
get_samples_gradient (GimpDrawable *drawable) get_samples_gradient (GimpDrawable *drawable)
{ {
GimpGradient *gradient; GimpGradient *gradient;
GeglColor **colors;
gsize n_d_samples; const Babl *format_dst;
gdouble *d_samples = NULL; gdouble *d_samples;
gint bpp;
gradient = gimp_context_get_gradient (); gradient = gimp_context_get_gradient ();
/* FIXME: "reverse" hardcoded to FALSE. */ /* FIXME: "reverse" hardcoded to FALSE. */
gimp_gradient_get_uniform_samples (gradient, NSAMPLES, FALSE, colors = gimp_gradient_get_uniform_samples (gradient, NSAMPLES, FALSE);
&n_d_samples, &d_samples);
if (! gimp_drawable_is_rgb (drawable)) if (gimp_drawable_is_rgb (drawable))
{ {
const Babl *format_src = babl_format ("R'G'B'A double"); format_dst = babl_format ("R'G'B'A double");
const Babl *format_dst = babl_format ("Y'A double"); bpp = 4;
const Babl *fish = babl_fish (format_src, format_dst);
babl_process (fish, d_samples, d_samples, NSAMPLES);
} }
else
{
format_dst = babl_format ("Y'A double");
bpp = 2;
}
d_samples = g_new0 (gdouble, NSAMPLES * bpp);
for (gint i = 0; colors[i] != NULL; i++)
gegl_color_get_pixel (colors[i], format_dst, &d_samples[i * bpp]);
gimp_color_array_free (colors);
return d_samples; return d_samples;
} }

View File

@ -2405,36 +2405,34 @@ fill_missing_colors (void)
static void static void
get_gradient (gint mode) get_gradient (gint mode)
{ {
GimpGradient *gradient; GimpGradient *gradient;
GeglColor **colors;
gsize n_f_samples; const Babl *format_dst = babl_format ("RGB u8");
gdouble *f_samples; guchar *g_sample_color_tab_p;
gdouble *f_samp; /* float samples */ gint lum;
gint lum;
free_colors (); free_colors ();
gradient = gimp_context_get_gradient (); gradient = gimp_context_get_gradient ();
gimp_gradient_get_uniform_samples (gradient, 256 /* n_samples */, colors = gimp_gradient_get_uniform_samples (gradient, 256 /* n_samples */,
mode == SMP_INV_GRADIENT, mode == SMP_INV_GRADIENT);
&n_f_samples, &f_samples);
g_return_if_fail (gimp_color_array_get_length (colors) == 256);
g_sample_color_tab_p = g_sample_color_tab;
for (lum = 0; lum < 256; lum++) for (lum = 0; lum < 256; lum++)
{ {
f_samp = &f_samples[lum * 4]; gegl_color_get_pixel (colors[lum], format_dst, g_sample_color_tab_p);
g_sample_color_tab[3 * lum + 0] = f_samp[0] * 255; g_lum_tab[lum].col_ptr = new_samp_color (g_sample_color_tab_p);
g_sample_color_tab[3 * lum + 1] = f_samp[1] * 255;
g_sample_color_tab[3 * lum + 2] = f_samp[2] * 255;
g_lum_tab[lum].col_ptr =
new_samp_color (&g_sample_color_tab[3 * lum]);
g_lum_tab[lum].from_sample = TRUE; g_lum_tab[lum].from_sample = TRUE;
g_lum_tab[lum].all_samples = 1; g_lum_tab[lum].all_samples = 1;
g_sample_color_tab_p += 3;
} }
g_free (f_samples); gimp_color_array_free (colors);
} }
static void static void

View File

@ -382,20 +382,17 @@ drawable_to_cmap (control_point *cp)
} }
else if (GRADIENT_DRAWABLE == config.cmap_drawable_id) else if (GRADIENT_DRAWABLE == config.cmap_drawable_id)
{ {
GimpGradient *gradient = gimp_context_get_gradient (); GimpGradient *gradient = gimp_context_get_gradient ();
GeglColor **colors;
gsize num; const Babl *format_dst = babl_format ("R'G'B' double");
gdouble *g;
/* FIXME: "reverse" hardcoded to FALSE. */ /* FIXME: "reverse" hardcoded to FALSE. */
gimp_gradient_get_uniform_samples (gradient, 256, FALSE, colors = gimp_gradient_get_uniform_samples (gradient, 256, FALSE);
&num, &g);
for (i = 0; i < 256; i++) for (i = 0; i < 256; i++)
for (j = 0; j < 3; j++) gegl_color_get_pixel (colors[i], format_dst, &(cp->cmap[i][0]));
cp->cmap[i][j] = g[i*4 + j];
g_free (g); gimp_color_array_free (colors);
} }
else else
{ {

View File

@ -36,8 +36,7 @@
#define ZOOM_UNDO_SIZE 100 #define ZOOM_UNDO_SIZE 100
static gsize n_gradient_samples = 0; static GeglColor **gradient_samples = NULL;
static gdouble *gradient_samples = NULL;
static GimpGradient *gradient = NULL; static GimpGradient *gradient = NULL;
static gboolean ready_now = FALSE; static gboolean ready_now = FALSE;
static gchar *tpath = NULL; static gchar *tpath = NULL;
@ -1186,22 +1185,23 @@ set_cmap_preview (GimpProcedureConfig *config)
void void
make_color_map (GimpProcedureConfig *config) make_color_map (GimpProcedureConfig *config)
{ {
gint i; const Babl *colormap_format = babl_format ("R'G'B' u8");
gint r; gint i;
gint gr; gint r;
gint bl; gint gr;
gdouble redstretch; gint bl;
gdouble greenstretch; gdouble redstretch;
gdouble bluestretch; gdouble greenstretch;
gdouble pi = atan (1) * 4; gdouble bluestretch;
gint n_colors; gdouble pi = atan (1) * 4;
gint color_mode; gint n_colors;
gint red_mode; gint color_mode;
gint green_mode; gint red_mode;
gint blue_mode; gint green_mode;
gboolean red_invert; gint blue_mode;
gboolean green_invert; gboolean red_invert;
gboolean blue_invert; gboolean green_invert;
gboolean blue_invert;
g_object_get (config, g_object_get (config,
"n-colors", &n_colors, "n-colors", &n_colors,
@ -1224,11 +1224,8 @@ make_color_map (GimpProcedureConfig *config)
{ {
GimpGradient *gradient = gimp_context_get_gradient (); GimpGradient *gradient = gimp_context_get_gradient ();
gimp_gradient_get_uniform_samples (gradient, gradient_samples = gimp_gradient_get_uniform_samples (gradient,
n_colors, n_colors, FALSE);
FALSE,
&n_gradient_samples,
&gradient_samples);
} }
redstretch *= 127.5; redstretch *= 127.5;
@ -1238,9 +1235,7 @@ make_color_map (GimpProcedureConfig *config)
for (i = 0; i < n_colors; i++) for (i = 0; i < n_colors; i++)
if (color_mode == 1) if (color_mode == 1)
{ {
colormap[i].r = (guchar)(gradient_samples[i * 4] * 255.9); gegl_color_get_pixel (gradient_samples[i], colormap_format, (void *) &(colormap[i]));
colormap[i].g = (guchar)(gradient_samples[i * 4 + 1] * 255.9);
colormap[i].b = (guchar)(gradient_samples[i * 4 + 2] * 255.9);
} }
else else
{ {
@ -1587,8 +1582,8 @@ create_save_file_chooser (GtkWidget *widget,
/* Set cache of gradient and samples from it. /* Set cache of gradient and samples from it.
* *
* The cache is in three global variables: * The cache is in 2 global variables:
* gradient, gradient_samples, n_gradient_samples. * gradient, gradient_samples.
* This keeps the three variables coherent. * This keeps the three variables coherent.
* *
* !!! There is one other writer of gradient_samples, see below. * !!! There is one other writer of gradient_samples, see below.
@ -1614,13 +1609,10 @@ set_grad_data_cache (GimpGradient *in_gradient,
/* Refresh the global cache of samples. */ /* Refresh the global cache of samples. */
if (gradient_samples != NULL) if (gradient_samples != NULL)
g_free (gradient_samples); gimp_color_array_free (gradient_samples);
gimp_gradient_get_uniform_samples (gradient, gradient_samples = gimp_gradient_get_uniform_samples (gradient,
n_colors, n_colors, FALSE);
FALSE,
&n_gradient_samples,
&gradient_samples);
} }
gchar* gchar*

View File

@ -5034,22 +5034,21 @@ gradient_get_values_real_external (const gchar *gradient_name,
gint nvalues, gint nvalues,
gboolean reverse) gboolean reverse)
{ {
GimpGradient *gradient; GimpGradient *gradient;
gsize n_tmp_values; GeglColor **colors;
const Babl *format = babl_format ("R'G'B'A u8");
gdouble *tmp_values; gdouble *tmp_values;
gint i; gint i;
gint j; gint j;
gradient = gimp_gradient_get_by_name (gradient_name); gradient = gimp_gradient_get_by_name (gradient_name);
gimp_gradient_get_uniform_samples (gradient, nvalues, reverse, colors = gimp_gradient_get_uniform_samples (gradient, nvalues, reverse);
&n_tmp_values, &tmp_values);
for (i = 0; i < nvalues; i++) for (i = 0; i < nvalues; i++)
for (j = 0; j < 4; j++) gegl_color_get_pixel (colors[i], format, (void *) &values[4 * i]);
values[4 * i + j] = (guchar) (tmp_values[4 * i + j] * 255);
g_free (tmp_values); gimp_color_array_free (colors);
} }
void void

View File

@ -887,15 +887,20 @@ static gdouble *
get_gradient_samples (GimpDrawable *drawable, get_gradient_samples (GimpDrawable *drawable,
gboolean reverse) gboolean reverse)
{ {
GimpGradient *gradient; GimpGradient *gradient;
GeglColor **colors;
gsize n_d_samples; const Babl *format = babl_format ("R'G'B'A double");
gdouble *d_samples = NULL; gdouble *d_samples;
gradient = gimp_context_get_gradient (); gradient = gimp_context_get_gradient ();
gimp_gradient_get_uniform_samples (gradient, NGRADSAMPLES, reverse, colors = gimp_gradient_get_uniform_samples (gradient, NGRADSAMPLES, reverse);
&n_d_samples, &d_samples);
d_samples = g_new0 (gdouble, NGRADSAMPLES * 4);
for (gint i = 0; i < NGRADSAMPLES; i++)
gegl_color_get_pixel (colors[i], format, &d_samples[i * 4]);
gimp_color_array_free (colors);
return d_samples; return d_samples;
} }