summaryrefslogtreecommitdiffstats
path: root/libgimp/gimplayer.c
diff options
context:
space:
mode:
Diffstat (limited to 'libgimp/gimplayer.c')
-rw-r--r--libgimp/gimplayer.c415
1 files changed, 415 insertions, 0 deletions
diff --git a/libgimp/gimplayer.c b/libgimp/gimplayer.c
new file mode 100644
index 0000000..a3f58fd
--- /dev/null
+++ b/libgimp/gimplayer.c
@@ -0,0 +1,415 @@
+/* LIBGIMP - The GIMP Library
+ * Copyright (C) 1995-2000 Peter Mattis and Spencer Kimball
+ *
+ * gimplayer.c
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#define GIMP_DISABLE_DEPRECATION_WARNINGS
+
+#include "gimp.h"
+
+
+/**
+ * gimp_layer_new:
+ * @image_ID: The image to which to add the layer.
+ * @name: The layer name.
+ * @width: The layer width.
+ * @height: The layer height.
+ * @type: The layer type.
+ * @opacity: The layer opacity.
+ * @mode: The layer combination mode.
+ *
+ * Create a new layer.
+ *
+ * This procedure creates a new layer with the specified width, height,
+ * and type. Name, opacity, and mode are also supplied parameters. The
+ * new layer still needs to be added to the image, as this is not
+ * automatic. Add the new layer with the gimp_image_insert_layer()
+ * command. Other attributes such as layer mask modes, and offsets
+ * should be set with explicit procedure calls.
+ *
+ * Returns: The newly created layer.
+ */
+gint32
+gimp_layer_new (gint32 image_ID,
+ const gchar *name,
+ gint width,
+ gint height,
+ GimpImageType type,
+ gdouble opacity,
+ GimpLayerMode mode)
+{
+ return _gimp_layer_new (image_ID,
+ width,
+ height,
+ type,
+ name,
+ opacity,
+ mode);
+}
+
+/**
+ * gimp_layer_copy:
+ * @layer_ID: The layer to copy.
+ *
+ * Copy a layer.
+ *
+ * This procedure copies the specified layer and returns the copy. The
+ * newly copied layer is for use within the original layer's image. It
+ * should not be subsequently added to any other image.
+ *
+ * Returns: The newly copied layer.
+ */
+gint32
+gimp_layer_copy (gint32 layer_ID)
+{
+ return _gimp_layer_copy (layer_ID, FALSE);
+}
+
+/**
+ * gimp_layer_new_from_pixbuf:
+ * @image_ID: The RGB image to which to add the layer.
+ * @name: The layer name.
+ * @pixbuf: A GdkPixbuf.
+ * @opacity: The layer opacity.
+ * @mode: The layer combination mode.
+ * @progress_start: start of progress
+ * @progress_end: end of progress
+ *
+ * Create a new layer from a %GdkPixbuf.
+ *
+ * This procedure creates a new layer from the given %GdkPixbuf. The
+ * image has to be an RGB image and just like with gimp_layer_new()
+ * you will still need to add the layer to it.
+ *
+ * If you pass @progress_end > @progress_start to this function,
+ * gimp_progress_update() will be called for. You have to call
+ * gimp_progress_init() beforehand then.
+ *
+ * Returns: The newly created layer.
+ *
+ * Since: 2.4
+ */
+gint32
+gimp_layer_new_from_pixbuf (gint32 image_ID,
+ const gchar *name,
+ GdkPixbuf *pixbuf,
+ gdouble opacity,
+ GimpLayerMode mode,
+ gdouble progress_start,
+ gdouble progress_end)
+{
+ gint32 layer;
+ gint width;
+ gint height;
+ gint bpp;
+ gdouble range = progress_end - progress_start;
+
+ g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), -1);
+
+ if (gimp_image_base_type (image_ID) != GIMP_RGB)
+ {
+ g_warning ("gimp_layer_new_from_pixbuf() needs an RGB image");
+ return -1;
+ }
+
+ if (gdk_pixbuf_get_colorspace (pixbuf) != GDK_COLORSPACE_RGB)
+ {
+ g_warning ("gimp_layer_new_from_pixbuf() assumes that GdkPixbuf is RGB");
+ return -1;
+ }
+
+ width = gdk_pixbuf_get_width (pixbuf);
+ height = gdk_pixbuf_get_height (pixbuf);
+ bpp = gdk_pixbuf_get_n_channels (pixbuf);
+
+ layer = gimp_layer_new (image_ID, name, width, height,
+ bpp == 3 ? GIMP_RGB_IMAGE : GIMP_RGBA_IMAGE,
+ opacity, mode);
+
+ if (layer == -1)
+ return -1;
+
+ if (gimp_plugin_precision_enabled ())
+ {
+ GeglBuffer *dest_buffer;
+
+ dest_buffer = gimp_drawable_get_buffer (layer);
+
+ 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 (dest_buffer);
+ }
+ else
+ {
+ GimpDrawable *drawable;
+ GimpPixelRgn rgn;
+ gpointer pr;
+ const guchar *pixels;
+ gint rowstride;
+ guint done = 0;
+ guint count = 0;
+
+ drawable = gimp_drawable_get (layer);
+
+ gimp_pixel_rgn_init (&rgn, drawable, 0, 0, width, height, TRUE, FALSE);
+
+ g_assert (bpp == rgn.bpp);
+
+ rowstride = gdk_pixbuf_get_rowstride (pixbuf);
+ pixels = gdk_pixbuf_get_pixels (pixbuf);
+
+ for (pr = gimp_pixel_rgns_register (1, &rgn);
+ pr != NULL;
+ pr = gimp_pixel_rgns_process (pr))
+ {
+ const guchar *src = pixels + rgn.y * rowstride + rgn.x * bpp;
+ guchar *dest = rgn.data;
+ gint y;
+
+ for (y = 0; y < rgn.h; y++)
+ {
+ memcpy (dest, src, rgn.w * rgn.bpp);
+
+ src += rowstride;
+ dest += rgn.rowstride;
+ }
+
+ if (range > 0.0)
+ {
+ done += rgn.h * rgn.w;
+
+ if (count++ % 32 == 0)
+ gimp_progress_update (progress_start +
+ (gdouble) done / (width * height) * range);
+ }
+ }
+
+ gimp_drawable_detach (drawable);
+ }
+
+ if (range > 0.0)
+ gimp_progress_update (progress_end);
+
+ return layer;
+}
+
+/**
+ * gimp_layer_new_from_surface:
+ * @image_ID: The RGB image to which to add the layer.
+ * @name: The layer name.
+ * @surface: A Cairo image surface.
+ * @progress_start: start of progress
+ * @progress_end: end of progress
+ *
+ * Create a new layer from a #cairo_surface_t.
+ *
+ * This procedure creates a new layer from the given
+ * #cairo_surface_t. The image has to be an RGB image and just like
+ * with gimp_layer_new() you will still need to add the layer to it.
+ *
+ * If you pass @progress_end > @progress_start to this function,
+ * gimp_progress_update() will be called for. You have to call
+ * gimp_progress_init() beforehand then.
+ *
+ * Returns: The newly created layer.
+ *
+ * Since: 2.8
+ */
+gint32
+gimp_layer_new_from_surface (gint32 image_ID,
+ const gchar *name,
+ cairo_surface_t *surface,
+ gdouble progress_start,
+ gdouble progress_end)
+{
+ gint32 layer;
+ gint width;
+ gint height;
+ cairo_format_t format;
+ gdouble range = progress_end - progress_start;
+
+ g_return_val_if_fail (surface != NULL, -1);
+ g_return_val_if_fail (cairo_surface_get_type (surface) ==
+ CAIRO_SURFACE_TYPE_IMAGE, -1);
+
+ if (gimp_image_base_type (image_ID) != GIMP_RGB)
+ {
+ g_warning ("gimp_layer_new_from_surface() needs an RGB image");
+ return -1;
+ }
+
+ width = cairo_image_surface_get_width (surface);
+ height = cairo_image_surface_get_height (surface);
+ format = cairo_image_surface_get_format (surface);
+
+ if (format != CAIRO_FORMAT_ARGB32 &&
+ format != CAIRO_FORMAT_RGB24)
+ {
+ g_warning ("gimp_layer_new_from_surface() assumes that surface is RGB");
+ return -1;
+ }
+
+ layer = gimp_layer_new (image_ID, name, width, height,
+ format == CAIRO_FORMAT_RGB24 ?
+ GIMP_RGB_IMAGE : GIMP_RGBA_IMAGE,
+ 100.0,
+ gimp_image_get_default_new_layer_mode (image_ID));
+
+ if (layer == -1)
+ return -1;
+
+ if (gimp_plugin_precision_enabled ())
+ {
+ GeglBuffer *src_buffer;
+ GeglBuffer *dest_buffer;
+
+ src_buffer = gimp_cairo_surface_create_buffer (surface);
+ dest_buffer = gimp_drawable_get_buffer (layer);
+
+ gegl_buffer_copy (src_buffer, NULL, GEGL_ABYSS_NONE,
+ dest_buffer, NULL);
+
+ g_object_unref (src_buffer);
+ g_object_unref (dest_buffer);
+ }
+ else
+ {
+ GimpDrawable *drawable;
+ GimpPixelRgn rgn;
+ const guchar *pixels;
+ gpointer pr;
+ gsize rowstride;
+ guint count = 0;
+ guint done = 0;
+
+ drawable = gimp_drawable_get (layer);
+
+ gimp_pixel_rgn_init (&rgn, drawable, 0, 0, width, height, TRUE, FALSE);
+
+ rowstride = cairo_image_surface_get_stride (surface);
+ pixels = cairo_image_surface_get_data (surface);
+
+ for (pr = gimp_pixel_rgns_register (1, &rgn);
+ pr != NULL;
+ pr = gimp_pixel_rgns_process (pr))
+ {
+ const guchar *src = pixels + rgn.y * rowstride + rgn.x * 4;
+ guchar *dest = rgn.data;
+ gint y;
+
+ switch (format)
+ {
+ case CAIRO_FORMAT_RGB24:
+ for (y = 0; y < rgn.h; y++)
+ {
+ const guchar *s = src;
+ guchar *d = dest;
+ gint w = rgn.w;
+
+ while (w--)
+ {
+ GIMP_CAIRO_RGB24_GET_PIXEL (s, d[0], d[1], d[2]);
+
+ s += 4;
+ d += 3;
+ }
+
+ src += rowstride;
+ dest += rgn.rowstride;
+ }
+ break;
+
+ case CAIRO_FORMAT_ARGB32:
+ for (y = 0; y < rgn.h; y++)
+ {
+ const guchar *s = src;
+ guchar *d = dest;
+ gint w = rgn.w;
+
+ while (w--)
+ {
+ GIMP_CAIRO_ARGB32_GET_PIXEL (s, d[0], d[1], d[2], d[3]);
+
+ s += 4;
+ d += 4;
+ }
+
+ src += rowstride;
+ dest += rgn.rowstride;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if (range > 0.0)
+ {
+ done += rgn.h * rgn.w;
+
+ if (count++ % 32 == 0)
+ gimp_progress_update (progress_start +
+ (gdouble) done / (width * height) * range);
+ }
+ }
+
+ gimp_drawable_detach (drawable);
+ }
+
+ if (range > 0.0)
+ gimp_progress_update (progress_end);
+
+ return layer;
+}
+
+/**
+ * gimp_layer_get_preserve_trans:
+ * @layer_ID: The layer.
+ *
+ * This procedure is deprecated! Use gimp_layer_get_lock_alpha() instead.
+ *
+ * Returns: The layer's preserve transperancy setting.
+ */
+gboolean
+gimp_layer_get_preserve_trans (gint32 layer_ID)
+{
+ return gimp_layer_get_lock_alpha (layer_ID);
+}
+
+/**
+ * gimp_layer_set_preserve_trans:
+ * @layer_ID: The layer.
+ * @preserve_trans: The new layer's preserve transperancy setting.
+ *
+ * This procedure is deprecated! Use gimp_layer_set_lock_alpha() instead.
+ *
+ * Returns: TRUE on success.
+ */
+gboolean
+gimp_layer_set_preserve_trans (gint32 layer_ID,
+ gboolean preserve_trans)
+{
+ return gimp_layer_set_lock_alpha (layer_ID, preserve_trans);
+}