app, libgimpwidgets: new gimp_color_area_set_out_of_gamut().

This allows to force a GimpColorArea to display as out-of-gamut color.
Current code was only considering the generic RGB case (outside of [0-1]
range), and in particular not grayscale or indexed images.

Ideally the GimpColorArea widget could be (optionally) made to follow a
context, so that for instance it could update its representation when
the context image changes, or when this image's type changes. Yet since
it is a libgimpwidgets widget, it cannot get such update. Instead I add
a new API function to display the color box with the out-of-gamut
triangle. The decision code for this will have to be done elsewhere.

Use this new API for GimpColorHistory to display non-gray colors in the
history as out-of-gamut on grayscale images, or colors absent of the
palette on indexed images.
This commit is contained in:
Jehan 2019-03-06 16:14:32 +01:00
parent bb7f61c919
commit 4be9b7a401
4 changed files with 135 additions and 16 deletions

View File

@ -32,6 +32,8 @@
#include "core/gimp.h"
#include "core/gimp-palettes.h"
#include "core/gimpcontext.h"
#include "core/gimpimage.h"
#include "app/core/gimpimage-colormap.h"
#include "core/gimpmarshal.h"
#include "core/gimppalettemru.h"
@ -55,6 +57,7 @@ enum
#define DEFAULT_HISTORY_SIZE 12
#define COLOR_AREA_SIZE 20
#define CHANNEL_EPSILON 1e-3
/* GObject methods */
static void gimp_color_history_constructed (GObject *object);
@ -85,12 +88,15 @@ static void gimp_color_history_size_allocate (GtkWidget
static void gimp_color_history_color_clicked (GtkWidget *widget,
GimpColorHistory *history);
static void gimp_color_history_palette_dirty (GimpPalette *palette,
GimpColorHistory *history);
static void gimp_color_history_palette_dirty (GimpColorHistory *history);
static void gimp_color_history_color_changed (GtkWidget *widget,
gpointer data);
static void gimp_color_history_image_changed (GimpContext *context,
GimpImage *image,
GimpColorHistory *history);
/* Utils */
static void gimp_color_history_reorganize (GimpColorHistory *history);
@ -169,7 +175,7 @@ gimp_color_history_constructed (GObject *object)
g_signal_connect_object (palette, "dirty",
G_CALLBACK (gimp_color_history_palette_dirty),
G_OBJECT (history), 0);
G_OBJECT (history), G_CONNECT_SWAPPED);
}
static void
@ -196,15 +202,41 @@ gimp_color_history_set_property (GObject *object,
switch (property_id)
{
case PROP_CONTEXT:
if (history->context)
g_signal_handlers_disconnect_by_func (history->context,
gimp_color_history_image_changed,
history);
if (history->active_image)
{
g_signal_handlers_disconnect_by_func (history->active_image,
G_CALLBACK (gimp_color_history_palette_dirty),
history);
history->active_image = NULL;
}
history->context = g_value_get_object (value);
if (history->context)
{
g_signal_connect (history->context, "image-changed",
G_CALLBACK (gimp_color_history_image_changed),
history);
history->active_image = gimp_context_get_image (history->context);
if (history->active_image)
{
g_signal_connect_swapped (history->active_image, "notify::base-type",
G_CALLBACK (gimp_color_history_palette_dirty),
history);
g_signal_connect_swapped (history->active_image, "colormap-changed",
G_CALLBACK (gimp_color_history_palette_dirty),
history);
}
}
break;
case PROP_HISTORY_SIZE:
{
GimpPalette *palette;
GtkWidget *button;
GtkWidget *color_area;
gint i;
GtkWidget *button;
GtkWidget *color_area;
gint i;
history->history_size = g_value_get_int (value);
@ -249,8 +281,7 @@ gimp_color_history_set_property (GObject *object,
history->color_areas[i] = color_area;
}
palette = gimp_palettes_get_color_history (history->context->gimp);
gimp_color_history_palette_dirty (palette, history);
gimp_color_history_palette_dirty (history);
}
break;
@ -426,22 +457,47 @@ gimp_color_history_color_clicked (GtkWidget *widget,
/* Color history palette callback. */
static void
gimp_color_history_palette_dirty (GimpPalette *palette,
GimpColorHistory *history)
gimp_color_history_palette_dirty (GimpColorHistory *history)
{
gint i;
GimpPalette *palette;
GimpPalette *colormap_palette = NULL;
GimpImageBaseType base_type = GIMP_RGB;
gint i;
palette = gimp_palettes_get_color_history (history->context->gimp);
if (history->active_image)
{
base_type = gimp_image_get_base_type (history->active_image);
if (base_type == GIMP_INDEXED)
colormap_palette = gimp_image_get_colormap_palette (history->active_image);
}
for (i = 0; i < history->history_size; i++)
{
GimpPaletteEntry *entry = gimp_palette_get_entry (palette, i);
GimpRGB black = { 0.0, 0.0, 0.0, 1.0 };
GimpRGB color = entry ? entry->color : black;
gboolean oog = FALSE;
g_signal_handlers_block_by_func (history->color_areas[i],
gimp_color_history_color_changed,
GINT_TO_POINTER (i));
gimp_color_area_set_color (GIMP_COLOR_AREA (history->color_areas[i]),
entry ? &entry->color : &black);
&color);
if (/* Common out-of-gamut case */
(color.r < 0.0 || color.r > 1.0 ||
color.g < 0.0 || color.g > 1.0 ||
color.b < 0.0 || color.b > 1.0) ||
/* Indexed images */
(colormap_palette && ! gimp_palette_find_entry (colormap_palette, &color, NULL)) ||
/* Grayscale images */
(base_type == GIMP_GRAY &&
(ABS (color.r - color.g) > CHANNEL_EPSILON ||
ABS (color.r - color.b) > CHANNEL_EPSILON ||
ABS (color.g - color.b) > CHANNEL_EPSILON)))
oog = TRUE;
gimp_color_area_set_out_of_gamut (GIMP_COLOR_AREA (history->color_areas[i]), oog);
g_signal_handlers_unblock_by_func (history->color_areas[i],
gimp_color_history_color_changed,
@ -469,6 +525,31 @@ gimp_color_history_color_changed (GtkWidget *widget,
gimp_palette_set_entry_color (palette, GPOINTER_TO_INT (data), &color);
}
static void
gimp_color_history_image_changed (GimpContext *context,
GimpImage *image,
GimpColorHistory *history)
{
/* Update active image. */
if (history->active_image)
g_signal_handlers_disconnect_by_func (history->active_image,
G_CALLBACK (gimp_color_history_palette_dirty),
history);
history->active_image = image;
if (image)
{
g_signal_connect_swapped (image, "notify::base-type",
G_CALLBACK (gimp_color_history_palette_dirty),
history);
g_signal_connect_swapped (image, "colormap-changed",
G_CALLBACK (gimp_color_history_palette_dirty),
history);
}
/* Update the palette. */
gimp_color_history_palette_dirty (history);
}
static void
gimp_color_history_reorganize (GimpColorHistory *history)
{

View File

@ -37,6 +37,7 @@ struct _GimpColorHistory
GtkGrid parent_instance;
GimpContext *context;
GimpImage *active_image;
GtkWidget **color_areas;
GtkWidget **buttons;

View File

@ -80,6 +80,8 @@ struct _GimpColorAreaPrivate
GimpRGB color;
guint draw_border : 1;
guint needs_render : 1;
gboolean out_of_gamut;
};
#define GET_PRIVATE(obj) (((GimpColorArea *) (obj))->priv)
@ -457,9 +459,10 @@ gimp_color_area_draw (GtkWidget *widget,
}
if (priv->config &&
(priv->color.r < 0.0 || priv->color.r > 1.0 ||
priv->color.g < 0.0 || priv->color.g > 1.0 ||
priv->color.b < 0.0 || priv->color.b > 1.0))
((priv->color.r < 0.0 || priv->color.r > 1.0 ||
priv->color.g < 0.0 || priv->color.g > 1.0 ||
priv->color.b < 0.0 || priv->color.b > 1.0) ||
priv->out_of_gamut))
{
GimpRGB color;
gint side = MIN (priv->width, priv->height) * 2 / 3;
@ -652,6 +655,38 @@ gimp_color_area_set_draw_border (GimpColorArea *area,
}
}
/**
* gimp_color_area_set_out_of_gamut:
* @area: a #GimpColorArea widget.
* @config: a #GimpColorConfig object.
*
* Sets the color area to render as an out-of-gamut color, i.e. with a
* small triangle on a corner using the color management out of gamut
* color (as per gimp_color_area_set_color_config()).
*
* By default, @area will render as out-of-gamut for any RGB color with
* a channel out of the [0; 1] range. This function allows to consider
* more colors out of gamut (for instance non-gray colors on a grayscale
* image, or colors absent of palettes in indexed images, etc.)
*
* Since: 2.10.10
*/
void
gimp_color_area_set_out_of_gamut (GimpColorArea *area,
gboolean out_of_gamut)
{
GimpColorAreaPrivate *priv;
g_return_if_fail (GIMP_IS_COLOR_AREA (area));
priv = GET_PRIVATE (area);
if (priv->out_of_gamut != out_of_gamut)
{
priv->out_of_gamut = out_of_gamut;
gtk_widget_queue_draw (GTK_WIDGET (area));
}
}
/**
* gimp_color_area_set_color_config:
* @area: a #GimpColorArea widget.

View File

@ -86,6 +86,8 @@ void gimp_color_area_set_type (GimpColorArea *area,
GimpColorAreaType type);
void gimp_color_area_set_draw_border (GimpColorArea *area,
gboolean draw_border);
void gimp_color_area_set_out_of_gamut (GimpColorArea *area,
gboolean out_of_gamut);
void gimp_color_area_set_color_config (GimpColorArea *area,
GimpColorConfig *config);