diff --git a/app/core/gimpdrawable-preview.c b/app/core/gimpdrawable-preview.c index c4647c8dd2..6e1ce741ce 100644 --- a/app/core/gimpdrawable-preview.c +++ b/app/core/gimpdrawable-preview.c @@ -19,18 +19,24 @@ #include +#include #include #include +#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 0a552ced6f..e058934fb8 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 2af04d151c..bc96c1f0d8 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 405a629431..374ce9c572 100644 --- a/app/core/gimpimage-preview.c +++ b/app/core/gimpimage-preview.c @@ -17,16 +17,20 @@ #include "config.h" +#include #include #include +#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 283e4b33d7..e6515d08f3 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 02ba6be748..72a6270856 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;