mirror of https://github.com/GNOME/gimp.git
app: update fg/bg color action code modifying colors through RGB axes.
In space invasion world, we want color-related code to be contextual. When we say "Increase/Decrease the red/green/blue channel by X%", it would actually mean something different if you are working on a sRGB space or a wider gamut space. Furthermore, it means also something different if you work on linear/perceptual, overriding the space's actual TRC. This is why this new code takes the active image into account and uses this as a base for the space and TRC you are working on. In case you have no active image, it defaults to the current GeglColor space (though really this case should not matter too much). In case your image is not RGB to begin with, it uses sRGB space.
This commit is contained in:
parent
b1178c51a3
commit
cd09634dc2
|
@ -30,10 +30,13 @@
|
||||||
|
|
||||||
#include "operations/layer-modes/gimp-layer-modes.h"
|
#include "operations/layer-modes/gimp-layer-modes.h"
|
||||||
|
|
||||||
|
#include "gegl/gimp-babl.h"
|
||||||
|
|
||||||
#include "core/gimp.h"
|
#include "core/gimp.h"
|
||||||
#include "core/gimpbrushgenerated.h"
|
#include "core/gimpbrushgenerated.h"
|
||||||
#include "core/gimpcontext.h"
|
#include "core/gimpcontext.h"
|
||||||
#include "core/gimpdatafactory.h"
|
#include "core/gimpdatafactory.h"
|
||||||
|
#include "core/gimpimage.h"
|
||||||
#include "core/gimplist.h"
|
#include "core/gimplist.h"
|
||||||
#include "core/gimppaintinfo.h"
|
#include "core/gimppaintinfo.h"
|
||||||
#include "core/gimptoolinfo.h"
|
#include "core/gimptoolinfo.h"
|
||||||
|
@ -78,6 +81,9 @@ static gboolean context_set_color_index (gint index,
|
||||||
static GimpPaletteEditor * context_get_palette_editor (void);
|
static GimpPaletteEditor * context_get_palette_editor (void);
|
||||||
static GimpColormapEditor * context_get_colormap_editor (void);
|
static GimpColormapEditor * context_get_colormap_editor (void);
|
||||||
|
|
||||||
|
static const Babl * context_get_rgb_format (GimpContext *context,
|
||||||
|
GeglColor *color);
|
||||||
|
|
||||||
|
|
||||||
/* public functions */
|
/* public functions */
|
||||||
|
|
||||||
|
@ -137,22 +143,27 @@ context_foreground_red_cmd_callback (GimpAction *action,
|
||||||
{
|
{
|
||||||
GimpContext *context;
|
GimpContext *context;
|
||||||
GeglColor *color;
|
GeglColor *color;
|
||||||
gdouble red;
|
const Babl *format;
|
||||||
gdouble green;
|
gdouble pixel[4];
|
||||||
gdouble blue;
|
|
||||||
gdouble alpha;
|
|
||||||
GimpActionSelectType select_type;
|
GimpActionSelectType select_type;
|
||||||
return_if_no_context (context, data);
|
return_if_no_context (context, data);
|
||||||
|
|
||||||
select_type = (GimpActionSelectType) g_variant_get_int32 (value);
|
select_type = (GimpActionSelectType) g_variant_get_int32 (value);
|
||||||
|
|
||||||
color = gegl_color_duplicate (gimp_context_get_foreground (context));
|
color = gegl_color_duplicate (gimp_context_get_foreground (context));
|
||||||
gegl_color_get_rgba_with_space (color, &red, &green, &blue, &alpha, NULL);
|
format = context_get_rgb_format (context, color);
|
||||||
red = action_select_value (select_type,
|
|
||||||
red,
|
gegl_color_get_pixel (color, format, pixel);
|
||||||
0.0, 1.0, 1.0,
|
/* TODO: if value was already out-of-gamut, say we want to decrease it
|
||||||
1.0 / 255.0, 0.01, 0.1, 0.0, FALSE);
|
* progressively. Should the algorithm allow it to be decreased while still
|
||||||
gegl_color_set_rgba_with_space (color, red, green, blue, alpha, NULL);
|
* staying out-of-gamut? Currently the function always clamps the result to
|
||||||
|
* min/max.
|
||||||
|
*/
|
||||||
|
pixel[0] = action_select_value (select_type,
|
||||||
|
pixel[0],
|
||||||
|
0.0, 1.0, 1.0,
|
||||||
|
1.0 / 255.0, 0.01, 0.1, 0.0, FALSE);
|
||||||
|
gegl_color_set_pixel (color, format, pixel);
|
||||||
gimp_context_set_foreground (context, color);
|
gimp_context_set_foreground (context, color);
|
||||||
g_object_unref (color);
|
g_object_unref (color);
|
||||||
}
|
}
|
||||||
|
@ -164,22 +175,22 @@ context_foreground_green_cmd_callback (GimpAction *action,
|
||||||
{
|
{
|
||||||
GimpContext *context;
|
GimpContext *context;
|
||||||
GeglColor *color;
|
GeglColor *color;
|
||||||
gdouble red;
|
const Babl *format;
|
||||||
gdouble green;
|
gdouble pixel[4];
|
||||||
gdouble blue;
|
|
||||||
gdouble alpha;
|
|
||||||
GimpActionSelectType select_type;
|
GimpActionSelectType select_type;
|
||||||
return_if_no_context (context, data);
|
return_if_no_context (context, data);
|
||||||
|
|
||||||
select_type = (GimpActionSelectType) g_variant_get_int32 (value);
|
select_type = (GimpActionSelectType) g_variant_get_int32 (value);
|
||||||
|
|
||||||
color = gegl_color_duplicate (gimp_context_get_foreground (context));
|
color = gegl_color_duplicate (gimp_context_get_foreground (context));
|
||||||
gegl_color_get_rgba_with_space (color, &red, &green, &blue, &alpha, NULL);
|
format = context_get_rgb_format (context, color);
|
||||||
green = action_select_value (select_type,
|
|
||||||
green,
|
gegl_color_get_pixel (color, format, pixel);
|
||||||
0.0, 1.0, 1.0,
|
pixel[1] = action_select_value (select_type,
|
||||||
1.0 / 255.0, 0.01, 0.1, 0.0, FALSE);
|
pixel[1],
|
||||||
gegl_color_set_rgba_with_space (color, red, green, blue, alpha, NULL);
|
0.0, 1.0, 1.0,
|
||||||
|
1.0 / 255.0, 0.01, 0.1, 0.0, FALSE);
|
||||||
|
gegl_color_set_pixel (color, format, pixel);
|
||||||
gimp_context_set_foreground (context, color);
|
gimp_context_set_foreground (context, color);
|
||||||
g_object_unref (color);
|
g_object_unref (color);
|
||||||
}
|
}
|
||||||
|
@ -191,22 +202,22 @@ context_foreground_blue_cmd_callback (GimpAction *action,
|
||||||
{
|
{
|
||||||
GimpContext *context;
|
GimpContext *context;
|
||||||
GeglColor *color;
|
GeglColor *color;
|
||||||
gdouble red;
|
const Babl *format;
|
||||||
gdouble green;
|
gdouble pixel[4];
|
||||||
gdouble blue;
|
|
||||||
gdouble alpha;
|
|
||||||
GimpActionSelectType select_type;
|
GimpActionSelectType select_type;
|
||||||
return_if_no_context (context, data);
|
return_if_no_context (context, data);
|
||||||
|
|
||||||
select_type = (GimpActionSelectType) g_variant_get_int32 (value);
|
select_type = (GimpActionSelectType) g_variant_get_int32 (value);
|
||||||
|
|
||||||
color = gegl_color_duplicate (gimp_context_get_foreground (context));
|
color = gegl_color_duplicate (gimp_context_get_foreground (context));
|
||||||
gegl_color_get_rgba_with_space (color, &red, &green, &blue, &alpha, NULL);
|
format = context_get_rgb_format (context, color);
|
||||||
blue = action_select_value (select_type,
|
|
||||||
blue,
|
gegl_color_get_pixel (color, format, pixel);
|
||||||
0.0, 1.0, 1.0,
|
pixel[2] = action_select_value (select_type,
|
||||||
1.0 / 255.0, 0.01, 0.1, 0.0, FALSE);
|
pixel[2],
|
||||||
gegl_color_set_rgba_with_space (color, red, green, blue, alpha, NULL);
|
0.0, 1.0, 1.0,
|
||||||
|
1.0 / 255.0, 0.01, 0.1, 0.0, FALSE);
|
||||||
|
gegl_color_set_pixel (color, format, pixel);
|
||||||
gimp_context_set_foreground (context, color);
|
gimp_context_set_foreground (context, color);
|
||||||
g_object_unref (color);
|
g_object_unref (color);
|
||||||
}
|
}
|
||||||
|
@ -218,23 +229,22 @@ context_background_red_cmd_callback (GimpAction *action,
|
||||||
{
|
{
|
||||||
GimpContext *context;
|
GimpContext *context;
|
||||||
GeglColor *color;
|
GeglColor *color;
|
||||||
gdouble red;
|
const Babl *format;
|
||||||
gdouble green;
|
gdouble pixel[4];
|
||||||
gdouble blue;
|
|
||||||
gdouble alpha;
|
|
||||||
GimpActionSelectType select_type;
|
GimpActionSelectType select_type;
|
||||||
return_if_no_context (context, data);
|
return_if_no_context (context, data);
|
||||||
|
|
||||||
select_type = (GimpActionSelectType) g_variant_get_int32 (value);
|
select_type = (GimpActionSelectType) g_variant_get_int32 (value);
|
||||||
|
|
||||||
color = gegl_color_duplicate (gimp_context_get_background (context));
|
color = gegl_color_duplicate (gimp_context_get_background (context));
|
||||||
/* TODO: what space to use for this action to work as expected? */
|
format = context_get_rgb_format (context, color);
|
||||||
gegl_color_get_rgba_with_space (color, &red, &green, &blue, &alpha, NULL);
|
|
||||||
red = action_select_value (select_type,
|
gegl_color_get_pixel (color, format, pixel);
|
||||||
red,
|
pixel[0] = action_select_value (select_type,
|
||||||
0.0, 1.0, 1.0,
|
pixel[0],
|
||||||
1.0 / 255.0, 0.01, 0.1, 0.0, FALSE);
|
0.0, 1.0, 1.0,
|
||||||
gegl_color_set_rgba_with_space (color, red, green, blue, alpha, NULL);
|
1.0 / 255.0, 0.01, 0.1, 0.0, FALSE);
|
||||||
|
gegl_color_set_pixel (color, format, pixel);
|
||||||
gimp_context_set_background (context, color);
|
gimp_context_set_background (context, color);
|
||||||
g_object_unref (color);
|
g_object_unref (color);
|
||||||
}
|
}
|
||||||
|
@ -246,22 +256,22 @@ context_background_green_cmd_callback (GimpAction *action,
|
||||||
{
|
{
|
||||||
GimpContext *context;
|
GimpContext *context;
|
||||||
GeglColor *color;
|
GeglColor *color;
|
||||||
gdouble red;
|
const Babl *format;
|
||||||
gdouble green;
|
gdouble pixel[4];
|
||||||
gdouble blue;
|
|
||||||
gdouble alpha;
|
|
||||||
GimpActionSelectType select_type;
|
GimpActionSelectType select_type;
|
||||||
return_if_no_context (context, data);
|
return_if_no_context (context, data);
|
||||||
|
|
||||||
select_type = (GimpActionSelectType) g_variant_get_int32 (value);
|
select_type = (GimpActionSelectType) g_variant_get_int32 (value);
|
||||||
|
|
||||||
color = gegl_color_duplicate (gimp_context_get_background (context));
|
color = gegl_color_duplicate (gimp_context_get_background (context));
|
||||||
gegl_color_get_rgba_with_space (color, &red, &green, &blue, &alpha, NULL);
|
format = context_get_rgb_format (context, color);
|
||||||
green = action_select_value (select_type,
|
|
||||||
green,
|
gegl_color_get_pixel (color, format, pixel);
|
||||||
0.0, 1.0, 1.0,
|
pixel[1] = action_select_value (select_type,
|
||||||
1.0 / 255.0, 0.01, 0.1, 0.0, FALSE);
|
pixel[1],
|
||||||
gegl_color_set_rgba_with_space (color, red, green, blue, alpha, NULL);
|
0.0, 1.0, 1.0,
|
||||||
|
1.0 / 255.0, 0.01, 0.1, 0.0, FALSE);
|
||||||
|
gegl_color_set_pixel (color, format, pixel);
|
||||||
gimp_context_set_background (context, color);
|
gimp_context_set_background (context, color);
|
||||||
g_object_unref (color);
|
g_object_unref (color);
|
||||||
}
|
}
|
||||||
|
@ -273,22 +283,22 @@ context_background_blue_cmd_callback (GimpAction *action,
|
||||||
{
|
{
|
||||||
GimpContext *context;
|
GimpContext *context;
|
||||||
GeglColor *color;
|
GeglColor *color;
|
||||||
gdouble red;
|
const Babl *format;
|
||||||
gdouble green;
|
gdouble pixel[4];
|
||||||
gdouble blue;
|
|
||||||
gdouble alpha;
|
|
||||||
GimpActionSelectType select_type;
|
GimpActionSelectType select_type;
|
||||||
return_if_no_context (context, data);
|
return_if_no_context (context, data);
|
||||||
|
|
||||||
select_type = (GimpActionSelectType) g_variant_get_int32 (value);
|
select_type = (GimpActionSelectType) g_variant_get_int32 (value);
|
||||||
|
|
||||||
color = gegl_color_duplicate (gimp_context_get_background (context));
|
color = gegl_color_duplicate (gimp_context_get_background (context));
|
||||||
gegl_color_get_rgba_with_space (color, &red, &green, &blue, &alpha, NULL);
|
format = context_get_rgb_format (context, color);
|
||||||
blue = action_select_value (select_type,
|
|
||||||
blue,
|
gegl_color_get_pixel (color, format, pixel);
|
||||||
|
pixel[2] = action_select_value (select_type,
|
||||||
|
pixel[2],
|
||||||
0.0, 1.0, 1.0,
|
0.0, 1.0, 1.0,
|
||||||
1.0 / 255.0, 0.01, 0.1, 0.0, FALSE);
|
1.0 / 255.0, 0.01, 0.1, 0.0, FALSE);
|
||||||
gegl_color_set_rgba_with_space (color, red, green, blue, alpha, NULL);
|
gegl_color_set_pixel (color, format, pixel);
|
||||||
gimp_context_set_background (context, color);
|
gimp_context_set_background (context, color);
|
||||||
g_object_unref (color);
|
g_object_unref (color);
|
||||||
}
|
}
|
||||||
|
@ -1086,3 +1096,86 @@ context_get_colormap_editor (void)
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The logic for the format to use in RGB color actions is as following:
|
||||||
|
* - The space we navigate through is the active image's space.
|
||||||
|
* - Increasing/decreasing follows the image TRC (in particular, if the image is
|
||||||
|
* linear or perceptual, we care about chromaticities yet don't follow the
|
||||||
|
* space TRC).
|
||||||
|
* - If there is no active image or if its space is non-sRGB, we use the context
|
||||||
|
* color's space.
|
||||||
|
* - We discard non-RGB spaces and fallback to sRGB.
|
||||||
|
*/
|
||||||
|
static const Babl *
|
||||||
|
context_get_rgb_format (GimpContext *context,
|
||||||
|
GeglColor *color)
|
||||||
|
{
|
||||||
|
GimpImage *image = NULL;
|
||||||
|
const Babl *format = NULL;
|
||||||
|
const Babl *space = NULL;
|
||||||
|
GimpTRCType trc = GIMP_TRC_NON_LINEAR;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
|
||||||
|
|
||||||
|
image = gimp_context_get_image (context);
|
||||||
|
if (image)
|
||||||
|
{
|
||||||
|
format = gimp_image_get_layer_format (image, FALSE);
|
||||||
|
space = babl_format_get_space (format);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (space == NULL ||
|
||||||
|
#if BABL_MINOR_VERSION > 1 || (BABL_MINOR_VERSION == 1 && BABL_MICRO_VERSION >= 107)
|
||||||
|
! babl_space_is_rgb (space) ||
|
||||||
|
#else
|
||||||
|
babl_space_is_cmyk (space) ||
|
||||||
|
babl_space_is_gray (space) ||
|
||||||
|
#endif
|
||||||
|
FALSE)
|
||||||
|
{
|
||||||
|
format = gegl_color_get_format (color);
|
||||||
|
space = babl_format_get_space (format);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if BABL_MINOR_VERSION > 1 || (BABL_MINOR_VERSION == 1 && BABL_MICRO_VERSION >= 107)
|
||||||
|
if (! babl_space_is_rgb (space))
|
||||||
|
#else
|
||||||
|
if (babl_space_is_cmyk (space) || babl_space_is_gray (space))
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
format = NULL;
|
||||||
|
space = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (format != NULL)
|
||||||
|
{
|
||||||
|
if (image != NULL)
|
||||||
|
{
|
||||||
|
GimpPrecision precision;
|
||||||
|
|
||||||
|
precision = gimp_image_get_precision (image);
|
||||||
|
trc = gimp_babl_trc (precision);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
trc = gimp_babl_format_get_trc (format);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (trc)
|
||||||
|
{
|
||||||
|
case GIMP_TRC_LINEAR:
|
||||||
|
format = babl_format_with_space ("RGBA double", space);
|
||||||
|
break;
|
||||||
|
case GIMP_TRC_NON_LINEAR:
|
||||||
|
format = babl_format_with_space ("R'G'B'A double", space);
|
||||||
|
break;
|
||||||
|
case GIMP_TRC_PERCEPTUAL:
|
||||||
|
format = babl_format_with_space ("R~G~B~A double", space);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_return_val_if_reached (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return format;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue