+ /* Calculate a semi-exact size. Here we copy with full rowstrides;
+ * maybe we should copy each row individually with the minimum
+ * rowstride?
+ */
+
+ size = ((pixbuf->height - 1) * pixbuf->rowstride +
+ pixbuf->width * ((pixbuf->n_channels * pixbuf->bits_per_sample + 7) / 8));
+
+ buf = malloc (size * sizeof (guchar));
+ if (!buf)
+ return NULL;
+
+ memcpy (buf, pixbuf->pixels, size);
+
+ return gdk_pixbuf_new_from_data (buf,
+ pixbuf->colorspace, pixbuf->has_alpha,
+ pixbuf->bits_per_sample,
+ pixbuf->width, pixbuf->height,
+ pixbuf->rowstride,
+ free_buffer,
+ NULL);
+}
+
+/**
+ * gdk_pixbuf_new_subpixbuf:
+ * @src_pixbuf: a #GdkPixbuf
+ * @src_x: X coord in @src_pixbuf
+ * @src_y: Y coord in @src_pixbuf
+ * @width: width of region in @src_pixbuf
+ * @height: height of region in @src_pixbuf
+ *
+ * Creates a new pixbuf which represents a sub-region of
+ * @src_pixbuf. The new pixbuf shares its pixels with the
+ * original pixbuf, so writing to one affects both.
+ * The new pixbuf holds a reference to @src_pixbuf, so
+ * @src_pixbuf will not be finalized until the new pixbuf
+ * is finalized.
+ *
+ * Return value: a new pixbuf
+ **/
+GdkPixbuf*
+gdk_pixbuf_new_subpixbuf (GdkPixbuf *src_pixbuf,
+ int src_x,
+ int src_y,
+ int width,
+ int height)
+{
+ guchar *pixels;
+ GdkPixbuf *sub;
+
+ g_return_val_if_fail (GDK_IS_PIXBUF (src_pixbuf), NULL);
+ g_return_val_if_fail (src_x >= 0 && src_x + width <= src_pixbuf->width, NULL);
+ g_return_val_if_fail (src_y >= 0 && src_y + height <= src_pixbuf->height, NULL);
+
+ pixels = (gdk_pixbuf_get_pixels (src_pixbuf)
+ + src_y * src_pixbuf->rowstride
+ + src_x * src_pixbuf->n_channels);
+
+ sub = gdk_pixbuf_new_from_data (pixels,
+ src_pixbuf->colorspace,
+ src_pixbuf->has_alpha,
+ src_pixbuf->bits_per_sample,
+ width, height,
+ src_pixbuf->rowstride,
+ NULL, NULL);
+
+ /* Keep a reference to src_pixbuf */
+ g_object_ref (G_OBJECT (src_pixbuf));
+
+ g_object_set_qdata_full (G_OBJECT (sub),
+ g_quark_from_static_string ("gdk-pixbuf-subpixbuf-src"),
+ src_pixbuf,
+ (GDestroyNotify) g_object_unref);
+
+ return sub;
+}
+
+\f
+
+/* Accessors */
+
+/**
+ * gdk_pixbuf_get_colorspace:
+ * @pixbuf: A pixbuf.
+ *
+ * Queries the color space of a pixbuf.
+ *
+ * Return value: Color space.
+ **/
+GdkColorspace
+gdk_pixbuf_get_colorspace (const GdkPixbuf *pixbuf)
+{
+ g_return_val_if_fail (pixbuf != NULL, GDK_COLORSPACE_RGB);
+
+ return pixbuf->colorspace;
+}
+
+/**
+ * gdk_pixbuf_get_n_channels:
+ * @pixbuf: A pixbuf.
+ *
+ * Queries the number of channels of a pixbuf.
+ *
+ * Return value: Number of channels.
+ **/
+int
+gdk_pixbuf_get_n_channels (const GdkPixbuf *pixbuf)
+{
+ g_return_val_if_fail (pixbuf != NULL, -1);
+
+ return pixbuf->n_channels;
+}
+
+/**
+ * gdk_pixbuf_get_has_alpha:
+ * @pixbuf: A pixbuf.
+ *
+ * Queries whether a pixbuf has an alpha channel (opacity information).
+ *
+ * Return value: TRUE if it has an alpha channel, FALSE otherwise.
+ **/
+gboolean
+gdk_pixbuf_get_has_alpha (const GdkPixbuf *pixbuf)
+{
+ g_return_val_if_fail (pixbuf != NULL, -1);
+
+ return pixbuf->has_alpha ? TRUE : FALSE;
+}
+
+/**
+ * gdk_pixbuf_get_bits_per_sample:
+ * @pixbuf: A pixbuf.
+ *
+ * Queries the number of bits per color sample in a pixbuf.
+ *
+ * Return value: Number of bits per color sample.
+ **/
+int
+gdk_pixbuf_get_bits_per_sample (const GdkPixbuf *pixbuf)
+{
+ g_return_val_if_fail (pixbuf != NULL, -1);
+
+ return pixbuf->bits_per_sample;
+}