From 5cae0bf65c9720c3b7b142240724c42e18bbca14 Mon Sep 17 00:00:00 2001 From: Omari Stephens Date: Sun, 23 Jan 2011 07:28:33 +0000 Subject: [PATCH] Bug 630748 - display filters do not work Create and use Cairo-compatible API for display filters. Also includes logic changes to the display filters to deal with cairo's ARGB32 pre-multiplied buffer format. --- app/display/gimpdisplayshell-render.c | 33 +++---- libgimpwidgets/gimpcolordisplay.c | 43 +++++++++ libgimpwidgets/gimpcolordisplay.h | 9 +- libgimpwidgets/gimpcolordisplaystack.c | 42 +++++++++ libgimpwidgets/gimpcolordisplaystack.h | 36 ++++---- modules/display-filter-color-blind.c | 123 +++++++++++++------------ modules/display-filter-gamma.c | 81 ++++++++-------- modules/display-filter-high-contrast.c | 79 ++++++++-------- modules/display-filter-lcms.c | 117 ++++++++++++++--------- modules/display-filter-proof.c | 110 +++++++++++++--------- plug-ins/pygimp/gimpui.defs | 20 ++++ 11 files changed, 434 insertions(+), 259 deletions(-) diff --git a/app/display/gimpdisplayshell-render.c b/app/display/gimpdisplayshell-render.c index 2c8b416a25..cf7cfe55c9 100644 --- a/app/display/gimpdisplayshell-render.c +++ b/app/display/gimpdisplayshell-render.c @@ -160,29 +160,24 @@ gimp_display_shell_render (GimpDisplayShell *shell, switch (type) { - case GIMP_RGBA_IMAGE: - render_image_rgb_a (&info); - break; - case GIMP_GRAYA_IMAGE: - render_image_gray_a (&info); - break; - default: - g_warning ("%s: unsupported projection type (%d)", G_STRFUNC, type); - g_assert_not_reached (); + case GIMP_RGBA_IMAGE: + render_image_rgb_a (&info); + break; + case GIMP_GRAYA_IMAGE: + render_image_gray_a (&info); + break; + default: + g_warning ("%s: unsupported projection type (%d)", G_STRFUNC, type); + g_assert_not_reached (); } - /* apply filters to the rendered projection */ -#if 0 - if (shell->filter_stack) - gimp_color_display_stack_convert (shell->filter_stack, - shell->render_buf, - w, h, - 3, - 3 * GIMP_DISPLAY_RENDER_BUF_WIDTH); -#endif - cairo_surface_mark_dirty (shell->render_surface); + /* apply filters to the rendered projection */ + if (shell->filter_stack) + gimp_color_display_stack_convert_surface (shell->filter_stack, + shell->render_surface); + if (shell->mask) { if (! shell->mask_surface) diff --git a/libgimpwidgets/gimpcolordisplay.c b/libgimpwidgets/gimpcolordisplay.c index 328618c885..5216b4adca 100644 --- a/libgimpwidgets/gimpcolordisplay.c +++ b/libgimpwidgets/gimpcolordisplay.c @@ -140,6 +140,7 @@ gimp_color_display_class_init (GimpColorDisplayClass *klass) klass->stock_id = GIMP_STOCK_DISPLAY_FILTER; klass->clone = NULL; + klass->convert_surface = NULL; klass->convert = NULL; klass->load_state = NULL; klass->save_state = NULL; @@ -334,6 +335,46 @@ gimp_color_display_clone (GimpColorDisplay *display) return GIMP_COLOR_DISPLAY (gimp_config_duplicate (GIMP_CONFIG (display))); } +/** + * gimp_color_display_convert_surface: + * @display: a #GimpColorDisplay + * @surface: a #cairo_image_surface_t of type ARGB32 + * + * Converts all pixels in @surface. + * + * Since: GIMP 2.8 + **/ +void +gimp_color_display_convert_surface (GimpColorDisplay *display, + cairo_surface_t *surface) +{ + g_return_if_fail (GIMP_IS_COLOR_DISPLAY (display)); + g_return_if_fail (surface != NULL); + g_return_if_fail (cairo_surface_get_type (surface) == + CAIRO_SURFACE_TYPE_IMAGE); + + if (display->enabled && + GIMP_COLOR_DISPLAY_GET_CLASS (display)->convert_surface) + { + cairo_surface_flush (surface); + GIMP_COLOR_DISPLAY_GET_CLASS (display)->convert_surface (display, surface); + cairo_surface_mark_dirty (surface); + } +} + +/** + * gimp_color_display_convert: + * @display: a #GimpColorDisplay + * @buf: the pixel buffer to convert + * @width: the width of the buffer + * @height: the height of the buffer + * @bpp: the number of bytes per pixel + * @bpl: the buffer's rowstride + * + * Converts all pixels in @buf. + * + * Deprecated: GIMP 2.8: Use gimp_color_display_convert_surface() instead. + **/ void gimp_color_display_convert (GimpColorDisplay *display, guchar *buf, @@ -344,6 +385,8 @@ gimp_color_display_convert (GimpColorDisplay *display, { g_return_if_fail (GIMP_IS_COLOR_DISPLAY (display)); + /* implementing the convert method is deprecated + */ if (display->enabled && GIMP_COLOR_DISPLAY_GET_CLASS (display)->convert) GIMP_COLOR_DISPLAY_GET_CLASS (display)->convert (display, buf, width, height, diff --git a/libgimpwidgets/gimpcolordisplay.h b/libgimpwidgets/gimpcolordisplay.h index d187c633cf..9b6a806569 100644 --- a/libgimpwidgets/gimpcolordisplay.h +++ b/libgimpwidgets/gimpcolordisplay.h @@ -56,6 +56,7 @@ struct _GimpColorDisplayClass /* implementing the GimpColorDisplay::clone method is deprecated */ GimpColorDisplay * (* clone) (GimpColorDisplay *display); + /* implementing the GimpColorDisplay::convert method is deprecated */ void (* convert) (GimpColorDisplay *display, guchar *buf, gint width, @@ -80,8 +81,10 @@ struct _GimpColorDisplayClass const gchar *stock_id; + void (* convert_surface) (GimpColorDisplay *display, + cairo_surface_t *surface); + /* Padding for future expansion */ - void (* _gimp_reserved2) (void); void (* _gimp_reserved3) (void); void (* _gimp_reserved4) (void); }; @@ -95,12 +98,16 @@ GimpColorDisplay * gimp_color_display_new (GType display_typ GimpColorDisplay * gimp_color_display_clone (GimpColorDisplay *display); +void gimp_color_display_convert_surface (GimpColorDisplay *display, + cairo_surface_t *surface); +#ifndef GIMP_DISABLE_DEPRECATED void gimp_color_display_convert (GimpColorDisplay *display, guchar *buf, gint width, gint height, gint bpp, gint bpl); +#endif void gimp_color_display_load_state (GimpColorDisplay *display, GimpParasite *state); GimpParasite * gimp_color_display_save_state (GimpColorDisplay *display); diff --git a/libgimpwidgets/gimpcolordisplaystack.c b/libgimpwidgets/gimpcolordisplaystack.c index 8b32fa41b2..90b9d69b50 100644 --- a/libgimpwidgets/gimpcolordisplaystack.c +++ b/libgimpwidgets/gimpcolordisplaystack.c @@ -27,6 +27,7 @@ #include "gimpwidgetstypes.h" +#undef GIMP_DISABLE_DEPRECATED #include "gimpcolordisplay.h" #include "gimpcolordisplaystack.h" #include "gimpwidgetsmarshal.h" @@ -283,6 +284,47 @@ gimp_color_display_stack_reorder_down (GimpColorDisplayStack *stack, } } +/** + * gimp_color_display_stack_convert_surface: + * @display: a #GimpColorDisplayStack + * @surface: a #cairo_image_surface_t of type ARGB32 + * + * Runs all the stack's filters on all pixels in @surface. + * + * Since: GIMP 2.8 + **/ +void +gimp_color_display_stack_convert_surface (GimpColorDisplayStack *stack, + cairo_surface_t *surface) +{ + GList *list; + + g_return_if_fail (GIMP_IS_COLOR_DISPLAY_STACK (stack)); + g_return_if_fail (surface != NULL); + g_return_if_fail (cairo_surface_get_type (surface) == + CAIRO_SURFACE_TYPE_IMAGE); + + for (list = stack->filters; list; list = g_list_next (list)) + { + GimpColorDisplay *display = list->data; + + gimp_color_display_convert_surface (display, surface); + } +} + +/** + * gimp_color_display_stack_convert: + * @display: a #GimpColorDisplayStack + * @buf: the pixel buffer to convert + * @width: the width of the buffer + * @height: the height of the buffer + * @bpp: the number of bytes per pixel + * @bpl: the buffer's rowstride + * + * Converts all pixels in @buf. + * + * Deprecated: GIMP 2.8: Use gimp_color_display_stack_convert_surface() instead. + **/ void gimp_color_display_stack_convert (GimpColorDisplayStack *stack, guchar *buf, diff --git a/libgimpwidgets/gimpcolordisplaystack.h b/libgimpwidgets/gimpcolordisplaystack.h index 727d2a3c0e..d561cdd0b7 100644 --- a/libgimpwidgets/gimpcolordisplaystack.h +++ b/libgimpwidgets/gimpcolordisplaystack.h @@ -71,24 +71,26 @@ GType gimp_color_display_stack_get_type (void) G_GNUC_CONST; GimpColorDisplayStack * gimp_color_display_stack_new (void); GimpColorDisplayStack * gimp_color_display_stack_clone (GimpColorDisplayStack *stack); -void gimp_color_display_stack_changed (GimpColorDisplayStack *stack); - -void gimp_color_display_stack_add (GimpColorDisplayStack *stack, - GimpColorDisplay *display); -void gimp_color_display_stack_remove (GimpColorDisplayStack *stack, - GimpColorDisplay *display); -void gimp_color_display_stack_reorder_up (GimpColorDisplayStack *stack, - GimpColorDisplay *display); -void gimp_color_display_stack_reorder_down (GimpColorDisplayStack *stack, - GimpColorDisplay *display); - -void gimp_color_display_stack_convert (GimpColorDisplayStack *stack, - guchar *buf, - gint width, - gint height, - gint bpp, - gint bpl); +void gimp_color_display_stack_changed (GimpColorDisplayStack *stack); +void gimp_color_display_stack_add (GimpColorDisplayStack *stack, + GimpColorDisplay *display); +void gimp_color_display_stack_remove (GimpColorDisplayStack *stack, + GimpColorDisplay *display); +void gimp_color_display_stack_reorder_up (GimpColorDisplayStack *stack, + GimpColorDisplay *display); +void gimp_color_display_stack_reorder_down (GimpColorDisplayStack *stack, + GimpColorDisplay *display); +void gimp_color_display_stack_convert_surface (GimpColorDisplayStack *stack, + cairo_surface_t *surface); +#ifndef GIMP_DISABLE_DEPRECATED +void gimp_color_display_stack_convert (GimpColorDisplayStack *stack, + guchar *buf, + gint width, + gint height, + gint bpp, + gint bpl); +#endif G_END_DECLS diff --git a/modules/display-filter-color-blind.c b/modules/display-filter-color-blind.c index 4e6159ca44..dcad8cb835 100644 --- a/modules/display-filter-color-blind.c +++ b/modules/display-filter-color-blind.c @@ -112,28 +112,24 @@ enum }; -GType cdisplay_colorblind_get_type (void); +GType cdisplay_colorblind_get_type (void); -static void cdisplay_colorblind_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec); -static void cdisplay_colorblind_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec); +static void cdisplay_colorblind_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void cdisplay_colorblind_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); -static void cdisplay_colorblind_convert (GimpColorDisplay *display, - guchar *buf, - gint w, - gint h, - gint bpp, - gint bpl); -static GtkWidget * cdisplay_colorblind_configure (GimpColorDisplay *display); -static void cdisplay_colorblind_changed (GimpColorDisplay *display); +static void cdisplay_colorblind_convert_surface (GimpColorDisplay *display, + cairo_surface_t *surface); +static GtkWidget * cdisplay_colorblind_configure (GimpColorDisplay *display); +static void cdisplay_colorblind_changed (GimpColorDisplay *display); -static void cdisplay_colorblind_set_deficiency (CdisplayColorblind *colorblind, - ColorblindDeficiency value); +static void cdisplay_colorblind_set_deficiency (CdisplayColorblind *colorblind, + ColorblindDeficiency value); /* The RGB<->LMS transforms above are computed from the human cone @@ -147,7 +143,7 @@ static void cdisplay_colorblind_set_deficiency (CdisplayColorblind *col * following are the gamma estimates that we have used in the * Vischeck code. Many colorblind users have viewed our simulations * and told us that they "work" (simulated and original images are - * indistinguishabled). + * indistinguishable). */ static const gfloat gammaRGB = 2.1; @@ -248,8 +244,8 @@ cdisplay_colorblind_class_init (CdisplayColorblindClass *klass) GObjectClass *object_class = G_OBJECT_CLASS (klass); GimpColorDisplayClass *display_class = GIMP_COLOR_DISPLAY_CLASS (klass); - object_class->get_property = cdisplay_colorblind_get_property; - object_class->set_property = cdisplay_colorblind_set_property; + object_class->get_property = cdisplay_colorblind_get_property; + object_class->set_property = cdisplay_colorblind_set_property; GIMP_CONFIG_INSTALL_PROP_ENUM (object_class, PROP_DEFICIENCY, "deficiency", NULL, @@ -257,13 +253,13 @@ cdisplay_colorblind_class_init (CdisplayColorblindClass *klass) DEFAULT_DEFICIENCY, 0); - display_class->name = _("Color Deficient Vision"); - display_class->help_id = "gimp-colordisplay-colorblind"; - display_class->stock_id = GIMP_STOCK_DISPLAY_FILTER_COLORBLIND; + display_class->name = _("Color Deficient Vision"); + display_class->help_id = "gimp-colordisplay-colorblind"; + display_class->stock_id = GIMP_STOCK_DISPLAY_FILTER_COLORBLIND; - display_class->convert = cdisplay_colorblind_convert; - display_class->configure = cdisplay_colorblind_configure; - display_class->changed = cdisplay_colorblind_changed; + display_class->convert_surface = cdisplay_colorblind_convert_surface; + display_class->configure = cdisplay_colorblind_configure; + display_class->changed = cdisplay_colorblind_changed; } static void @@ -359,55 +355,61 @@ lut_lookup (gfloat value, } static void -cdisplay_colorblind_convert (GimpColorDisplay *display, - guchar *buf, - gint width, - gint height, - gint bpp, - gint bpl) +cdisplay_colorblind_convert_surface (GimpColorDisplay *display, + cairo_surface_t *surface) { CdisplayColorblind *colorblind = CDISPLAY_COLORBLIND (display); - const gfloat a1 = colorblind->a1; - const gfloat b1 = colorblind->b1; - const gfloat c1 = colorblind->c1; - const gfloat a2 = colorblind->a2; - const gfloat b2 = colorblind->b2; - const gfloat c2 = colorblind->c2; - gfloat tmp; - gfloat red, green, blue; - gfloat redOld, greenOld; - guchar *b; - gint x, y; + gint width = cairo_image_surface_get_width (surface); + gint height = cairo_image_surface_get_height (surface); + gint stride = cairo_image_surface_get_stride (surface); + guchar *buf = cairo_image_surface_get_data (surface); + cairo_format_t fmt = cairo_image_surface_get_format (surface); + const gfloat a1 = colorblind->a1; + const gfloat b1 = colorblind->b1; + const gfloat c1 = colorblind->c1; + const gfloat a2 = colorblind->a2; + const gfloat b2 = colorblind->b2; + const gfloat c2 = colorblind->c2; + gfloat tmp; + gfloat red, green, blue; + gfloat redOld, greenOld; + guchar r, g, b, a; + gint x, y, skip; - /* Require 3 bytes per pixel (assume RGB) */ - if (bpp != 3) + /* Require ARGB32 pixel format */ + if (fmt != CAIRO_FORMAT_ARGB32) return; - for (y = 0; y < height; y++, buf += bpl) - for (x = 0, b = buf; x < width; x++, b += bpp) + skip = stride - 4 * width; + + for (y = 0; y < height; y++, buf += skip) + for (x = 0; x < width; x++, buf += 4) { guint32 pixel; guint index; /* First check our cache */ - pixel = b[0] << 16 | b[1] << 8 | b[2]; + GIMP_CAIRO_ARGB32_GET_PIXEL (buf, r, g, b, a); + pixel = r << 16 | g << 8 | b; index = pixel % COLOR_CACHE_SIZE; if (colorblind->cache[2 * index] == pixel) { pixel = colorblind->cache[2 * index + 1]; - b[2] = pixel & 0xFF; pixel >>= 8; - b[1] = pixel & 0xFF; pixel >>= 8; - b[0] = pixel & 0xFF; + b = pixel & 0xFF; pixel >>= 8; + g = pixel & 0xFF; pixel >>= 8; + r = pixel & 0xFF; + + GIMP_CAIRO_ARGB32_SET_PIXEL (buf, r, g, b, a); continue; } /* Remove gamma to linearize RGB intensities */ - red = colorblind->gamma_lut[b[0]]; - green = colorblind->gamma_lut[b[1]]; - blue = colorblind->gamma_lut[b[2]]; + red = colorblind->gamma_lut[r]; + green = colorblind->gamma_lut[g]; + blue = colorblind->gamma_lut[b]; /* Convert to LMS (dot product with transform matrix) */ redOld = red; @@ -459,13 +461,14 @@ cdisplay_colorblind_convert (GimpColorDisplay *display, blue = redOld * lms2rgb[6] + greenOld * lms2rgb[7] + blue * lms2rgb[8]; /* Apply gamma to go back to non-linear intensities */ - b[0] = lut_lookup (red, colorblind->gamma_lut); - b[1] = lut_lookup (green, colorblind->gamma_lut); - b[2] = lut_lookup (blue, colorblind->gamma_lut); + r = lut_lookup (red, colorblind->gamma_lut); + g = lut_lookup (green, colorblind->gamma_lut); + b = lut_lookup (blue, colorblind->gamma_lut); + GIMP_CAIRO_ARGB32_SET_PIXEL (buf, r, g, b, a); /* Put the result into our cache */ colorblind->cache[2 * index] = pixel; - colorblind->cache[2 * index + 1] = b[0] << 16 | b[1] << 8 | b[2]; + colorblind->cache[2 * index + 1] = r << 16 | g << 8 | b; } } diff --git a/modules/display-filter-gamma.c b/modules/display-filter-gamma.c index f228b76b32..797bd16914 100644 --- a/modules/display-filter-gamma.c +++ b/modules/display-filter-gamma.c @@ -61,26 +61,22 @@ enum }; -GType cdisplay_gamma_get_type (void); +GType cdisplay_gamma_get_type (void); -static void cdisplay_gamma_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec); -static void cdisplay_gamma_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec); +static void cdisplay_gamma_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void cdisplay_gamma_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); -static void cdisplay_gamma_convert (GimpColorDisplay *display, - guchar *buf, - gint w, - gint h, - gint bpp, - gint bpl); -static GtkWidget * cdisplay_gamma_configure (GimpColorDisplay *display); -static void cdisplay_gamma_set_gamma (CdisplayGamma *gamma, - gdouble value); +static void cdisplay_gamma_convert_surface (GimpColorDisplay *display, + cairo_surface_t *surface); +static GtkWidget * cdisplay_gamma_configure (GimpColorDisplay *display); +static void cdisplay_gamma_set_gamma (CdisplayGamma *gamma, + gdouble value); static const GimpModuleInfo cdisplay_gamma_info = @@ -117,20 +113,20 @@ cdisplay_gamma_class_init (CdisplayGammaClass *klass) GObjectClass *object_class = G_OBJECT_CLASS (klass); GimpColorDisplayClass *display_class = GIMP_COLOR_DISPLAY_CLASS (klass); - object_class->get_property = cdisplay_gamma_get_property; - object_class->set_property = cdisplay_gamma_set_property; + object_class->get_property = cdisplay_gamma_get_property; + object_class->set_property = cdisplay_gamma_set_property; GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_GAMMA, "gamma", NULL, 0.01, 10.0, DEFAULT_GAMMA, 0); - display_class->name = _("Gamma"); - display_class->help_id = "gimp-colordisplay-gamma"; - display_class->stock_id = GIMP_STOCK_DISPLAY_FILTER_GAMMA; + display_class->name = _("Gamma"); + display_class->help_id = "gimp-colordisplay-gamma"; + display_class->stock_id = GIMP_STOCK_DISPLAY_FILTER_GAMMA; - display_class->convert = cdisplay_gamma_convert; - display_class->configure = cdisplay_gamma_configure; + display_class->convert_surface = cdisplay_gamma_convert_surface; + display_class->configure = cdisplay_gamma_configure; } static void @@ -182,15 +178,20 @@ cdisplay_gamma_set_property (GObject *object, } static void -cdisplay_gamma_convert (GimpColorDisplay *display, - guchar *buf, - gint width, - gint height, - gint bpp, - gint bpl) +cdisplay_gamma_convert_surface (GimpColorDisplay *display, + cairo_surface_t *surface) { - CdisplayGamma *gamma = CDISPLAY_GAMMA (display); - gint i, j = height; + CdisplayGamma *gamma = CDISPLAY_GAMMA (display); + gint width = cairo_image_surface_get_width (surface); + gint height = cairo_image_surface_get_height (surface); + gint stride = cairo_image_surface_get_stride (surface); + guchar *buf = cairo_image_surface_get_data (surface); + cairo_format_t fmt = cairo_image_surface_get_format (surface); + gint i, j, skip; + gint r, g, b, a; + + if (fmt != CAIRO_FORMAT_ARGB32) + return; /* You will not be using the entire buffer most of the time. * Hence, the simplistic code for this is as follows: @@ -203,18 +204,22 @@ cdisplay_gamma_convert (GimpColorDisplay *display, * } */ - width *= bpp; - bpl -= width; + j = height; + skip = stride - 4 * width; while (j--) { i = width; while (i--) { - *buf = gamma->lookup[*buf]; - buf++; + GIMP_CAIRO_ARGB32_GET_PIXEL (buf, r, g, b, a); + r = gamma->lookup[r]; + g = gamma->lookup[g]; + b = gamma->lookup[b]; + GIMP_CAIRO_ARGB32_SET_PIXEL (buf, r, g, b, a); + buf += 4; } - buf += bpl; + buf += skip; } } diff --git a/modules/display-filter-high-contrast.c b/modules/display-filter-high-contrast.c index 48091ad5ed..550aceea0b 100644 --- a/modules/display-filter-high-contrast.c +++ b/modules/display-filter-high-contrast.c @@ -61,26 +61,22 @@ enum }; -GType cdisplay_contrast_get_type (void); +GType cdisplay_contrast_get_type (void); -static void cdisplay_contrast_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec); -static void cdisplay_contrast_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec); +static void cdisplay_contrast_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void cdisplay_contrast_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); -static void cdisplay_contrast_convert (GimpColorDisplay *display, - guchar *buf, - gint w, - gint h, - gint bpp, - gint bpl); -static GtkWidget * cdisplay_contrast_configure (GimpColorDisplay *display); -static void cdisplay_contrast_set_contrast (CdisplayContrast *contrast, - gdouble value); +static void cdisplay_contrast_convert_surface (GimpColorDisplay *display, + cairo_surface_t *surface); +static GtkWidget * cdisplay_contrast_configure (GimpColorDisplay *display); +static void cdisplay_contrast_set_contrast (CdisplayContrast *contrast, + gdouble value); static const GimpModuleInfo cdisplay_contrast_info = @@ -117,20 +113,20 @@ cdisplay_contrast_class_init (CdisplayContrastClass *klass) GObjectClass *object_class = G_OBJECT_CLASS (klass); GimpColorDisplayClass *display_class = GIMP_COLOR_DISPLAY_CLASS (klass); - object_class->get_property = cdisplay_contrast_get_property; - object_class->set_property = cdisplay_contrast_set_property; + object_class->get_property = cdisplay_contrast_get_property; + object_class->set_property = cdisplay_contrast_set_property; GIMP_CONFIG_INSTALL_PROP_DOUBLE (object_class, PROP_CONTRAST, "contrast", NULL, 0.01, 10.0, DEFAULT_CONTRAST, 0); - display_class->name = _("Contrast"); - display_class->help_id = "gimp-colordisplay-contrast"; - display_class->stock_id = GIMP_STOCK_DISPLAY_FILTER_CONTRAST; + display_class->name = _("Contrast"); + display_class->help_id = "gimp-colordisplay-contrast"; + display_class->stock_id = GIMP_STOCK_DISPLAY_FILTER_CONTRAST; - display_class->convert = cdisplay_contrast_convert; - display_class->configure = cdisplay_contrast_configure; + display_class->convert_surface = cdisplay_contrast_convert_surface; + display_class->configure = cdisplay_contrast_configure; } static void @@ -182,15 +178,20 @@ cdisplay_contrast_set_property (GObject *object, } static void -cdisplay_contrast_convert (GimpColorDisplay *display, - guchar *buf, - gint width, - gint height, - gint bpp, - gint bpl) +cdisplay_contrast_convert_surface (GimpColorDisplay *display, + cairo_surface_t *surface) { CdisplayContrast *contrast = CDISPLAY_CONTRAST (display); - gint i, j = height; + gint width = cairo_image_surface_get_width (surface); + gint height = cairo_image_surface_get_height (surface); + gint stride = cairo_image_surface_get_stride (surface); + guchar *buf = cairo_image_surface_get_data (surface); + cairo_format_t fmt = cairo_image_surface_get_format (surface); + gint i, j, skip; + gint r, g, b, a; + + if (fmt != CAIRO_FORMAT_ARGB32) + return; /* You will not be using the entire buffer most of the time. * Hence, the simplistic code for this is as follows: @@ -203,18 +204,22 @@ cdisplay_contrast_convert (GimpColorDisplay *display, * } */ - width *= bpp; - bpl -= width; + j = height; + skip = stride - 4 * width; while (j--) { i = width; while (i--) { - *buf = contrast->lookup[*buf]; - buf++; + GIMP_CAIRO_ARGB32_GET_PIXEL (buf, r, g, b, a); + r = contrast->lookup[r]; + g = contrast->lookup[g]; + b = contrast->lookup[b]; + GIMP_CAIRO_ARGB32_SET_PIXEL (buf, r, g, b, a); + buf += 4; } - buf += bpl; + buf += skip; } } diff --git a/modules/display-filter-lcms.c b/modules/display-filter-lcms.c index 5cd5da338b..bde16109f8 100644 --- a/modules/display-filter-lcms.c +++ b/modules/display-filter-lcms.c @@ -51,7 +51,7 @@ #define CDISPLAY_IS_LCMS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CDISPLAY_TYPE_LCMS)) -typedef struct _CdisplayLcms CdisplayLcms; +typedef struct _CdisplayLcms CdisplayLcms; typedef struct _CdisplayLcmsClass CdisplayLcmsClass; struct _CdisplayLcms @@ -67,32 +67,28 @@ struct _CdisplayLcmsClass }; -GType cdisplay_lcms_get_type (void); +GType cdisplay_lcms_get_type (void); -static void cdisplay_lcms_finalize (GObject *object); +static void cdisplay_lcms_finalize (GObject *object); -static GtkWidget * cdisplay_lcms_configure (GimpColorDisplay *display); -static void cdisplay_lcms_convert (GimpColorDisplay *display, - guchar *buf, - gint width, - gint height, - gint bpp, - gint bpl); -static void cdisplay_lcms_changed (GimpColorDisplay *display); +static GtkWidget * cdisplay_lcms_configure (GimpColorDisplay *display); +static void cdisplay_lcms_convert_surface (GimpColorDisplay *display, + cairo_surface_t *surface); +static void cdisplay_lcms_changed (GimpColorDisplay *display); -static cmsHPROFILE cdisplay_lcms_get_rgb_profile (CdisplayLcms *lcms); -static cmsHPROFILE cdisplay_lcms_get_display_profile (CdisplayLcms *lcms); -static cmsHPROFILE cdisplay_lcms_get_printer_profile (CdisplayLcms *lcms); +static cmsHPROFILE cdisplay_lcms_get_rgb_profile (CdisplayLcms *lcms); +static cmsHPROFILE cdisplay_lcms_get_display_profile (CdisplayLcms *lcms); +static cmsHPROFILE cdisplay_lcms_get_printer_profile (CdisplayLcms *lcms); -static void cdisplay_lcms_attach_labelled (GtkTable *table, - gint row, - const gchar *text, - GtkWidget *widget); -static void cdisplay_lcms_update_profile_label (CdisplayLcms *lcms, - const gchar *name); -static void cdisplay_lcms_notify_profile (GObject *config, - GParamSpec *pspec, - CdisplayLcms *lcms); +static void cdisplay_lcms_attach_labelled (GtkTable *table, + gint row, + const gchar *text, + GtkWidget *widget); +static void cdisplay_lcms_update_profile_label (CdisplayLcms *lcms, + const gchar *name); +static void cdisplay_lcms_notify_profile (GObject *config, + GParamSpec *pspec, + CdisplayLcms *lcms); static const GimpModuleInfo cdisplay_lcms_info = @@ -128,15 +124,15 @@ cdisplay_lcms_class_init (CdisplayLcmsClass *klass) GObjectClass *object_class = G_OBJECT_CLASS (klass); GimpColorDisplayClass *display_class = GIMP_COLOR_DISPLAY_CLASS (klass); - object_class->finalize = cdisplay_lcms_finalize; + object_class->finalize = cdisplay_lcms_finalize; - display_class->name = _("Color Management"); - display_class->help_id = "gimp-colordisplay-lcms"; - display_class->stock_id = GIMP_STOCK_DISPLAY_FILTER_LCMS; + display_class->name = _("Color Management"); + display_class->help_id = "gimp-colordisplay-lcms"; + display_class->stock_id = GIMP_STOCK_DISPLAY_FILTER_LCMS; - display_class->configure = cdisplay_lcms_configure; - display_class->convert = cdisplay_lcms_convert; - display_class->changed = cdisplay_lcms_changed; + display_class->configure = cdisplay_lcms_configure; + display_class->convert_surface = cdisplay_lcms_convert_surface; + display_class->changed = cdisplay_lcms_changed; cmsErrorAction (LCMS_ERROR_IGNORE); } @@ -257,24 +253,55 @@ cdisplay_lcms_configure (GimpColorDisplay *display) } static void -cdisplay_lcms_convert (GimpColorDisplay *display, - guchar *buf, - gint width, - gint height, - gint bpp, - gint bpl) +cdisplay_lcms_convert_surface (GimpColorDisplay *display, + cairo_surface_t *surface) { - CdisplayLcms *lcms = CDISPLAY_LCMS (display); - gint y; + CdisplayLcms *lcms = CDISPLAY_LCMS (display); + gint width = cairo_image_surface_get_width (surface); + gint height = cairo_image_surface_get_height (surface); + gint stride = cairo_image_surface_get_stride (surface); + guchar *buf = cairo_image_surface_get_data (surface); + cairo_format_t fmt = cairo_image_surface_get_format (surface); + guchar *rowbuf; + gint x, y; + guchar r, g, b, a; - if (bpp != 3) + if (fmt != CAIRO_FORMAT_ARGB32) return; if (! lcms->transform) return; - for (y = 0; y < height; y++, buf += bpl) - cmsDoTransform (lcms->transform, buf, buf, width); + rowbuf = g_malloc (stride); + + for (y = 0; y < height; y++, buf += stride) + { + /* Switch buf from ARGB premul to ARGB non-premul, since lcms ignores the + * alpha channel. The macro takes care of byte order. + */ + for (x = 0; x < width; x++) + { + GIMP_CAIRO_ARGB32_GET_PIXEL (buf + 4*x, r, g, b, a); + rowbuf[4*x+0] = a; + rowbuf[4*x+1] = r; + rowbuf[4*x+2] = g; + rowbuf[4*x+3] = b; + } + + cmsDoTransform (lcms->transform, rowbuf, rowbuf, width); + + /* And back to ARGB premul */ + for (x = 0; x < width; x++) + { + a = rowbuf[4*x+0]; + r = rowbuf[4*x+1]; + g = rowbuf[4*x+2]; + b = rowbuf[4*x+3]; + GIMP_CAIRO_ARGB32_SET_PIXEL (buf + 4*x, r, g, b, a); + } + } + + g_free (rowbuf); } static void @@ -339,8 +366,8 @@ cdisplay_lcms_changed (GimpColorDisplay *display) cmsSetAlarmCodes (r, g, b); } - lcms->transform = cmsCreateProofingTransform (src_profile, TYPE_RGB_8, - dest_profile, TYPE_RGB_8, + lcms->transform = cmsCreateProofingTransform (src_profile, TYPE_ARGB_8, + dest_profile, TYPE_ARGB_8, proof_profile, config->simulation_intent, config->display_intent, @@ -355,8 +382,8 @@ cdisplay_lcms_changed (GimpColorDisplay *display) if (! dest_profile) dest_profile = cmsCreate_sRGBProfile (); - lcms->transform = cmsCreateTransform (src_profile, TYPE_RGB_8, - dest_profile, TYPE_RGB_8, + lcms->transform = cmsCreateTransform (src_profile, TYPE_ARGB_8, + dest_profile, TYPE_ARGB_8, config->display_intent, flags); } diff --git a/modules/display-filter-proof.c b/modules/display-filter-proof.c index 8c14dd7977..a9e722b252 100644 --- a/modules/display-filter-proof.c +++ b/modules/display-filter-proof.c @@ -38,7 +38,7 @@ #define CDISPLAY_IS_PROOF_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CDISPLAY_TYPE_PROOF)) -typedef struct _CdisplayProof CdisplayProof; +typedef struct _CdisplayProof CdisplayProof; typedef struct _CdisplayProofClass CdisplayProofClass; struct _CdisplayProof @@ -67,27 +67,23 @@ enum }; -GType cdisplay_proof_get_type (void); +GType cdisplay_proof_get_type (void); -static void cdisplay_proof_finalize (GObject *object); -static void cdisplay_proof_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec); -static void cdisplay_proof_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec); +static void cdisplay_proof_finalize (GObject *object); +static void cdisplay_proof_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); +static void cdisplay_proof_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); -static void cdisplay_proof_convert (GimpColorDisplay *display, - guchar *buf, - gint width, - gint height, - gint bpp, - gint bpl); -static GtkWidget * cdisplay_proof_configure (GimpColorDisplay *display); -static void cdisplay_proof_changed (GimpColorDisplay *display); +static void cdisplay_proof_convert_surface (GimpColorDisplay *display, + cairo_surface_t *surface); +static GtkWidget * cdisplay_proof_configure (GimpColorDisplay *display); +static void cdisplay_proof_changed (GimpColorDisplay *display); static const GimpModuleInfo cdisplay_proof_info = @@ -123,9 +119,9 @@ cdisplay_proof_class_init (CdisplayProofClass *klass) GObjectClass *object_class = G_OBJECT_CLASS (klass); GimpColorDisplayClass *display_class = GIMP_COLOR_DISPLAY_CLASS (klass); - object_class->finalize = cdisplay_proof_finalize; - object_class->get_property = cdisplay_proof_get_property; - object_class->set_property = cdisplay_proof_set_property; + object_class->finalize = cdisplay_proof_finalize; + object_class->get_property = cdisplay_proof_get_property; + object_class->set_property = cdisplay_proof_set_property; GIMP_CONFIG_INSTALL_PROP_ENUM (object_class, PROP_INTENT, "intent", NULL, @@ -141,13 +137,13 @@ cdisplay_proof_class_init (CdisplayProofClass *klass) GIMP_CONFIG_PATH_FILE, NULL, 0); - display_class->name = _("Color Proof"); - display_class->help_id = "gimp-colordisplay-proof"; - display_class->stock_id = GIMP_STOCK_DISPLAY_FILTER_PROOF; + display_class->name = _("Color Proof"); + display_class->help_id = "gimp-colordisplay-proof"; + display_class->stock_id = GIMP_STOCK_DISPLAY_FILTER_PROOF; - display_class->convert = cdisplay_proof_convert; - display_class->configure = cdisplay_proof_configure; - display_class->changed = cdisplay_proof_changed; + display_class->convert_surface = cdisplay_proof_convert_surface; + display_class->configure = cdisplay_proof_configure; + display_class->changed = cdisplay_proof_changed; cmsErrorAction (LCMS_ERROR_IGNORE); } @@ -238,24 +234,55 @@ cdisplay_proof_set_property (GObject *object, } static void -cdisplay_proof_convert (GimpColorDisplay *display, - guchar *buf, - gint width, - gint height, - gint bpp, - gint bpl) +cdisplay_proof_convert_surface (GimpColorDisplay *display, + cairo_surface_t *surface) { - CdisplayProof *proof = CDISPLAY_PROOF (display); - gint y; + CdisplayProof *proof = CDISPLAY_PROOF (display); + gint width = cairo_image_surface_get_width (surface); + gint height = cairo_image_surface_get_height (surface); + gint stride = cairo_image_surface_get_stride (surface); + guchar *buf = cairo_image_surface_get_data (surface); + cairo_format_t fmt = cairo_image_surface_get_format (surface); + guchar *rowbuf; + gint x, y; + guchar r, g, b, a; - if (bpp != 3) + if (fmt != CAIRO_FORMAT_ARGB32) return; if (! proof->transform) return; - for (y = 0; y < height; y++, buf += bpl) - cmsDoTransform (proof->transform, buf, buf, width); + rowbuf = g_malloc (stride); + + for (y = 0; y < height; y++, buf += stride) + { + /* Switch buf from ARGB premul to ARGB non-premul, since lcms ignores the + * alpha channel. The macro takes care of byte order. + */ + for (x = 0; x < width; x++) + { + GIMP_CAIRO_ARGB32_GET_PIXEL (buf + 4*x, r, g, b, a); + rowbuf[4*x+0] = a; + rowbuf[4*x+1] = r; + rowbuf[4*x+2] = g; + rowbuf[4*x+3] = b; + } + + cmsDoTransform (proof->transform, rowbuf, rowbuf, width); + + /* And back to ARGB premul */ + for (x = 0; x < width; x++) + { + a = rowbuf[4*x+0]; + r = rowbuf[4*x+1]; + g = rowbuf[4*x+2]; + b = rowbuf[4*x+3]; + GIMP_CAIRO_ARGB32_SET_PIXEL (buf + 4*x, r, g, b, a); + } + } + + g_free (rowbuf); } static void @@ -442,9 +469,8 @@ cdisplay_proof_changed (GimpColorDisplay *display) if (proof->bpc) flags |= cmsFLAGS_BLACKPOINTCOMPENSATION; - proof->transform = cmsCreateProofingTransform (rgbProfile, - TYPE_RGB_8, - rgbProfile, TYPE_RGB_8, + proof->transform = cmsCreateProofingTransform (rgbProfile, TYPE_ARGB_8, + rgbProfile, TYPE_ARGB_8, proofProfile, proof->intent, proof->intent, diff --git a/plug-ins/pygimp/gimpui.defs b/plug-ins/pygimp/gimpui.defs index 3319451c01..e0efe329e7 100644 --- a/plug-ins/pygimp/gimpui.defs +++ b/plug-ins/pygimp/gimpui.defs @@ -798,6 +798,15 @@ (return-type "GimpColorDisplay*") ) +(define-method convert_surface + (of-object "GimpColorDisplay") + (c-name "gimp_color_display_convert_surface") + (return-type "none") + (parameters + '("cairo_surface_t*" "surface") + ) +) + (define-method convert (of-object "GimpColorDisplay") (c-name "gimp_color_display_convert") @@ -809,6 +818,7 @@ '("gint" "bpp") '("gint" "bpl") ) + (deprecated "use convert_surface(cairo_surface_t*) instead") ) (define-method load_state @@ -934,6 +944,15 @@ ) ) +(define-method convert_surface + (of-object "GimpColorDisplayStack") + (c-name "gimp_color_display_stack_convert_surface") + (return-type "none") + (parameters + '("cairo_surface_t*" "surface") + ) +) + (define-method convert (of-object "GimpColorDisplayStack") (c-name "gimp_color_display_stack_convert") @@ -945,6 +964,7 @@ '("gint" "bpp") '("gint" "bpl") ) + (deprecated "use convert_surface(cairo_surface_t*) instead") )