[gimp] Bug 722676: Pasting image from clipboard sometimes does not work.
- From: Michael Natterer <mitch src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] Bug 722676: Pasting image from clipboard sometimes does not work.
- Date: Sat, 22 Feb 2014 23:51:05 +0000 (UTC)
commit 9498cc615d5fd72ce0c7aa881e99209d13ea1e9e
Author: Massimo Valentini <mvalentini src gnome org>
Date: Thu Feb 20 18:20:17 2014 +0100
Bug 722676: Pasting image from clipboard sometimes does not work.
Change gimp_pixbuf_create_buffer() to copy the pixels if a linear
buffer cannot be created. Add functions that convert between
GimpTempBuf and GdkPixbuf. Fix users of gimp_pixbuf_create_buffer()
to make the least possible copies. Patch modified by Mitch.
app/core/gimplayer.c | 16 +++++--
app/core/gimppattern-load.c | 14 +-----
app/core/gimptempbuf.c | 96 +++++++++++++++++++++++++++++++++++++++
app/core/gimptempbuf.h | 4 ++
app/core/gimpviewable.c | 29 +-----------
app/paint/gimppaintcore-loops.c | 3 +-
libgimp/gimplayer.c | 8 ++--
libgimpcolor/gimppixbuf.c | 41 +++++++++++++----
8 files changed, 152 insertions(+), 59 deletions(-)
---
diff --git a/app/core/gimplayer.c b/app/core/gimplayer.c
index ef47e99..6f959a1 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 45b2be1..f3d8a8a 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 dfd8c1f..42bae76 100644
--- a/app/core/gimptempbuf.c
+++ b/app/core/gimptempbuf.c
@@ -23,9 +23,12 @@
#include <gegl.h>
#include <gegl-utils.h>
#include <glib/gstdio.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
#include "core-types.h"
+#include "libgimpcolor/gimpcolor.h"
+
#include "gimptempbuf.h"
@@ -62,6 +65,53 @@ gimp_temp_buf_new (gint width,
}
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)
{
GimpTempBuf *dest;
@@ -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 2a6033a..5eb7daa 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 d55271f..edf0f14 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 816d16d..a270e52 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 <http://www.gnu.org/licenses/>.
*/
-
+
#include "config.h"
#include <gegl.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
#include "paint-types.h"
diff --git a/libgimp/gimplayer.c b/libgimp/gimplayer.c
index 43c9b8f..e087d0e 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 9f5977f..ded08bd 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;
+ }
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]