diff --git a/app/core/gimplayer.c b/app/core/gimplayer.c index ef47e99b92..6f959a169b 100644 --- a/app/core/gimplayer.c +++ b/app/core/gimplayer.c @@ -1290,17 +1290,25 @@ gimp_layer_new_from_pixbuf (GdkPixbuf *pixbuf, { GeglBuffer *buffer; GimpLayer *layer; + gint width; + gint height; g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), NULL); g_return_val_if_fail (GIMP_IS_IMAGE (dest_image), NULL); g_return_val_if_fail (format != NULL, NULL); - buffer = gimp_pixbuf_create_buffer (pixbuf); + width = gdk_pixbuf_get_width (pixbuf); + height = gdk_pixbuf_get_height (pixbuf); - layer = gimp_layer_new_from_buffer (buffer, dest_image, format, - name, opacity, mode); + layer = gimp_layer_new (dest_image, width, height, + format, name, opacity, mode); - g_object_unref (buffer); + buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (layer)); + + gegl_buffer_set (buffer, GEGL_RECTANGLE (0, 0, width, height), 0, + gimp_pixbuf_get_format (pixbuf), + gdk_pixbuf_get_pixels (pixbuf), + gdk_pixbuf_get_rowstride (pixbuf)); return layer; } diff --git a/app/core/gimppattern-load.c b/app/core/gimppattern-load.c index 45b2be1ee9..f3d8a8aa28 100644 --- a/app/core/gimppattern-load.c +++ b/app/core/gimppattern-load.c @@ -198,8 +198,6 @@ gimp_pattern_load_pixbuf (GimpContext *context, { GimpPattern *pattern; GdkPixbuf *pixbuf; - GeglBuffer *src_buffer; - GeglBuffer *dest_buffer; gchar *name; g_return_val_if_fail (filename != NULL, NULL); @@ -225,17 +223,7 @@ gimp_pattern_load_pixbuf (GimpContext *context, NULL); g_free (name); - pattern->mask = gimp_temp_buf_new (gdk_pixbuf_get_width (pixbuf), - gdk_pixbuf_get_height (pixbuf), - gimp_pixbuf_get_format (pixbuf)); - - src_buffer = gimp_pixbuf_create_buffer (pixbuf); - dest_buffer = gimp_temp_buf_create_buffer (pattern->mask); - - gegl_buffer_copy (src_buffer, NULL, dest_buffer, NULL); - - g_object_unref (src_buffer); - g_object_unref (dest_buffer); + pattern->mask = gimp_temp_buf_new_from_pixbuf (pixbuf, NULL); g_object_unref (pixbuf); diff --git a/app/core/gimptempbuf.c b/app/core/gimptempbuf.c index dfd8c1fac4..42bae76610 100644 --- a/app/core/gimptempbuf.c +++ b/app/core/gimptempbuf.c @@ -23,9 +23,12 @@ #include #include #include +#include #include "core-types.h" +#include "libgimpcolor/gimpcolor.h" + #include "gimptempbuf.h" @@ -61,6 +64,53 @@ gimp_temp_buf_new (gint width, return temp; } +GimpTempBuf * +gimp_temp_buf_new_from_pixbuf (GdkPixbuf *pixbuf, + const Babl *f_or_null) +{ + const Babl *format = f_or_null; + const Babl *fish = NULL; + GimpTempBuf *temp_buf; + const guchar *pixels; + gint width; + gint height; + gint rowstride; + gint bpp; + guchar *data; + gint i; + + g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), NULL); + + if (! format) + format = gimp_pixbuf_get_format (pixbuf); + + pixels = gdk_pixbuf_get_pixels (pixbuf); + width = gdk_pixbuf_get_width (pixbuf); + height = gdk_pixbuf_get_height (pixbuf); + rowstride = gdk_pixbuf_get_rowstride (pixbuf); + + temp_buf = gimp_temp_buf_new (width, height, format); + data = gimp_temp_buf_get_data (temp_buf); + + bpp = babl_format_get_bytes_per_pixel (format); + + if (gimp_pixbuf_get_format (pixbuf) != format) + fish = babl_fish (gimp_pixbuf_get_format (pixbuf), format); + + for (i = 0; i < height; ++i) + { + if (fish) + babl_process (fish, pixels, data, width); + else + memcpy (data, pixels, width * bpp); + + data += width * bpp; + pixels += rowstride; + } + + return temp_buf; +} + GimpTempBuf * gimp_temp_buf_copy (const GimpTempBuf *src) { @@ -238,6 +288,52 @@ gimp_temp_buf_create_buffer (GimpTempBuf *temp_buf) return buffer; } +GdkPixbuf * +gimp_temp_buf_create_pixbuf (GimpTempBuf *temp_buf) +{ + GdkPixbuf *pixbuf; + const Babl *format; + const Babl *fish = NULL; + const guchar *data; + gint width; + gint height; + gint bpp; + guchar *pixels; + gint rowstride; + gint i; + + g_return_val_if_fail (temp_buf != NULL, NULL); + + data = gimp_temp_buf_get_data (temp_buf); + format = gimp_temp_buf_get_format (temp_buf); + width = gimp_temp_buf_get_width (temp_buf); + height = gimp_temp_buf_get_height (temp_buf); + bpp = babl_format_get_bytes_per_pixel (format); + + pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, + babl_format_has_alpha (format), + 8, width, height); + + pixels = gdk_pixbuf_get_pixels (pixbuf); + rowstride = gdk_pixbuf_get_rowstride (pixbuf); + + if (format != gimp_pixbuf_get_format (pixbuf)) + fish = babl_fish (format, gimp_pixbuf_get_format (pixbuf)); + + for (i = 0; i <= height; ++i) + { + if (fish) + babl_process (fish, data, pixels, width); + else + memcpy (pixels, data, width * bpp); + + data += width * bpp; + pixels += rowstride; + } + + return pixbuf; +} + GimpTempBuf * gimp_gegl_buffer_get_temp_buf (GeglBuffer *buffer) { diff --git a/app/core/gimptempbuf.h b/app/core/gimptempbuf.h index 2a6033aa44..5eb7daa5f1 100644 --- a/app/core/gimptempbuf.h +++ b/app/core/gimptempbuf.h @@ -22,6 +22,8 @@ GimpTempBuf * gimp_temp_buf_new (gint width, gint height, const Babl *fomat) G_GNUC_WARN_UNUSED_RESULT; +GimpTempBuf * gimp_temp_buf_new_from_pixbuf (GdkPixbuf *pixbuf, + const Babl *f_or_null) G_GNUC_WARN_UNUSED_RESULT; GimpTempBuf * gimp_temp_buf_copy (const GimpTempBuf *src) G_GNUC_WARN_UNUSED_RESULT; GimpTempBuf * gimp_temp_buf_ref (GimpTempBuf *buf); @@ -46,6 +48,8 @@ guchar * gimp_temp_buf_data_clear (GimpTempBuf *buf); gsize gimp_temp_buf_get_memsize (const GimpTempBuf *buf); GeglBuffer * gimp_temp_buf_create_buffer (GimpTempBuf *temp_buf) G_GNUC_WARN_UNUSED_RESULT; +GdkPixbuf * gimp_temp_buf_create_pixbuf (GimpTempBuf *temp_buf) G_GNUC_WARN_UNUSED_RESULT; + GimpTempBuf * gimp_gegl_buffer_get_temp_buf (GeglBuffer *buffer); diff --git a/app/core/gimpviewable.c b/app/core/gimpviewable.c index d55271f9bf..edf0f149a3 100644 --- a/app/core/gimpviewable.c +++ b/app/core/gimpviewable.c @@ -388,22 +388,7 @@ gimp_viewable_real_get_new_pixbuf (GimpViewable *viewable, if (temp_buf) { - GeglBuffer *src_buffer; - GeglBuffer *dest_buffer; - - pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, - babl_format_has_alpha (gimp_temp_buf_get_format (temp_buf)), - 8, - gimp_temp_buf_get_width (temp_buf), - gimp_temp_buf_get_height (temp_buf)); - - src_buffer = gimp_temp_buf_create_buffer (temp_buf); - dest_buffer = gimp_pixbuf_create_buffer (pixbuf); - - gegl_buffer_copy (src_buffer, NULL, dest_buffer, NULL); - - g_object_unref (src_buffer); - g_object_unref (dest_buffer); + pixbuf = gimp_temp_buf_create_pixbuf (temp_buf); } else if (private->icon_pixbuf) { @@ -930,8 +915,6 @@ gimp_viewable_get_dummy_preview (GimpViewable *viewable, { GdkPixbuf *pixbuf; GimpTempBuf *buf; - GeglBuffer *src_buffer; - GeglBuffer *dest_buffer; g_return_val_if_fail (GIMP_IS_VIEWABLE (viewable), NULL); g_return_val_if_fail (width > 0, NULL); @@ -941,15 +924,7 @@ gimp_viewable_get_dummy_preview (GimpViewable *viewable, pixbuf = gimp_viewable_get_dummy_pixbuf (viewable, width, height, babl_format_has_alpha (format)); - buf = gimp_temp_buf_new (width, height, format); - - src_buffer = gimp_pixbuf_create_buffer (pixbuf); - dest_buffer = gimp_temp_buf_create_buffer (buf); - - gegl_buffer_copy (src_buffer, NULL, dest_buffer, NULL); - - g_object_unref (src_buffer); - g_object_unref (dest_buffer); + buf = gimp_temp_buf_new_from_pixbuf (pixbuf, format); g_object_unref (pixbuf); diff --git a/app/paint/gimppaintcore-loops.c b/app/paint/gimppaintcore-loops.c index 816d16d41c..a270e5231d 100644 --- a/app/paint/gimppaintcore-loops.c +++ b/app/paint/gimppaintcore-loops.c @@ -14,10 +14,11 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + #include "config.h" #include +#include #include "paint-types.h" diff --git a/libgimp/gimplayer.c b/libgimp/gimplayer.c index 43c9b8f5ce..e087d0e579 100644 --- a/libgimp/gimplayer.c +++ b/libgimp/gimplayer.c @@ -150,15 +150,15 @@ gimp_layer_new_from_pixbuf (gint32 image_ID, if (gimp_plugin_precision_enabled ()) { - GeglBuffer *src_buffer; GeglBuffer *dest_buffer; - src_buffer = gimp_pixbuf_create_buffer (pixbuf); dest_buffer = gimp_drawable_get_buffer (layer); - gegl_buffer_copy (src_buffer, NULL, dest_buffer, NULL); + gegl_buffer_set (dest_buffer, GEGL_RECTANGLE (0, 0, width, height), 0, + gimp_pixbuf_get_format (pixbuf), + gdk_pixbuf_get_pixels (pixbuf), + gdk_pixbuf_get_rowstride (pixbuf)); - g_object_unref (src_buffer); g_object_unref (dest_buffer); } else diff --git a/libgimpcolor/gimppixbuf.c b/libgimpcolor/gimppixbuf.c index 9f5977fb9f..ded08bd942 100644 --- a/libgimpcolor/gimppixbuf.c +++ b/libgimpcolor/gimppixbuf.c @@ -57,11 +57,14 @@ gimp_pixbuf_get_format (GdkPixbuf *pixbuf) * gimp_pixbuf_create_buffer: * @pixbuf: a #GdkPixbuf * - * Returns a #GeglBuffer that's backed by the @pixbuf's pixels, without - * copying them. This function refs the pixbuf, so it will be kept - * around for as long as te buffer exists. + * Returns a #GeglBuffer that's either backed by the @pixbuf's pixels, + * or a copy of them. This function tries to not copy the @pixbuf's + * pixels. If the pixbuf's rowstride is a multiple of its bpp, a + * simple reference to the @pixbuf's pixels is made and @pixbuf will + * be kept around for as long as the buffer exists; otherwise the + * pixels are copied. * - * Return value: a new #GeglBuffer as a wrapper around @pixbuf. + * Return value: a new #GeglBuffer. * * Since: GIMP 2.10 **/ @@ -71,17 +74,35 @@ gimp_pixbuf_create_buffer (GdkPixbuf *pixbuf) gint width; gint height; gint rowstride; + gint bpp; g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), NULL); width = gdk_pixbuf_get_width (pixbuf); height = gdk_pixbuf_get_height (pixbuf); rowstride = gdk_pixbuf_get_rowstride (pixbuf); + bpp = gdk_pixbuf_get_n_channels (pixbuf); - return gegl_buffer_linear_new_from_data (gdk_pixbuf_get_pixels (pixbuf), - gimp_pixbuf_get_format (pixbuf), - GEGL_RECTANGLE (0, 0, width, height), - rowstride, - (GDestroyNotify) g_object_unref, - g_object_ref (pixbuf)); + if ((rowstride % bpp) == 0) + { + return gegl_buffer_linear_new_from_data (gdk_pixbuf_get_pixels (pixbuf), + gimp_pixbuf_get_format (pixbuf), + GEGL_RECTANGLE (0, 0, + width, height), + rowstride, + (GDestroyNotify) g_object_unref, + g_object_ref (pixbuf)); + } + else + { + GeglBuffer *buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, + width, height), + gimp_pixbuf_get_format (pixbuf)); + + gegl_buffer_set (buffer, NULL, 0, NULL, + gdk_pixbuf_get_pixels (pixbuf), + gdk_pixbuf_get_rowstride (pixbuf)); + + return buffer; + } }