From e42129241681dde7adae7d20697e7b421682fbb4 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 27 Apr 2024 18:23:22 +0200 Subject: Adding upstream version 2.10.22. Signed-off-by: Daniel Baumann --- app/core/gimptempbuf.c | 450 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 450 insertions(+) create mode 100644 app/core/gimptempbuf.c (limited to 'app/core/gimptempbuf.c') diff --git a/app/core/gimptempbuf.c b/app/core/gimptempbuf.c new file mode 100644 index 0000000..2879be9 --- /dev/null +++ b/app/core/gimptempbuf.c @@ -0,0 +1,450 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * 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 +#include +#include +#include + +#include "core-types.h" + +#include "libgimpcolor/gimpcolor.h" + +#include "gimptempbuf.h" + + +#define LOCK_DATA_ALIGNMENT 16 + + +struct _GimpTempBuf +{ + gint ref_count; + gint width; + gint height; + const Babl *format; + guchar *data; +}; + +typedef struct +{ + const Babl *format; + GeglAccessMode access_mode; +} LockData; + +G_STATIC_ASSERT (sizeof (LockData) <= LOCK_DATA_ALIGNMENT); + + +/* local variables */ + +static guintptr gimp_temp_buf_total_memsize = 0; + + +/* public functions */ + +GimpTempBuf * +gimp_temp_buf_new (gint width, + gint height, + const Babl *format) +{ + GimpTempBuf *temp; + gint bpp; + + g_return_val_if_fail (format != NULL, NULL); + + bpp = babl_format_get_bytes_per_pixel (format); + + g_return_val_if_fail (width > 0 && height > 0 && bpp > 0, NULL); + g_return_val_if_fail (G_MAXSIZE / width / height / bpp > 0, NULL); + + temp = g_slice_new (GimpTempBuf); + + temp->ref_count = 1; + temp->width = width; + temp->height = height; + temp->format = format; + temp->data = gegl_malloc ((gsize) width * height * bpp); + + g_atomic_pointer_add (&gimp_temp_buf_total_memsize, + +gimp_temp_buf_get_memsize (temp)); + + 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) +{ + GimpTempBuf *dest; + + g_return_val_if_fail (src != NULL, NULL); + + dest = gimp_temp_buf_new (src->width, src->height, src->format); + + memcpy (gimp_temp_buf_get_data (dest), + gimp_temp_buf_get_data (src), + gimp_temp_buf_get_data_size (src)); + + return dest; +} + +GimpTempBuf * +gimp_temp_buf_ref (const GimpTempBuf *buf) +{ + g_return_val_if_fail (buf != NULL, NULL); + + g_atomic_int_inc ((gint *) &buf->ref_count); + + return (GimpTempBuf *) buf; +} + +void +gimp_temp_buf_unref (const GimpTempBuf *buf) +{ + g_return_if_fail (buf != NULL); + g_return_if_fail (buf->ref_count > 0); + + if (g_atomic_int_dec_and_test ((gint *) &buf->ref_count)) + { + g_atomic_pointer_add (&gimp_temp_buf_total_memsize, + -gimp_temp_buf_get_memsize (buf)); + + + if (buf->data) + gegl_free (buf->data); + + g_slice_free (GimpTempBuf, (GimpTempBuf *) buf); + } +} + +GimpTempBuf * +gimp_temp_buf_scale (const GimpTempBuf *src, + gint new_width, + gint new_height) +{ + GimpTempBuf *dest; + const guchar *src_data; + guchar *dest_data; + gdouble x_ratio; + gdouble y_ratio; + gint bytes; + gint loop1; + gint loop2; + + g_return_val_if_fail (src != NULL, NULL); + g_return_val_if_fail (new_width > 0 && new_height > 0, NULL); + + if (new_width == src->width && new_height == src->height) + return gimp_temp_buf_copy (src); + + dest = gimp_temp_buf_new (new_width, + new_height, + src->format); + + src_data = gimp_temp_buf_get_data (src); + dest_data = gimp_temp_buf_get_data (dest); + + x_ratio = (gdouble) src->width / (gdouble) new_width; + y_ratio = (gdouble) src->height / (gdouble) new_height; + + bytes = babl_format_get_bytes_per_pixel (src->format); + + for (loop1 = 0 ; loop1 < new_height ; loop1++) + { + for (loop2 = 0 ; loop2 < new_width ; loop2++) + { + const guchar *src_pixel; + guchar *dest_pixel; + gint i; + + src_pixel = src_data + + (gint) (loop2 * x_ratio) * bytes + + (gint) (loop1 * y_ratio) * bytes * src->width; + + dest_pixel = dest_data + + (loop2 + loop1 * new_width) * bytes; + + for (i = 0 ; i < bytes; i++) + *dest_pixel++ = *src_pixel++; + } + } + + return dest; +} + +gint +gimp_temp_buf_get_width (const GimpTempBuf *buf) +{ + return buf->width; +} + +gint +gimp_temp_buf_get_height (const GimpTempBuf *buf) +{ + return buf->height; +} + +const Babl * +gimp_temp_buf_get_format (const GimpTempBuf *buf) +{ + return buf->format; +} + +void +gimp_temp_buf_set_format (GimpTempBuf *buf, + const Babl *format) +{ + g_return_if_fail (babl_format_get_bytes_per_pixel (buf->format) == + babl_format_get_bytes_per_pixel (format)); + + buf->format = format; +} + +guchar * +gimp_temp_buf_get_data (const GimpTempBuf *buf) +{ + return buf->data; +} + +gsize +gimp_temp_buf_get_data_size (const GimpTempBuf *buf) +{ + return (gsize) babl_format_get_bytes_per_pixel (buf->format) * + buf->width * buf->height; +} + +guchar * +gimp_temp_buf_data_clear (GimpTempBuf *buf) +{ + memset (buf->data, 0, gimp_temp_buf_get_data_size (buf)); + + return buf->data; +} + +gpointer +gimp_temp_buf_lock (const GimpTempBuf *buf, + const Babl *format, + GeglAccessMode access_mode) +{ + guchar *data; + LockData *lock_data; + gint n_pixels; + gint bpp; + + g_return_val_if_fail (buf != NULL, NULL); + + if (! format || format == buf->format) + return gimp_temp_buf_get_data (buf); + + n_pixels = buf->width * buf->height; + bpp = babl_format_get_bytes_per_pixel (format); + + data = gegl_scratch_alloc (LOCK_DATA_ALIGNMENT + n_pixels * bpp); + + if ((guintptr) data % LOCK_DATA_ALIGNMENT) + { + g_free (data); + + g_return_val_if_reached (NULL); + } + + lock_data = (LockData *) data; + lock_data->format = format; + lock_data->access_mode = access_mode; + + data += LOCK_DATA_ALIGNMENT; + + if (access_mode & GEGL_ACCESS_READ) + { + babl_process (babl_fish (buf->format, format), + gimp_temp_buf_get_data (buf), + data, + n_pixels); + } + + return data; +} + +void +gimp_temp_buf_unlock (const GimpTempBuf *buf, + gconstpointer data) +{ + LockData *lock_data; + + g_return_if_fail (buf != NULL); + g_return_if_fail (data != NULL); + + if (data == buf->data) + return; + + lock_data = (LockData *) ((const guint8 *) data - LOCK_DATA_ALIGNMENT); + + if (lock_data->access_mode & GEGL_ACCESS_WRITE) + { + babl_process (babl_fish (lock_data->format, buf->format), + data, + gimp_temp_buf_get_data (buf), + buf->width * buf->height); + } + + gegl_scratch_free (lock_data); +} + +gsize +gimp_temp_buf_get_memsize (const GimpTempBuf *buf) +{ + if (buf) + return (sizeof (GimpTempBuf) + gimp_temp_buf_get_data_size (buf)); + + return 0; +} + +GeglBuffer * +gimp_temp_buf_create_buffer (const GimpTempBuf *temp_buf) +{ + GeglBuffer *buffer; + + g_return_val_if_fail (temp_buf != NULL, NULL); + + buffer = + gegl_buffer_linear_new_from_data (gimp_temp_buf_get_data (temp_buf), + temp_buf->format, + GEGL_RECTANGLE (0, 0, + temp_buf->width, + temp_buf->height), + GEGL_AUTO_ROWSTRIDE, + (GDestroyNotify) gimp_temp_buf_unref, + gimp_temp_buf_ref (temp_buf)); + + g_object_set_data (G_OBJECT (buffer), + "gimp-temp-buf", (GimpTempBuf *) temp_buf); + + return buffer; +} + +GdkPixbuf * +gimp_temp_buf_create_pixbuf (const 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) +{ + g_return_val_if_fail (GEGL_IS_BUFFER (buffer), NULL); + + return g_object_get_data (G_OBJECT (buffer), "gimp-temp-buf"); +} + + +/* public functions (stats) */ + +guint64 +gimp_temp_buf_get_total_memsize (void) +{ + return gimp_temp_buf_total_memsize; +} -- cgit v1.2.3