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.
This commit is contained in:
parent
0ee27de463
commit
9e8499bb48
6 changed files with 244 additions and 8 deletions
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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__ */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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__ */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in a new issue