[gimp] app, libgimpwidgets: new gimp_color_area_set_out_of_gamut().
- From: Jehan <jehanp src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] app, libgimpwidgets: new gimp_color_area_set_out_of_gamut().
- Date: Wed, 6 Mar 2019 15:36:37 +0000 (UTC)
commit 4be9b7a401b8f981b4720f090c887b494e890726
Author: Jehan <jehan girinstud io>
Date: Wed Mar 6 16:14:32 2019 +0100
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.
app/widgets/gimpcolorhistory.c | 107 ++++++++++++++++++++++++++++++++++++-----
app/widgets/gimpcolorhistory.h | 1 +
libgimpwidgets/gimpcolorarea.c | 41 ++++++++++++++--
libgimpwidgets/gimpcolorarea.h | 2 +
4 files changed, 135 insertions(+), 16 deletions(-)
---
diff --git a/app/widgets/gimpcolorhistory.c b/app/widgets/gimpcolorhistory.c
index 8e75570750..4e377dcc94 100644
--- a/app/widgets/gimpcolorhistory.c
+++ b/app/widgets/gimpcolorhistory.c
@@ -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)
{
diff --git a/app/widgets/gimpcolorhistory.h b/app/widgets/gimpcolorhistory.h
index f0f5c65fd4..cd86196301 100644
--- a/app/widgets/gimpcolorhistory.h
+++ b/app/widgets/gimpcolorhistory.h
@@ -37,6 +37,7 @@ struct _GimpColorHistory
GtkGrid parent_instance;
GimpContext *context;
+ GimpImage *active_image;
GtkWidget **color_areas;
GtkWidget **buttons;
diff --git a/libgimpwidgets/gimpcolorarea.c b/libgimpwidgets/gimpcolorarea.c
index d0acf3dcfd..7684f9056c 100644
--- a/libgimpwidgets/gimpcolorarea.c
+++ b/libgimpwidgets/gimpcolorarea.c
@@ -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.
diff --git a/libgimpwidgets/gimpcolorarea.h b/libgimpwidgets/gimpcolorarea.h
index aed62c4f58..693ae4e159 100644
--- a/libgimpwidgets/gimpcolorarea.h
+++ b/libgimpwidgets/gimpcolorarea.h
@@ -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);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]