[gimp] Bug 478528 - Layer and Image previews are not color managed
- From: Michael Natterer <mitch src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] Bug 478528 - Layer and Image previews are not color managed
- Date: Fri, 15 Apr 2016 15:56:52 +0000 (UTC)
commit 9e8499bb48c8ceda5864e0b877ffb7a43a22d605
Author: Michael Natterer <mitch gimp org>
Date: Fri Apr 15 16:52:25 2016 +0100
Bug 478528 - Layer and Image previews are not color managed
Change gimp_viewable_get_[new]_preview() to return buffers of the
image's and layers' colorspace, but in u8. This way layer and image
previews can transform them correctly to the display profile.
Note: this makes plug-ins receive thumbnail buffers in that
pixel format too.
Also change gimp_viewable_get_[new]_pixbuf() to always return sRGB
buffers that can reasonably be put to screen directly, or put into DND
buffers. This is at least more correct now.
app/core/gimpdrawable-preview.c | 149 +++++++++++++++++++++++++++++++++++++--
app/core/gimpdrawable-preview.h | 14 ++++-
app/core/gimpdrawable.c | 1 +
app/core/gimpimage-preview.c | 83 +++++++++++++++++++++-
app/core/gimpimage-preview.h | 4 +
app/core/gimpimage.c | 1 +
6 files changed, 244 insertions(+), 8 deletions(-)
---
diff --git a/app/core/gimpdrawable-preview.c b/app/core/gimpdrawable-preview.c
index c4647c8..6e1ce74 100644
--- a/app/core/gimpdrawable-preview.c
+++ b/app/core/gimpdrawable-preview.c
@@ -19,18 +19,24 @@
#include <string.h>
+#include <cairo.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <gegl.h>
+#include "libgimpcolor/gimpcolor.h"
#include "libgimpmath/gimpmath.h"
#include "core-types.h"
#include "config/gimpcoreconfig.h"
+#include "gegl/gimp-babl.h"
+#include "gegl/gimp-gegl-loops.h"
+
#include "gimp.h"
#include "gimpchannel.h"
#include "gimpimage.h"
+#include "gimpimage-color-profile.h"
#include "gimpdrawable-preview.h"
#include "gimpdrawable-private.h"
#include "gimplayer.h"
@@ -59,22 +65,53 @@ gimp_drawable_get_new_preview (GimpViewable *viewable,
height);
}
+GdkPixbuf *
+gimp_drawable_get_new_pixbuf (GimpViewable *viewable,
+ GimpContext *context,
+ gint width,
+ gint height)
+{
+ GimpItem *item = GIMP_ITEM (viewable);
+ GimpImage *image = gimp_item_get_image (item);
+
+ if (! image->gimp->config->layer_previews)
+ return NULL;
+
+ return gimp_drawable_get_sub_pixbuf (GIMP_DRAWABLE (viewable),
+ 0, 0,
+ gimp_item_get_width (item),
+ gimp_item_get_height (item),
+ width,
+ height);
+}
+
const Babl *
gimp_drawable_get_preview_format (GimpDrawable *drawable)
{
+ gboolean alpha;
+ gboolean linear;
+
g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
+ alpha = gimp_drawable_has_alpha (drawable);
+ linear = gimp_drawable_get_linear (drawable);
+
switch (gimp_drawable_get_base_type (drawable))
{
case GIMP_GRAY:
- if (gimp_drawable_has_alpha (drawable))
- return babl_format ("Y'A u8");
- else
- return babl_format ("Y' u8");
+ return gimp_babl_format (GIMP_GRAY,
+ gimp_babl_precision (GIMP_COMPONENT_TYPE_U8,
+ linear),
+ alpha);
case GIMP_RGB:
+ return gimp_babl_format (GIMP_RGB,
+ gimp_babl_precision (GIMP_COMPONENT_TYPE_U8,
+ linear),
+ alpha);
+
case GIMP_INDEXED:
- if (gimp_drawable_has_alpha (drawable))
+ if (alpha)
return babl_format ("R'G'B'A u8");
else
return babl_format ("R'G'B' u8");
@@ -138,3 +175,105 @@ gimp_drawable_get_sub_preview (GimpDrawable *drawable,
return preview;
}
+
+GdkPixbuf *
+gimp_drawable_get_sub_pixbuf (GimpDrawable *drawable,
+ gint src_x,
+ gint src_y,
+ gint src_width,
+ gint src_height,
+ gint dest_width,
+ gint dest_height)
+{
+ GimpItem *item;
+ GimpImage *image;
+ GeglBuffer *buffer;
+ GdkPixbuf *pixbuf;
+ gdouble scale;
+ gint scaled_x;
+ gint scaled_y;
+ GimpColorTransform transform;
+ const Babl *src_format;
+ const Babl *dest_format;
+
+ g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
+ g_return_val_if_fail (src_x >= 0, NULL);
+ g_return_val_if_fail (src_y >= 0, NULL);
+ g_return_val_if_fail (src_width > 0, NULL);
+ g_return_val_if_fail (src_height > 0, NULL);
+ g_return_val_if_fail (dest_width > 0, NULL);
+ g_return_val_if_fail (dest_height > 0, NULL);
+
+ item = GIMP_ITEM (drawable);
+
+ g_return_val_if_fail ((src_x + src_width) <= gimp_item_get_width (item), NULL);
+ g_return_val_if_fail ((src_y + src_height) <= gimp_item_get_height (item), NULL);
+
+ image = gimp_item_get_image (item);
+
+ if (! image->gimp->config->layer_previews)
+ return NULL;
+
+ buffer = gimp_drawable_get_buffer (drawable);
+
+ pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
+ dest_width, dest_height);
+
+ scale = MIN ((gdouble) dest_width / (gdouble) src_width,
+ (gdouble) dest_height / (gdouble) src_height);
+
+ scaled_x = RINT ((gdouble) src_x * scale);
+ scaled_y = RINT ((gdouble) src_y * scale);
+
+ transform = gimp_image_get_color_transform_to_srgb_u8 (image,
+ &src_format,
+ &dest_format);
+
+ if (transform)
+ {
+ GimpTempBuf *temp_buf;
+ GeglBuffer *src_buf;
+ GeglBuffer *dest_buf;
+
+ temp_buf = gimp_temp_buf_new (dest_width, dest_height, src_format);
+
+ gegl_buffer_get (buffer,
+ GEGL_RECTANGLE (scaled_x, scaled_y,
+ dest_width, dest_height),
+ scale,
+ gimp_temp_buf_get_format (temp_buf),
+ gimp_temp_buf_get_data (temp_buf),
+ GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_CLAMP);
+
+ src_buf = gimp_temp_buf_create_buffer (temp_buf);
+ dest_buf = gimp_pixbuf_create_buffer (pixbuf);
+
+ gimp_temp_buf_unref (temp_buf);
+
+ gimp_gegl_convert_color_transform (src_buf,
+ GEGL_RECTANGLE (0, 0,
+ dest_width, dest_height),
+ src_format,
+ dest_buf,
+ GEGL_RECTANGLE (0, 0, 0, 0),
+ dest_format,
+ transform,
+ NULL);
+
+ g_object_unref (src_buf);
+ g_object_unref (dest_buf);
+ }
+ else
+ {
+ gegl_buffer_get (buffer,
+ GEGL_RECTANGLE (scaled_x, scaled_y,
+ dest_width, dest_height),
+ scale,
+ gimp_pixbuf_get_format (pixbuf),
+ gdk_pixbuf_get_pixels (pixbuf),
+ gdk_pixbuf_get_rowstride (pixbuf),
+ GEGL_ABYSS_CLAMP);
+ }
+
+ return pixbuf;
+}
diff --git a/app/core/gimpdrawable-preview.h b/app/core/gimpdrawable-preview.h
index 0a552ce..e058934 100644
--- a/app/core/gimpdrawable-preview.h
+++ b/app/core/gimpdrawable-preview.h
@@ -20,17 +20,22 @@
/*
- * virtual function of GimpDrawable -- dont't call directly
+ * virtual functions of GimpDrawable -- dont't call directly
*/
GimpTempBuf * gimp_drawable_get_new_preview (GimpViewable *viewable,
GimpContext *context,
gint width,
gint height);
+GdkPixbuf * gimp_drawable_get_new_pixbuf (GimpViewable *viewable,
+ GimpContext *context,
+ gint width,
+ gint height);
/*
* normal functions (no virtuals)
*/
const Babl * gimp_drawable_get_preview_format (GimpDrawable *drawable);
+
GimpTempBuf * gimp_drawable_get_sub_preview (GimpDrawable *drawable,
gint src_x,
gint src_y,
@@ -38,6 +43,13 @@ GimpTempBuf * gimp_drawable_get_sub_preview (GimpDrawable *drawable,
gint src_height,
gint dest_width,
gint dest_height);
+GdkPixbuf * gimp_drawable_get_sub_pixbuf (GimpDrawable *drawable,
+ gint src_x,
+ gint src_y,
+ gint src_width,
+ gint src_height,
+ gint dest_width,
+ gint dest_height);
#endif /* __GIMP_DRAWABLE__PREVIEW_H__ */
diff --git a/app/core/gimpdrawable.c b/app/core/gimpdrawable.c
index 2af04d1..bc96c1f 100644
--- a/app/core/gimpdrawable.c
+++ b/app/core/gimpdrawable.c
@@ -245,6 +245,7 @@ gimp_drawable_class_init (GimpDrawableClass *klass)
viewable_class->get_size = gimp_drawable_get_size;
viewable_class->get_new_preview = gimp_drawable_get_new_preview;
+ viewable_class->get_new_pixbuf = gimp_drawable_get_new_pixbuf;
filter_class->get_node = gimp_drawable_get_node;
diff --git a/app/core/gimpimage-preview.c b/app/core/gimpimage-preview.c
index 405a629..374ce9c 100644
--- a/app/core/gimpimage-preview.c
+++ b/app/core/gimpimage-preview.c
@@ -17,16 +17,20 @@
#include "config.h"
+#include <cairo.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <gegl.h>
+#include "libgimpcolor/gimpcolor.h"
+
#include "core-types.h"
#include "gegl/gimp-babl.h"
+#include "gegl/gimp-gegl-loops.h"
#include "gimpimage.h"
+#include "gimpimage-color-profile.h"
#include "gimpimage-preview.h"
-#include "gimpimage-private.h"
#include "gimppickable.h"
#include "gimpprojectable.h"
#include "gimpprojection.h"
@@ -103,6 +107,7 @@ gimp_image_get_new_preview (GimpViewable *viewable,
{
GimpImage *image = GIMP_IMAGE (viewable);
const Babl *format;
+ gboolean linear;
GimpTempBuf *buf;
gdouble scale_x;
gdouble scale_y;
@@ -111,8 +116,11 @@ gimp_image_get_new_preview (GimpViewable *viewable,
scale_y = (gdouble) height / (gdouble) gimp_image_get_height (image);
format = gimp_projectable_get_format (GIMP_PROJECTABLE (image));
+ linear = gimp_babl_format_get_linear (format);
+
format = gimp_babl_format (gimp_babl_format_get_base_type (format),
- GIMP_PRECISION_U8_GAMMA,
+ gimp_babl_precision (GIMP_COMPONENT_TYPE_U8,
+ linear),
babl_format_has_alpha (format));
buf = gimp_temp_buf_new (width, height, format);
@@ -126,3 +134,74 @@ gimp_image_get_new_preview (GimpViewable *viewable,
return buf;
}
+
+GdkPixbuf *
+gimp_image_get_new_pixbuf (GimpViewable *viewable,
+ GimpContext *context,
+ gint width,
+ gint height)
+{
+ GimpImage *image = GIMP_IMAGE (viewable);
+ GdkPixbuf *pixbuf;
+ gdouble scale_x;
+ gdouble scale_y;
+ GimpColorTransform transform;
+ const Babl *src_format;
+ const Babl *dest_format;
+
+ scale_x = (gdouble) width / (gdouble) gimp_image_get_width (image);
+ scale_y = (gdouble) height / (gdouble) gimp_image_get_height (image);
+
+ pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
+ width, height);
+
+ transform = gimp_image_get_color_transform_to_srgb_u8 (image,
+ &src_format,
+ &dest_format);
+
+ if (transform)
+ {
+ GimpTempBuf *temp_buf;
+ GeglBuffer *src_buf;
+ GeglBuffer *dest_buf;
+
+ temp_buf = gimp_temp_buf_new (width, height, src_format);
+
+ gegl_buffer_get (gimp_pickable_get_buffer (GIMP_PICKABLE (image)),
+ GEGL_RECTANGLE (0, 0, width, height),
+ MIN (scale_x, scale_y),
+ gimp_temp_buf_get_format (temp_buf),
+ gimp_temp_buf_get_data (temp_buf),
+ GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_CLAMP);
+
+ src_buf = gimp_temp_buf_create_buffer (temp_buf);
+ dest_buf = gimp_pixbuf_create_buffer (pixbuf);
+
+ gimp_temp_buf_unref (temp_buf);
+
+ gimp_gegl_convert_color_transform (src_buf,
+ GEGL_RECTANGLE (0, 0,
+ width, height),
+ src_format,
+ dest_buf,
+ GEGL_RECTANGLE (0, 0, 0, 0),
+ dest_format,
+ transform,
+ NULL);
+
+ g_object_unref (src_buf);
+ g_object_unref (dest_buf);
+ }
+ else
+ {
+ gegl_buffer_get (gimp_pickable_get_buffer (GIMP_PICKABLE (image)),
+ GEGL_RECTANGLE (0, 0, width, height),
+ MIN (scale_x, scale_y),
+ gimp_pixbuf_get_format (pixbuf),
+ gdk_pixbuf_get_pixels (pixbuf),
+ gdk_pixbuf_get_rowstride (pixbuf),
+ GEGL_ABYSS_CLAMP);
+ }
+
+ return pixbuf;
+}
diff --git a/app/core/gimpimage-preview.h b/app/core/gimpimage-preview.h
index 283e4b3..e6515d0 100644
--- a/app/core/gimpimage-preview.h
+++ b/app/core/gimpimage-preview.h
@@ -39,6 +39,10 @@ GimpTempBuf * gimp_image_get_new_preview (GimpViewable *viewable,
GimpContext *context,
gint width,
gint height);
+GdkPixbuf * gimp_image_get_new_pixbuf (GimpViewable *viewable,
+ GimpContext *context,
+ gint width,
+ gint height);
#endif /* __GIMP_IMAGE_PREVIEW_H__ */
diff --git a/app/core/gimpimage.c b/app/core/gimpimage.c
index 02ba6be..72a6270 100644
--- a/app/core/gimpimage.c
+++ b/app/core/gimpimage.c
@@ -550,6 +550,7 @@ gimp_image_class_init (GimpImageClass *klass)
viewable_class->get_preview_size = gimp_image_get_preview_size;
viewable_class->get_popup_size = gimp_image_get_popup_size;
viewable_class->get_new_preview = gimp_image_get_new_preview;
+ viewable_class->get_new_pixbuf = gimp_image_get_new_pixbuf;
viewable_class->get_description = gimp_image_get_description;
klass->mode_changed = gimp_image_real_mode_changed;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]