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
* @color: returns a newly allocated color
*
* If you are iterating over an gradient, you should pass the the
* return value from the last call for @seg.
* If you are iterating over an gradient, you should pass the return
* value from the last call for @seg.
*
* Returns: the gradient segment the color is from
**/

View File

@ -160,8 +160,7 @@ gradient_get_uniform_samples_invoker (GimpProcedure *procedure,
GimpGradient *gradient;
gint num_samples;
gboolean reverse;
gsize num_color_samples = 0;
gdouble *color_samples = NULL;
GeglColor **color_samples = NULL;
gradient = g_value_get_object (gimp_value_array_index (args, 0));
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;
gdouble pos = 0.0;
gdouble delta = 1.0 / (num_samples - 1);
gdouble *sample;
GeglColor **sample;
num_color_samples = num_samples * 4;
sample = color_samples = g_new0 (gdouble, num_color_samples);
sample = color_samples = g_new0 (GeglColor *, num_samples + 1);
while (num_samples--)
{
GeglColor *color = NULL;
seg = gimp_gradient_get_color_at (gradient, context, seg,
pos, reverse,
GIMP_GRADIENT_BLEND_RGB_PERCEPTUAL,
&color);
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);
sample += 4;
pos += delta;
g_clear_object (&color);
sample++,
pos += delta;
}
}
else
@ -208,7 +196,7 @@ gradient_get_uniform_samples_invoker (GimpProcedure *procedure,
error ? *error : NULL);
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;
}
@ -1353,7 +1341,7 @@ register_gradient_procs (GimpPDB *pdb)
"gimp-gradient-get-uniform-samples");
gimp_procedure_set_static_help (procedure,
"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);
gimp_procedure_set_static_attribution (procedure,
"Federico Mena Quintero",
@ -1380,10 +1368,11 @@ register_gradient_procs (GimpPDB *pdb)
FALSE,
GIMP_PARAM_READWRITE));
gimp_procedure_add_return_value (procedure,
gimp_param_spec_double_array ("color-samples",
"color samples",
"Color samples: { R1, G1, B1, A1, ..., Rn, Gn, Bn, An }",
GIMP_PARAM_READWRITE));
g_param_spec_boxed ("color-samples",
"color samples",
"Color samples",
GIMP_TYPE_COLOR_ARRAY,
GIMP_PARAM_READWRITE));
gimp_pdb_register_procedure (pdb, procedure);
g_object_unref (procedure);

View File

@ -150,32 +150,29 @@ gimp_gradient_get_number_of_segments (GimpGradient *gradient)
* @gradient: The gradient.
* @num_samples: The number of samples to take.
* @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.
*
* 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 }.
* 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 }`.
*
* 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
**/
gboolean
gimp_gradient_get_uniform_samples (GimpGradient *gradient,
gint num_samples,
gboolean reverse,
gsize *num_color_samples,
gdouble **color_samples)
GeglColor **
gimp_gradient_get_uniform_samples (GimpGradient *gradient,
gint num_samples,
gboolean reverse)
{
GimpValueArray *args;
GimpValueArray *return_vals;
gboolean success = TRUE;
GeglColor **color_samples = NULL;
args = gimp_value_array_new_from_types (NULL,
GIMP_TYPE_GRADIENT, gradient,
@ -188,19 +185,12 @@ gimp_gradient_get_uniform_samples (GimpGradient *gradient,
args);
gimp_value_array_unref (args);
*num_color_samples = 0;
*color_samples = NULL;
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);
}
if (GIMP_VALUES_GET_ENUM (return_vals, 0) == GIMP_PDB_SUCCESS)
color_samples = gimp_color_array_copy (g_value_get_boxed (gimp_value_array_index (return_vals, 1)));
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_get_by_name (const gchar *name);
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,
gboolean reverse,
gsize *num_color_samples,
gdouble **color_samples);
gboolean reverse);
gboolean gimp_gradient_get_custom_samples (GimpGradient *gradient,
gsize num_samples,
const gdouble *positions,

View File

@ -216,21 +216,27 @@ get_gradient_data (GimpGradient *gradient,
gsize *sample_count,
gdouble **sample_array)
{
gboolean result;
gdouble *samples;
gsize n_samples;
gboolean result = FALSE;
GeglColor **samples;
result = gimp_gradient_get_uniform_samples (gradient,
allocation_width,
FALSE, /* not reversed. */
&n_samples,
&samples);
samples = gimp_gradient_get_uniform_samples (gradient, allocation_width,
FALSE /* not reversed. */);
if (result)
if (samples)
{
gdouble *dsamples;
/* Return array of samples to dereferenced handles. */
*sample_array = samples;
*sample_count = n_samples;
*sample_count = gimp_color_array_get_length (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. */

View File

@ -137,11 +137,11 @@ sub gradient_get_uniform_samples {
$blurb = 'Sample the gradient in uniform parts.';
$help = <<'HELP';
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 }`.
HELP
&federico_pdb_misc('1997', '2.2');
@ -155,10 +155,8 @@ HELP
);
@outargs = (
{ name => 'color_samples', type => 'doublearray', void_ret => 1,
desc => 'Color samples: { R1, G1, B1, A1, ..., Rn, Gn, Bn, An }',
array => { desc => 'Length of the color_samples array (4 *
num_samples)' } }
{ name => 'color_samples', type => 'colorarray',
desc => 'Color samples' }
);
%invoke = (
@ -169,30 +167,19 @@ HELP
GimpGradientSegment *seg = NULL;
gdouble pos = 0.0;
gdouble delta = 1.0 / (num_samples - 1);
gdouble *sample;
GeglColor **sample;
num_color_samples = num_samples * 4;
sample = color_samples = g_new0 (gdouble, num_color_samples);
sample = color_samples = g_new0 (GeglColor *, num_samples + 1);
while (num_samples--)
{
GeglColor *color = NULL;
seg = gimp_gradient_get_color_at (gradient, context, seg,
pos, reverse,
GIMP_GRADIENT_BLEND_RGB_PERCEPTUAL,
&color);
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);
sample += 4;
pos += delta;
g_clear_object (&color);
sample++,
pos += delta;
}
}
else

View File

@ -414,25 +414,34 @@ map (GeglBuffer *buffer,
static gdouble *
get_samples_gradient (GimpDrawable *drawable)
{
GimpGradient *gradient;
gsize n_d_samples;
gdouble *d_samples = NULL;
GimpGradient *gradient;
GeglColor **colors;
const Babl *format_dst;
gdouble *d_samples;
gint bpp;
gradient = gimp_context_get_gradient ();
/* FIXME: "reverse" hardcoded to FALSE. */
gimp_gradient_get_uniform_samples (gradient, NSAMPLES, FALSE,
&n_d_samples, &d_samples);
colors = gimp_gradient_get_uniform_samples (gradient, NSAMPLES, FALSE);
if (! gimp_drawable_is_rgb (drawable))
if (gimp_drawable_is_rgb (drawable))
{
const Babl *format_src = babl_format ("R'G'B'A double");
const Babl *format_dst = babl_format ("Y'A double");
const Babl *fish = babl_fish (format_src, format_dst);
babl_process (fish, d_samples, d_samples, NSAMPLES);
format_dst = babl_format ("R'G'B'A double");
bpp = 4;
}
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;
}

View File

@ -2405,36 +2405,34 @@ fill_missing_colors (void)
static void
get_gradient (gint mode)
{
GimpGradient *gradient;
gsize n_f_samples;
gdouble *f_samples;
gdouble *f_samp; /* float samples */
gint lum;
GimpGradient *gradient;
GeglColor **colors;
const Babl *format_dst = babl_format ("RGB u8");
guchar *g_sample_color_tab_p;
gint lum;
free_colors ();
gradient = gimp_context_get_gradient ();
gimp_gradient_get_uniform_samples (gradient, 256 /* n_samples */,
mode == SMP_INV_GRADIENT,
&n_f_samples, &f_samples);
colors = gimp_gradient_get_uniform_samples (gradient, 256 /* n_samples */,
mode == SMP_INV_GRADIENT);
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++)
{
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_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].col_ptr = new_samp_color (g_sample_color_tab_p);
g_lum_tab[lum].from_sample = TRUE;
g_lum_tab[lum].all_samples = 1;
g_sample_color_tab_p += 3;
}
g_free (f_samples);
gimp_color_array_free (colors);
}
static void

View File

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

View File

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

View File

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

View File

@ -887,15 +887,20 @@ static gdouble *
get_gradient_samples (GimpDrawable *drawable,
gboolean reverse)
{
GimpGradient *gradient;
gsize n_d_samples;
gdouble *d_samples = NULL;
GimpGradient *gradient;
GeglColor **colors;
const Babl *format = babl_format ("R'G'B'A double");
gdouble *d_samples;
gradient = gimp_context_get_gradient ();
gimp_gradient_get_uniform_samples (gradient, NGRADSAMPLES, reverse,
&n_d_samples, &d_samples);
colors = gimp_gradient_get_uniform_samples (gradient, NGRADSAMPLES, reverse);
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;
}