mirror of https://github.com/GNOME/gimp.git
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.
This commit is contained in:
parent
ee772d398f
commit
9498cc615d
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue