summaryrefslogtreecommitdiff
path: root/testing/gimp
diff options
context:
space:
mode:
Diffstat (limited to 'testing/gimp')
-rw-r--r--testing/gimp/PKGBUILD53
-rw-r--r--testing/gimp/gimp-poppler-0.18.patch476
-rw-r--r--testing/gimp/gimp.install12
-rw-r--r--testing/gimp/libpng_compile.patch984
-rw-r--r--testing/gimp/linux.gpl19
-rw-r--r--testing/gimp/uri-backend-libcurl.patch77
6 files changed, 1621 insertions, 0 deletions
diff --git a/testing/gimp/PKGBUILD b/testing/gimp/PKGBUILD
new file mode 100644
index 000000000..ee911ffd7
--- /dev/null
+++ b/testing/gimp/PKGBUILD
@@ -0,0 +1,53 @@
+# $Id: PKGBUILD 148115 2012-01-30 18:46:22Z ibiru $
+# Maintainer: tobias <tobias@archlinux.org>
+
+pkgname=gimp
+pkgver=2.6.11
+pkgrel=8
+pkgdesc="GNU Image Manipulation Program"
+arch=('i686' 'x86_64')
+url="http://www.gimp.org/"
+license=('GPL' 'LGPL')
+depends=('pygtk' 'lcms' 'libxpm' 'libwmf' 'libxmu' 'librsvg' 'libmng' 'dbus-glib' \
+ 'libexif' 'gegl' 'desktop-file-utils' 'hicolor-icon-theme')
+makedepends=('intltool' 'libwebkit' 'poppler-glib' 'alsa-lib' 'iso-codes' 'curl')
+optdepends=('gutenprint: for sophisticated printing only as gimp has built-in cups print support'
+ 'libwebkit: for the help browser'
+ 'poppler-glib: for pdf support'
+ 'alsa-lib: for MIDI event controller module'
+ 'curl: for URI support')
+options=('!libtool' '!makeflags')
+conflicts=('gimp-devel')
+install=gimp.install
+source=(ftp://ftp.gimp.org/pub/gimp/v${pkgver%.*}/${pkgname}-${pkgver}.tar.bz2 linux.gpl
+ uri-backend-libcurl.patch gimp-poppler-0.18.patch libpng_compile.patch)
+sha1sums=('2f9d596e727bdbf304fa78257c1731d9faf3934c'
+ '110ce9798173b19a662d086ed7b882b4729f06cf'
+ 'a65b0ee6cd1b4345065b7b98c07f2fed15f844f4'
+ '1479a6d80be7adf74f66a3b88057a5029fe892e8'
+ '5ce329d2e2cb136e93f16117fa79ab6e31866f68')
+
+build() {
+ cd "${srcdir}/${pkgname}-${pkgver}"
+ patch -p1 < ../uri-backend-libcurl.patch
+ patch -p1 < ../gimp-poppler-0.18.patch
+ patch -p1 < ../libpng_compile.patch
+ PYTHON=/usr/bin/python2 LIBS+="-lgobject-2.0 -lglib-2.0 -lm" \
+ ./configure --prefix=/usr --sysconfdir=/etc \
+ --enable-mp --enable-gimp-console --enable-gimp-remote \
+ --enable-python --with-gif-compression=lzw --with-libcurl \
+ --without-aa --without-hal --without-gvfs --without-gnomevfs
+ make
+}
+
+package() {
+ cd "${srcdir}/${pkgname}-${pkgver}"
+ make DESTDIR="${pkgdir}" install
+ sed -i 's|#!/usr/bin/env python|#!/usr/bin/env python2|' "${pkgdir}"/usr/lib/gimp/2.0/plug-ins/*.py
+ install -D -m644 "${srcdir}/linux.gpl" "${pkgdir}/usr/share/gimp/2.0/palettes/Linux.gpl"
+
+ rm "${pkgdir}/usr/share/man/man1/gimp-console.1"
+ ln -s gimp-console-${pkgver%.*}.1.gz "${pkgdir}/usr/share/man/man1/gimp-console.1.gz"
+ ln -s gimptool-2.0 "${pkgdir}/usr/bin/gimptool"
+ ln -sf gimptool-2.0.1.gz "${pkgdir}/usr/share/man/man1/gimptool.1.gz"
+}
diff --git a/testing/gimp/gimp-poppler-0.18.patch b/testing/gimp/gimp-poppler-0.18.patch
new file mode 100644
index 000000000..0715460bc
--- /dev/null
+++ b/testing/gimp/gimp-poppler-0.18.patch
@@ -0,0 +1,476 @@
+From 69f69eed816b89be9a01a48a1f0643d1fd496118 Mon Sep 17 00:00:00 2001
+From: Nils Philippsen <nils@redhat.com>
+Date: Fri, 6 May 2011 11:58:44 +0200
+Subject: [PATCH] patch: poppler-0.17
+
+Squashed commit of the following:
+
+commit 529d940222dfc352d41fbf72de29134421aa4002
+Author: Nils Philippsen <nils@redhat.com>
+Date: Fri May 6 11:50:30 2011 +0200
+
+ use code based on pixbufs instead of cairo surfaces
+
+ this is done to avoid adding to libgimp, thanks to Mukund Sivaraman for
+ hints how to do this
+
+commit f8671d8767d4cdab830dc06310e96c63a88ec0fd
+Author: Mukund Sivaraman <muks@banu.com>
+Date: Thu Apr 21 13:57:13 2011 +0530
+
+ file-pdf-load: Update attribution, removing bogus copyright
+ (cherry picked from commit e999122e0b20b6ccd6bde3ce039bb64068fc0019)
+
+commit 89a78f2590d298dac2f42e6d9a3016fc5d672c70
+Author: Nils Philippsen <nils@redhat.com>
+Date: Thu Apr 21 13:52:18 2011 +0200
+
+ file-pdf-load: Use better API + cleanups
+
+ * fixes issues with poppler 0.17 completely
+ * uses new libgimp API to pass surfaces instead of pixbufs
+ * uses GTK+ 3 API to convert surfaces to pixbufs where available
+ (backported from commit 7bdadd80ba479d6ff904e276d805e16f6b940ee2)
+
+commit 4e92302c4a14a961f112587a0ad86696c88da2f8
+Author: Nils Philippsen <nils@redhat.com>
+Date: Thu Apr 21 13:38:08 2011 +0200
+
+ file-pdf-load: Don't use deprecated API (bug #646947)
+
+ (cherry picked from commit 9b3e1c91fd2eac69da6947ec9c7fbf10096ba237)
+
+ Conflicts:
+
+ plug-ins/common/file-pdf.c
+---
+ plug-ins/common/file-pdf.c | 323 ++++++++++++++++++++++++++++++++++++++------
+ 1 files changed, 283 insertions(+), 40 deletions(-)
+
+diff --git a/plug-ins/common/file-pdf.c b/plug-ins/common/file-pdf.c
+index a43b459..43c2b7d 100644
+--- a/plug-ins/common/file-pdf.c
++++ b/plug-ins/common/file-pdf.c
+@@ -4,6 +4,9 @@
+ *
+ * Copyright (C) 2005 Nathan Summers
+ *
++ * Some code in render_page_to_surface() borrowed from
++ * poppler.git/glib/poppler-page.cc.
++ *
+ * 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 2 of the License, or
+@@ -80,16 +83,20 @@ static gboolean load_dialog (PopplerDocument *doc,
+ static PopplerDocument * open_document (const gchar *filename,
+ GError **error);
+
+-static GdkPixbuf * get_thumbnail (PopplerDocument *doc,
++static cairo_surface_t * get_thumb_surface (PopplerDocument *doc,
++ gint page,
++ gint preferred_size);
++
++static GdkPixbuf * get_thumb_pixbuf (PopplerDocument *doc,
+ gint page,
+ gint preferred_size);
+
+ static gint32 layer_from_pixbuf (gint32 image,
+- const gchar *layer_name,
+- gint position,
+- GdkPixbuf *buf,
+- gdouble progress_start,
+- gdouble progress_scale);
++ const gchar *layer_name,
++ gint position,
++ GdkPixbuf *pixbuf,
++ gdouble progress_start,
++ gdouble progress_scale);
+
+ /**
+ ** the following was formerly part of
+@@ -433,11 +440,12 @@ run (const gchar *name,
+ }
+ else
+ {
+- gdouble width = 0;
+- gdouble height = 0;
+- gdouble scale;
+- gint32 image = -1;
+- GdkPixbuf *pixbuf = NULL;
++ gdouble width = 0;
++ gdouble height = 0;
++ gdouble scale;
++ gint32 image = -1;
++ gint num_pages = 0;
++ GdkPixbuf *pixbuf = NULL;
+
+ /* Possibly retrieve last settings */
+ gimp_get_data (LOAD_PROC, &loadvals);
+@@ -455,7 +463,10 @@ run (const gchar *name,
+ g_object_unref (page);
+ }
+
+- pixbuf = get_thumbnail (doc, 0, param[1].data.d_int32);
++ num_pages = poppler_document_get_n_pages (doc);
++
++ pixbuf = get_thumb_pixbuf (doc, 0, param[1].data.d_int32);
++
+ g_object_unref (doc);
+ }
+
+@@ -548,6 +559,187 @@ open_document (const gchar *filename,
+ return doc;
+ }
+
++/* FIXME: Remove this someday when we depend fully on GTK+ >= 3 */
++
++#if (!GTK_CHECK_VERSION (3, 0, 0))
++
++static cairo_format_t
++gdk_cairo_format_for_content (cairo_content_t content)
++{
++ switch (content)
++ {
++ case CAIRO_CONTENT_COLOR:
++ return CAIRO_FORMAT_RGB24;
++ case CAIRO_CONTENT_ALPHA:
++ return CAIRO_FORMAT_A8;
++ case CAIRO_CONTENT_COLOR_ALPHA:
++ default:
++ return CAIRO_FORMAT_ARGB32;
++ }
++}
++
++static cairo_surface_t *
++gdk_cairo_surface_coerce_to_image (cairo_surface_t *surface,
++ cairo_content_t content,
++ int src_x,
++ int src_y,
++ int width,
++ int height)
++{
++ cairo_surface_t *copy;
++ cairo_t *cr;
++
++ copy = cairo_image_surface_create (gdk_cairo_format_for_content (content),
++ width,
++ height);
++
++ cr = cairo_create (copy);
++ cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
++ cairo_set_source_surface (cr, surface, -src_x, -src_y);
++ cairo_paint (cr);
++ cairo_destroy (cr);
++
++ return copy;
++}
++
++static void
++convert_alpha (guchar *dest_data,
++ int dest_stride,
++ guchar *src_data,
++ int src_stride,
++ int src_x,
++ int src_y,
++ int width,
++ int height)
++{
++ int x, y;
++
++ src_data += src_stride * src_y + src_x * 4;
++
++ for (y = 0; y < height; y++) {
++ guint32 *src = (guint32 *) src_data;
++
++ for (x = 0; x < width; x++) {
++ guint alpha = src[x] >> 24;
++
++ if (alpha == 0)
++ {
++ dest_data[x * 4 + 0] = 0;
++ dest_data[x * 4 + 1] = 0;
++ dest_data[x * 4 + 2] = 0;
++ }
++ else
++ {
++ dest_data[x * 4 + 0] = (((src[x] & 0xff0000) >> 16) * 255 + alpha / 2) / alpha;
++ dest_data[x * 4 + 1] = (((src[x] & 0x00ff00) >> 8) * 255 + alpha / 2) / alpha;
++ dest_data[x * 4 + 2] = (((src[x] & 0x0000ff) >> 0) * 255 + alpha / 2) / alpha;
++ }
++ dest_data[x * 4 + 3] = alpha;
++ }
++
++ src_data += src_stride;
++ dest_data += dest_stride;
++ }
++}
++
++static void
++convert_no_alpha (guchar *dest_data,
++ int dest_stride,
++ guchar *src_data,
++ int src_stride,
++ int src_x,
++ int src_y,
++ int width,
++ int height)
++{
++ int x, y;
++
++ src_data += src_stride * src_y + src_x * 4;
++
++ for (y = 0; y < height; y++) {
++ guint32 *src = (guint32 *) src_data;
++
++ for (x = 0; x < width; x++) {
++ dest_data[x * 3 + 0] = src[x] >> 16;
++ dest_data[x * 3 + 1] = src[x] >> 8;
++ dest_data[x * 3 + 2] = src[x];
++ }
++
++ src_data += src_stride;
++ dest_data += dest_stride;
++ }
++}
++
++/**
++ * gdk_pixbuf_get_from_surface:
++ * @surface: surface to copy from
++ * @src_x: Source X coordinate within @surface
++ * @src_y: Source Y coordinate within @surface
++ * @width: Width in pixels of region to get
++ * @height: Height in pixels of region to get
++ *
++ * Transfers image data from a #cairo_surface_t and converts it to an RGB(A)
++ * representation inside a #GdkPixbuf. This allows you to efficiently read
++ * individual pixels from cairo surfaces. For #GdkWindows, use
++ * gdk_pixbuf_get_from_window() instead.
++ *
++ * This function will create an RGB pixbuf with 8 bits per channel.
++ * The pixbuf will contain an alpha channel if the @surface contains one.
++ *
++ * Return value: (transfer full): A newly-created pixbuf with a reference
++ * count of 1, or %NULL on error
++ */
++static GdkPixbuf *
++gdk_pixbuf_get_from_surface (cairo_surface_t *surface,
++ gint src_x,
++ gint src_y,
++ gint width,
++ gint height)
++{
++ cairo_content_t content;
++ GdkPixbuf *dest;
++
++ /* General sanity checks */
++ g_return_val_if_fail (surface != NULL, NULL);
++ g_return_val_if_fail (width > 0 && height > 0, NULL);
++
++ content = cairo_surface_get_content (surface) | CAIRO_CONTENT_COLOR;
++ dest = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
++ !!(content & CAIRO_CONTENT_ALPHA),
++ 8,
++ width, height);
++
++ surface = gdk_cairo_surface_coerce_to_image (surface, content,
++ src_x, src_y,
++ width, height);
++ cairo_surface_flush (surface);
++ if (cairo_surface_status (surface) || dest == NULL)
++ {
++ cairo_surface_destroy (surface);
++ return NULL;
++ }
++
++ if (gdk_pixbuf_get_has_alpha (dest))
++ convert_alpha (gdk_pixbuf_get_pixels (dest),
++ gdk_pixbuf_get_rowstride (dest),
++ cairo_image_surface_get_data (surface),
++ cairo_image_surface_get_stride (surface),
++ 0, 0,
++ width, height);
++ else
++ convert_no_alpha (gdk_pixbuf_get_pixels (dest),
++ gdk_pixbuf_get_rowstride (dest),
++ cairo_image_surface_get_data (surface),
++ cairo_image_surface_get_stride (surface),
++ 0, 0,
++ width, height);
++
++ cairo_surface_destroy (surface);
++ return dest;
++}
++
++#endif
++
+ static gint32
+ layer_from_pixbuf (gint32 image,
+ const gchar *layer_name,
+@@ -566,6 +758,54 @@ layer_from_pixbuf (gint32 image,
+ return layer;
+ }
+
++static cairo_surface_t *
++render_page_to_surface (PopplerPage *page,
++ int width,
++ int height,
++ double scale)
++{
++ cairo_surface_t *surface;
++ cairo_t *cr;
++
++ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
++ cr = cairo_create (surface);
++
++ cairo_save (cr);
++ cairo_translate (cr, 0.0, 0.0);
++
++ if (scale != 1.0)
++ cairo_scale (cr, scale, scale);
++
++ poppler_page_render (page, cr);
++ cairo_restore (cr);
++
++ cairo_set_operator (cr, CAIRO_OPERATOR_DEST_OVER);
++ cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
++ cairo_paint (cr);
++
++ cairo_destroy (cr);
++
++ return surface;
++}
++
++static GdkPixbuf *
++render_page_to_pixbuf (PopplerPage *page,
++ int width,
++ int height,
++ double scale)
++{
++ GdkPixbuf *pixbuf;
++ cairo_surface_t *surface;
++
++ surface = render_page_to_surface (page, width, height, scale);
++ pixbuf = gdk_pixbuf_get_from_surface (surface, 0, 0,
++ cairo_image_surface_get_width (surface),
++ cairo_image_surface_get_height (surface));
++ cairo_surface_destroy (surface);
++
++ return pixbuf;
++}
++
+ static gint32
+ load_image (PopplerDocument *doc,
+ const gchar *filename,
+@@ -597,7 +837,7 @@ load_image (PopplerDocument *doc,
+ gdouble page_width;
+ gdouble page_height;
+
+- GdkPixbuf *buf;
++ GdkPixbuf *pixbuf;
+ gint width;
+ gint height;
+
+@@ -627,15 +867,13 @@ load_image (PopplerDocument *doc,
+ gimp_image_set_resolution (image_ID, resolution, resolution);
+ }
+
+- buf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, width, height);
+-
+- poppler_page_render_to_pixbuf (page, 0, 0, width, height, scale, 0, buf);
++ pixbuf = render_page_to_pixbuf (page, width, height, scale);
+
+- layer_from_pixbuf (image_ID, page_label, i, buf,
++ layer_from_pixbuf (image_ID, page_label, i, pixbuf,
+ doc_progress, 1.0 / pages->n_pages);
+
+ g_free (page_label);
+- g_object_unref (buf);
++ g_object_unref(pixbuf);
+
+ doc_progress = (double) (i + 1) / pages->n_pages;
+ gimp_progress_update (doc_progress);
+@@ -676,30 +914,22 @@ load_image (PopplerDocument *doc,
+ return image_ID;
+ }
+
+-static GdkPixbuf *
+-get_thumbnail (PopplerDocument *doc,
+- gint page_num,
+- gint preferred_size)
++static cairo_surface_t *
++get_thumb_surface (PopplerDocument *doc,
++ gint page_num,
++ gint preferred_size)
+ {
+ PopplerPage *page;
+- GdkPixbuf *pixbuf;
++ cairo_surface_t *surface;
+
+ page = poppler_document_get_page (doc, page_num);
+
+ if (! page)
+ return NULL;
+
+- /* XXX: Remove conditional when we depend on poppler 0.8.0, but also
+- * add configure check to make sure POPPLER_WITH_GDK is enabled!
+- */
+-#ifdef POPPLER_WITH_GDK
+- pixbuf = poppler_page_get_thumbnail_pixbuf (page);
+-#else
+- pixbuf = poppler_page_get_thumbnail (page);
+-#endif
+-
++ surface = poppler_page_get_thumbnail (page);
+
+- if (! pixbuf)
++ if (! surface)
+ {
+ gdouble width;
+ gdouble height;
+@@ -712,15 +942,28 @@ get_thumbnail (PopplerDocument *doc,
+ width *= scale;
+ height *= scale;
+
+- pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8,
+- width, height);
+-
+- poppler_page_render_to_pixbuf (page,
+- 0, 0, width, height, scale, 0, pixbuf);
++ surface = render_page_to_surface (page, width, height, scale);
+ }
+
+ g_object_unref (page);
+
++ return surface;
++}
++
++static GdkPixbuf *
++get_thumb_pixbuf (PopplerDocument *doc,
++ gint page_num,
++ gint preferred_size)
++{
++ cairo_surface_t *surface;
++ GdkPixbuf *pixbuf;
++
++ surface = get_thumb_surface (doc, page_num, preferred_size);
++ pixbuf = gdk_pixbuf_get_from_surface (surface, 0, 0,
++ cairo_image_surface_get_width (surface),
++ cairo_image_surface_get_height (surface));
++ cairo_surface_destroy (surface);
++
+ return pixbuf;
+ }
+
+@@ -769,8 +1012,8 @@ thumbnail_thread (gpointer data)
+ idle_data->page_no = i;
+
+ /* FIXME get preferred size from somewhere? */
+- idle_data->pixbuf = get_thumbnail (thread_data->document, i,
+- THUMBNAIL_SIZE);
++ idle_data->pixbuf = get_thumb_pixbuf (thread_data->document, i,
++ THUMBNAIL_SIZE);
+
+ g_idle_add (idle_set_thumbnail, idle_data);
+
+--
+1.7.5
diff --git a/testing/gimp/gimp.install b/testing/gimp/gimp.install
new file mode 100644
index 000000000..c317fbaca
--- /dev/null
+++ b/testing/gimp/gimp.install
@@ -0,0 +1,12 @@
+post_install() {
+ update-desktop-database -q
+ gtk-update-icon-cache -q -t -f usr/share/icons/hicolor
+}
+
+post_upgrade() {
+ post_install
+}
+
+post_remove() {
+ post_install
+}
diff --git a/testing/gimp/libpng_compile.patch b/testing/gimp/libpng_compile.patch
new file mode 100644
index 000000000..26d3f9427
--- /dev/null
+++ b/testing/gimp/libpng_compile.patch
@@ -0,0 +1,984 @@
+Description: fix compilation against libpng 1.5
+Origin: upstream, 2.6 branch, diff of 2917a0e..e7469007
+Bug-Debian: http://bugs.debian.org/649972
+
+diff --git a/plug-ins/common/file-mng.c b/plug-ins/common/file-mng.c
+index 29dd155..8054504 100644
+--- a/plug-ins/common/file-mng.c
++++ b/plug-ins/common/file-mng.c
+@@ -136,7 +136,6 @@ struct mng_data_t
+ gint32 default_dispose;
+ };
+
+-
+ /* Values of the instance of the above struct when the plug-in is
+ * first invoked. */
+
+@@ -160,6 +159,21 @@ static struct mng_data_t mng_data =
+ };
+
+
++/* These are not saved or restored. */
++
++struct mng_globals_t
++{
++ gboolean has_trns;
++ png_bytep trans;
++ int num_trans;
++ gboolean has_plte;
++ png_colorp palette;
++ int num_palette;
++};
++
++static struct mng_globals_t mngg;
++
++
+ /* The output FILE pointer which is used by libmng;
+ * passed around as user data. */
+ struct mnglib_userdata_t
+@@ -196,7 +210,8 @@ static gboolean respin_cmap (png_structp png_ptr,
+ png_infop png_info_ptr,
+ guchar *remap,
+ gint32 image_id,
+- GimpDrawable *drawable);
++ GimpDrawable *drawable,
++ int *bit_depth);
+
+ static gboolean mng_save_image (const gchar *filename,
+ gint32 image_id,
+@@ -414,6 +429,18 @@ ia_has_transparent_pixels (guchar *pixels,
+ return FALSE;
+ }
+
++static int
++get_bit_depth_for_palette (int num_palette)
++{
++ if (num_palette <= 2)
++ return 1;
++ else if (num_palette <= 4)
++ return 2;
++ else if (num_palette <= 16)
++ return 4;
++ else
++ return 8;
++}
+
+ /* Spins the color map (palette) putting the transparent color at
+ * index 0 if there is space. If there isn't any space, warn the user
+@@ -422,11 +449,12 @@ ia_has_transparent_pixels (guchar *pixels,
+ */
+
+ static gboolean
+-respin_cmap (png_structp png_ptr,
+- png_infop png_info_ptr,
++respin_cmap (png_structp pp,
++ png_infop info,
+ guchar *remap,
+ gint32 image_id,
+- GimpDrawable *drawable)
++ GimpDrawable *drawable,
++ int *bit_depth)
+ {
+ static guchar trans[] = { 0 };
+ guchar *before;
+@@ -464,10 +492,13 @@ respin_cmap (png_structp png_ptr,
+
+ if (transparent != -1)
+ {
+- png_color palette[256] = { {0, 0, 0} };
++ static png_color palette[256] = { {0, 0, 0} };
+ gint i;
+
+- png_set_tRNS (png_ptr, png_info_ptr, (png_bytep) trans, 1, NULL);
++ /* Set tRNS chunk values for writing later. */
++ mngg.has_trns = TRUE;
++ mngg.trans = trans;
++ mngg.num_trans = 1;
+
+ /* Transform all pixels with a value = transparent to
+ * 0 and vice versa to compensate for re-ordering in palette
+@@ -489,7 +520,12 @@ respin_cmap (png_structp png_ptr,
+ palette[i].blue = before[3 * remap[i] + 2];
+ }
+
+- png_set_PLTE (png_ptr, png_info_ptr, (png_colorp) palette, colors);
++ /* Set PLTE chunk values for writing later. */
++ mngg.has_plte = TRUE;
++ mngg.palette = palette;
++ mngg.num_palette = colors;
++
++ *bit_depth = get_bit_depth_for_palette (colors);
+
+ return TRUE;
+ }
+@@ -500,7 +536,10 @@ respin_cmap (png_structp png_ptr,
+ }
+ }
+
+- png_set_PLTE (png_ptr, png_info_ptr, (png_colorp) before, colors);
++ mngg.has_plte = TRUE;
++ mngg.palette = (png_colorp) before;
++ mngg.num_palette = colors;
++ *bit_depth = get_bit_depth_for_palette (colors);
+
+ return FALSE;
+ }
+@@ -777,7 +816,6 @@ mng_save_image (const gchar *filename,
+
+ for (i = (num_layers - 1); i >= 0; i--)
+ {
+- gint num_colors;
+ GimpImageType layer_drawable_type;
+ GimpDrawable *layer_drawable;
+ gint layer_offset_x, layer_offset_y;
+@@ -795,8 +833,8 @@ mng_save_image (const gchar *filename,
+ gchar frame_mode;
+ int frame_delay;
+ gchar *temp_file_name;
+- png_structp png_ptr;
+- png_infop png_info_ptr;
++ png_structp pp;
++ png_infop info;
+ FILE *infile, *outfile;
+ int num_passes;
+ int tile_height;
+@@ -804,6 +842,8 @@ mng_save_image (const gchar *filename,
+ int pass, j, k, begin, end, num;
+ guchar *fixed;
+ guchar layer_remap[256];
++ int color_type;
++ int bit_depth;
+
+ layer_name = gimp_drawable_get_name (layers[i]);
+ layer_chunks_type = parse_chunks_type_from_layer_name (layer_name);
+@@ -948,9 +988,9 @@ mng_save_image (const gchar *filename,
+ goto err3;
+ }
+
+- png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING,
++ pp = png_create_write_struct (PNG_LIBPNG_VER_STRING,
+ NULL, NULL, NULL);
+- if (NULL == png_ptr)
++ if (NULL == pp)
+ {
+ g_warning ("Unable to png_create_write_struct() in mng_save_image()");
+ fclose (outfile);
+@@ -958,89 +998,97 @@ mng_save_image (const gchar *filename,
+ goto err3;
+ }
+
+- png_info_ptr = png_create_info_struct (png_ptr);
+- if (NULL == png_info_ptr)
++ info = png_create_info_struct (pp);
++ if (NULL == info)
+ {
+ g_warning
+ ("Unable to png_create_info_struct() in mng_save_image()");
+- png_destroy_write_struct (&png_ptr, NULL);
++ png_destroy_write_struct (&pp, NULL);
+ fclose (outfile);
+ g_unlink (temp_file_name);
+ goto err3;
+ }
+
+- if (setjmp (png_ptr->jmpbuf) != 0)
++ if (setjmp (png_jmpbuf (pp)) != 0)
+ {
+ g_warning ("HRM saving PNG in mng_save_image()");
+- png_destroy_write_struct (&png_ptr, &png_info_ptr);
++ png_destroy_write_struct (&pp, &info);
+ fclose (outfile);
+ g_unlink (temp_file_name);
+ goto err3;
+ }
+
+- png_init_io (png_ptr, outfile);
+- png_set_compression_level (png_ptr, mng_data.compression_level);
++ png_init_io (pp, outfile);
+
+- png_info_ptr->width = layer_cols;
+- png_info_ptr->height = layer_rows;
+- png_info_ptr->interlace_type = (mng_data.interlaced == 0 ? 0 : 1);
+- png_info_ptr->bit_depth = 8;
++ bit_depth = 8;
+
+ switch (layer_drawable_type)
+ {
+ case GIMP_RGB_IMAGE:
+- png_info_ptr->color_type = PNG_COLOR_TYPE_RGB;
++ color_type = PNG_COLOR_TYPE_RGB;
+ break;
+ case GIMP_RGBA_IMAGE:
+- png_info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
++ color_type = PNG_COLOR_TYPE_RGB_ALPHA;
+ break;
+ case GIMP_GRAY_IMAGE:
+- png_info_ptr->color_type = PNG_COLOR_TYPE_GRAY;
++ color_type = PNG_COLOR_TYPE_GRAY;
+ break;
+ case GIMP_GRAYA_IMAGE:
+- png_info_ptr->color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
++ color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
+ break;
+ case GIMP_INDEXED_IMAGE:
+- png_info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
+- png_info_ptr->valid |= PNG_INFO_PLTE;
+- png_info_ptr->palette =
+- (png_colorp) gimp_image_get_colormap (image_id, &num_colors);
+- png_info_ptr->num_palette = num_colors;
++ color_type = PNG_COLOR_TYPE_PALETTE;
++ mngg.has_plte = TRUE;
++ mngg.palette = (png_colorp)
++ gimp_image_get_colormap (image_id, &mngg.num_palette);
++ bit_depth = get_bit_depth_for_palette (mngg.num_palette);
+ break;
+ case GIMP_INDEXEDA_IMAGE:
+- png_info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
++ color_type = PNG_COLOR_TYPE_PALETTE;
+ layer_has_unique_palette =
+- respin_cmap (png_ptr, png_info_ptr, layer_remap,
+- image_id, layer_drawable);
++ respin_cmap (pp, info, layer_remap,
++ image_id, layer_drawable,
++ &bit_depth);
+ break;
+ default:
+ g_warning ("This can't be!\n");
+- png_destroy_write_struct (&png_ptr, &png_info_ptr);
++ png_destroy_write_struct (&pp, &info);
+ fclose (outfile);
+ g_unlink (temp_file_name);
+ goto err3;
+ }
+
+- if ((png_info_ptr->valid & PNG_INFO_PLTE) == PNG_INFO_PLTE)
++ /* Note: png_set_IHDR() must be called before any other
++ png_set_*() functions. */
++ png_set_IHDR (pp, info, layer_cols, layer_rows,
++ bit_depth,
++ color_type,
++ mng_data.interlaced ? PNG_INTERLACE_ADAM7 : PNG_INTERLACE_NONE,
++ PNG_COMPRESSION_TYPE_BASE,
++ PNG_FILTER_TYPE_BASE);
++
++ if (mngg.has_trns)
++ {
++ png_set_tRNS (pp, info, mngg.trans, mngg.num_trans, NULL);
++ }
++
++ if (mngg.has_plte)
+ {
+- if (png_info_ptr->num_palette <= 2)
+- png_info_ptr->bit_depth = 1;
+- else if (png_info_ptr->num_palette <= 4)
+- png_info_ptr->bit_depth = 2;
+- else if (png_info_ptr->num_palette <= 16)
+- png_info_ptr->bit_depth = 4;
++ png_set_PLTE (pp, info, mngg.palette, mngg.num_palette);
+ }
+
+- png_write_info (png_ptr, png_info_ptr);
++ png_set_compression_level (pp, mng_data.compression_level);
++
++ png_write_info (pp, info);
+
+ if (mng_data.interlaced != 0)
+- num_passes = png_set_interlace_handling (png_ptr);
++ num_passes = png_set_interlace_handling (pp);
+ else
+ num_passes = 1;
+
+- if ((png_info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) &&
+- (png_info_ptr->bit_depth < 8))
+- png_set_packing (png_ptr);
++ if ((color_type == PNG_COLOR_TYPE_PALETTE) &&
++ (bit_depth < 8))
++ png_set_packing (pp);
+
+ tile_height = gimp_tile_height ();
+ layer_pixel = g_new (guchar, tile_height * layer_cols * layer_bpp);
+@@ -1065,7 +1113,7 @@ mng_save_image (const gchar *filename,
+ gimp_pixel_rgn_get_rect (&layer_pixel_rgn, layer_pixel, 0,
+ begin, layer_cols, num);
+
+- if ((png_info_ptr->valid & PNG_INFO_tRNS) == PNG_INFO_tRNS)
++ if (png_get_valid (pp, info, PNG_INFO_tRNS))
+ {
+ for (j = 0; j < num; j++)
+ {
+@@ -1077,7 +1125,7 @@ mng_save_image (const gchar *filename,
+ }
+ }
+ else
+- if (((png_info_ptr->valid & PNG_INFO_PLTE) == PNG_INFO_PLTE)
++ if (png_get_valid (pp, info, PNG_INFO_PLTE)
+ && (layer_bpp == 2))
+ {
+ for (j = 0; j < num; j++)
+@@ -1089,12 +1137,12 @@ mng_save_image (const gchar *filename,
+ }
+ }
+
+- png_write_rows (png_ptr, layer_pixels, num);
++ png_write_rows (pp, layer_pixels, num);
+ }
+ }
+
+- png_write_end (png_ptr, png_info_ptr);
+- png_destroy_write_struct (&png_ptr, &png_info_ptr);
++ png_write_end (pp, info);
++ png_destroy_write_struct (&pp, &info);
+
+ g_free (layer_pixels);
+ g_free (layer_pixel);
+diff --git a/plug-ins/common/file-png.c b/plug-ins/common/file-png.c
+index d42afff..8fa8983 100644
+--- a/plug-ins/common/file-png.c
++++ b/plug-ins/common/file-png.c
+@@ -106,6 +106,17 @@ typedef struct
+ }
+ PngSaveGui;
+
++/* These are not saved or restored. */
++typedef struct
++{
++ gboolean has_trns;
++ png_bytep trans;
++ int num_trans;
++ gboolean has_plte;
++ png_colorp palette;
++ int num_palette;
++}
++PngGlobals;
+
+ /*
+ * Local functions...
+@@ -127,7 +138,7 @@ static gboolean save_image (const gchar *filename,
+ gint32 orig_image_ID,
+ GError **error);
+
+-static void respin_cmap (png_structp pp,
++static int respin_cmap (png_structp pp,
+ png_infop info,
+ guchar *remap,
+ gint32 image_ID,
+@@ -175,6 +186,7 @@ static const PngSaveVals defaults =
+ };
+
+ static PngSaveVals pngvals;
++static PngGlobals pngg;
+
+
+ /*
+@@ -653,13 +665,25 @@ on_read_error (png_structp png_ptr, png_const_charp error_msg)
+ error_data->drawable->width, num);
+ }
+
+- longjmp (png_ptr->jmpbuf, 1);
++ longjmp (png_jmpbuf (png_ptr), 1);
++}
++
++static int
++get_bit_depth_for_palette (int num_palette)
++{
++ if (num_palette <= 2)
++ return 1;
++ else if (num_palette <= 4)
++ return 2;
++ else if (num_palette <= 16)
++ return 4;
++ else
++ return 8;
+ }
+
+ /*
+ * 'load_image()' - Load a PNG image into a new image window.
+ */
+-
+ static gint32
+ load_image (const gchar *filename,
+ gboolean interactive,
+@@ -695,9 +719,20 @@ load_image (const gchar *filename,
+ gint num_texts;
+
+ pp = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
++ if (!pp)
++ {
++ /* this could happen if the compile time and run-time libpng
++ versions do not match. */
++
++ g_set_error (error, 0, 0,
++ _("Error creating PNG read struct while saving '%s'."),
++ gimp_filename_to_utf8 (filename));
++ return -1;
++ }
++
+ info = png_create_info_struct (pp);
+
+- if (setjmp (pp->jmpbuf))
++ if (setjmp (png_jmpbuf (pp)))
+ {
+ g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
+ _("Error while reading '%s'. File corrupted?"),
+@@ -705,10 +740,6 @@ load_image (const gchar *filename,
+ return image;
+ }
+
+- /* initialise image here, thus avoiding compiler warnings */
+-
+- image = -1;
+-
+ /*
+ * Open the file and initialize the PNG read "engine"...
+ */
+@@ -738,17 +769,19 @@ load_image (const gchar *filename,
+ * Latest attempt, this should be my best yet :)
+ */
+
+- if (info->bit_depth == 16)
++ if (png_get_bit_depth (pp, info) == 16)
+ {
+ png_set_strip_16 (pp);
+ }
+
+- if (info->color_type == PNG_COLOR_TYPE_GRAY && info->bit_depth < 8)
++ if (png_get_color_type (pp, info) == PNG_COLOR_TYPE_GRAY &&
++ png_get_bit_depth (pp, info) < 8)
+ {
+ png_set_expand (pp);
+ }
+
+- if (info->color_type == PNG_COLOR_TYPE_PALETTE && info->bit_depth < 8)
++ if (png_get_color_type (pp, info) == PNG_COLOR_TYPE_PALETTE &&
++ png_get_bit_depth (pp, info) < 8)
+ {
+ png_set_packing (pp);
+ }
+@@ -757,8 +790,8 @@ load_image (const gchar *filename,
+ * Expand G+tRNS to GA, RGB+tRNS to RGBA
+ */
+
+- if (info->color_type != PNG_COLOR_TYPE_PALETTE &&
+- (info->valid & PNG_INFO_tRNS))
++ if (png_get_color_type (pp, info) != PNG_COLOR_TYPE_PALETTE &&
++ png_get_valid (pp, info, PNG_INFO_tRNS))
+ {
+ png_set_expand (pp);
+ }
+@@ -775,7 +808,7 @@ load_image (const gchar *filename,
+ */
+
+ if (png_get_valid (pp, info, PNG_INFO_tRNS) &&
+- info->color_type == PNG_COLOR_TYPE_PALETTE)
++ png_get_color_type (pp, info) == PNG_COLOR_TYPE_PALETTE)
+ {
+ png_get_tRNS (pp, info, &alpha_ptr, &num, NULL);
+ /* Copy the existing alpha values from the tRNS chunk */
+@@ -797,7 +830,7 @@ load_image (const gchar *filename,
+
+ png_read_update_info (pp, info);
+
+- switch (info->color_type)
++ switch (png_get_color_type (pp, info))
+ {
+ case PNG_COLOR_TYPE_RGB: /* RGB */
+ bpp = 3;
+@@ -836,7 +869,9 @@ load_image (const gchar *filename,
+ return -1;
+ }
+
+- image = gimp_image_new (info->width, info->height, image_type);
++ image = gimp_image_new (png_get_image_width (pp, info),
++ png_get_image_height (pp, info),
++ image_type);
+ if (image == -1)
+ {
+ g_set_error (error, 0, 0,
+@@ -849,7 +884,9 @@ load_image (const gchar *filename,
+ * Create the "background" layer to hold the image...
+ */
+
+- layer = gimp_layer_new (image, _("Background"), info->width, info->height,
++ layer = gimp_layer_new (image, _("Background"),
++ png_get_image_width (pp, info),
++ png_get_image_height (pp, info),
+ layer_type, 100, GIMP_NORMAL_MODE);
+ gimp_image_add_layer (image, layer, 0);
+
+@@ -883,7 +920,8 @@ load_image (const gchar *filename,
+
+ gimp_layer_set_offsets (layer, offset_x, offset_y);
+
+- if ((abs (offset_x) > info->width) || (abs (offset_y) > info->height))
++ if ((abs (offset_x) > png_get_image_width (pp, info)) ||
++ (abs (offset_y) > png_get_image_height (pp, info)))
+ {
+ if (interactive)
+ g_message (_("The PNG file specifies an offset that caused "
+@@ -938,23 +976,27 @@ load_image (const gchar *filename,
+
+ empty = 0; /* by default assume no full transparent palette entries */
+
+- if (info->color_type & PNG_COLOR_MASK_PALETTE)
++ if (png_get_color_type (pp, info) & PNG_COLOR_MASK_PALETTE)
+ {
++ png_colorp palette;
++ int num_palette;
++
++ png_get_PLTE (pp, info, &palette, &num_palette);
+ if (png_get_valid (pp, info, PNG_INFO_tRNS))
+ {
+ for (empty = 0; empty < 256 && alpha[empty] == 0; ++empty)
+ /* Calculates number of fully transparent "empty" entries */;
+
+ /* keep at least one entry */
+- empty = MIN (empty, info->num_palette - 1);
++ empty = MIN (empty, num_palette - 1);
+
+- gimp_image_set_colormap (image, (guchar *) (info->palette + empty),
+- info->num_palette - empty);
++ gimp_image_set_colormap (image, (guchar *) (palette + empty),
++ num_palette - empty);
+ }
+ else
+ {
+- gimp_image_set_colormap (image, (guchar *) info->palette,
+- info->num_palette);
++ gimp_image_set_colormap (image, (guchar *) palette,
++ num_palette);
+ }
+ }
+
+@@ -972,18 +1014,19 @@ load_image (const gchar *filename,
+ */
+
+ tile_height = gimp_tile_height ();
+- pixel = g_new0 (guchar, tile_height * info->width * bpp);
++ pixel = g_new0 (guchar, tile_height * png_get_image_width (pp, info) * bpp);
+ pixels = g_new (guchar *, tile_height);
+
+ for (i = 0; i < tile_height; i++)
+- pixels[i] = pixel + info->width * info->channels * i;
++ pixels[i] = pixel + png_get_image_width (pp, info) *
++ png_get_channels (pp, info) * i;
+
+ /* Install our own error handler to handle incomplete PNG files better */
+ error_data.drawable = drawable;
+ error_data.pixel = pixel;
+ error_data.tile_height = tile_height;
+- error_data.width = info->width;
+- error_data.height = info->height;
++ error_data.width = png_get_image_width (pp, info);
++ error_data.height = png_get_image_height (pp, info);
+ error_data.bpp = bpp;
+ error_data.pixel_rgn = &pixel_rgn;
+
+@@ -996,10 +1039,11 @@ load_image (const gchar *filename,
+ */
+
+ for (begin = 0, end = tile_height;
+- begin < info->height; begin += tile_height, end += tile_height)
++ begin < png_get_image_height (pp, info);
++ begin += tile_height, end += tile_height)
+ {
+- if (end > info->height)
+- end = info->height;
++ if (end > png_get_image_height (pp, info))
++ end = png_get_image_height (pp, info);
+
+ num = end - begin;
+
+@@ -1016,11 +1060,13 @@ load_image (const gchar *filename,
+ gimp_pixel_rgn_set_rect (&pixel_rgn, pixel, 0, begin,
+ drawable->width, num);
+
+- memset (pixel, 0, tile_height * info->width * bpp);
++ memset (pixel, 0,
++ tile_height * png_get_image_width (pp, info) * bpp);
+
+- gimp_progress_update (((gdouble) pass +
+- (gdouble) end / (gdouble) info->height) /
+- (gdouble) num_passes);
++ gimp_progress_update
++ (((gdouble) pass +
++ (gdouble) end / (gdouble) png_get_image_height (pp, info)) /
++ (gdouble) num_passes);
+ }
+ }
+
+@@ -1189,7 +1235,6 @@ save_image (const gchar *filename,
+ GimpPixelRgn pixel_rgn; /* Pixel region for layer */
+ png_structp pp; /* PNG read pointer */
+ png_infop info; /* PNG info pointer */
+- gint num_colors; /* Number of colors in colormap */
+ gint offx, offy; /* Drawable offsets from origin */
+ guchar **pixels, /* Pixel rows */
+ *fixed, /* Fixed-up pixel data */
+@@ -1200,56 +1245,28 @@ save_image (const gchar *filename,
+ guchar red, green, blue; /* Used for palette background */
+ time_t cutime; /* Time since epoch */
+ struct tm *gmt; /* GMT broken down */
++ int color_type;
++ int bit_depth;
+
+ guchar remap[256]; /* Re-mapping for the palette */
+
+ png_textp text = NULL;
+
+- if (pngvals.comment)
++ pp = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
++ if (!pp)
+ {
+- GimpParasite *parasite;
+- gsize text_length = 0;
+-
+- parasite = gimp_image_parasite_find (orig_image_ID, "gimp-comment");
+- if (parasite)
+- {
+- gchar *comment = g_strndup (gimp_parasite_data (parasite),
+- gimp_parasite_data_size (parasite));
++ /* this could happen if the compile time and run-time libpng
++ versions do not match. */
+
+- gimp_parasite_free (parasite);
+-
+- text = g_new0 (png_text, 1);
+- text->key = "Comment";
+-
+-#ifdef PNG_iTXt_SUPPORTED
+-
+- text->compression = PNG_ITXT_COMPRESSION_NONE;
+- text->text = comment;
+- text->itxt_length = strlen (comment);
+-
+-#else
+-
+- text->compression = PNG_TEXT_COMPRESSION_NONE;
+- text->text = g_convert (comment, -1,
+- "ISO-8859-1", "UTF-8",
+- NULL, &text_length,
+- NULL);
+- text->text_length = text_length;
+-
+-#endif
+-
+- if (!text->text)
+- {
+- g_free (text);
+- text = NULL;
+- }
+- }
++ g_set_error (error, 0, 0,
++ _("Error creating PNG write struct while saving '%s'."),
++ gimp_filename_to_utf8 (filename));
++ return FALSE;
+ }
+
+- pp = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ info = png_create_info_struct (pp);
+
+- if (setjmp (pp->jmpbuf))
++ if (setjmp (png_jmpbuf (pp)))
+ {
+ g_set_error (error, 0, 0,
+ _("Error while saving '%s'. Could not save image."),
+@@ -1257,9 +1274,6 @@ save_image (const gchar *filename,
+ return FALSE;
+ }
+
+- if (text)
+- png_set_text (pp, info, text, 1);
+-
+ /*
+ * Open the file and initialize the PNG write "engine"...
+ */
+@@ -1286,17 +1300,6 @@ save_image (const gchar *filename,
+ type = gimp_drawable_type (drawable_ID);
+
+ /*
+- * Set the image dimensions, bit depth, interlacing and compression
+- */
+-
+- png_set_compression_level (pp, pngvals.compression_level);
+-
+- info->width = drawable->width;
+- info->height = drawable->height;
+- info->bit_depth = 8;
+- info->interlace_type = pngvals.interlaced;
+-
+- /*
+ * Initialise remap[]
+ */
+ for (i = 0; i < 256; i++)
+@@ -1306,42 +1309,44 @@ save_image (const gchar *filename,
+ * Set color type and remember bytes per pixel count
+ */
+
++ bit_depth = 8;
++
+ switch (type)
+ {
+ case GIMP_RGB_IMAGE:
+- info->color_type = PNG_COLOR_TYPE_RGB;
++ color_type = PNG_COLOR_TYPE_RGB;
+ bpp = 3;
+ break;
+
+ case GIMP_RGBA_IMAGE:
+- info->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
++ color_type = PNG_COLOR_TYPE_RGB_ALPHA;
+ bpp = 4;
+ break;
+
+ case GIMP_GRAY_IMAGE:
+- info->color_type = PNG_COLOR_TYPE_GRAY;
++ color_type = PNG_COLOR_TYPE_GRAY;
+ bpp = 1;
+ break;
+
+ case GIMP_GRAYA_IMAGE:
+- info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
++ color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
+ bpp = 2;
+ break;
+
+ case GIMP_INDEXED_IMAGE:
+ bpp = 1;
+- info->color_type = PNG_COLOR_TYPE_PALETTE;
+- info->valid |= PNG_INFO_PLTE;
+- info->palette =
+- (png_colorp) gimp_image_get_colormap (image_ID, &num_colors);
+- info->num_palette = num_colors;
++ color_type = PNG_COLOR_TYPE_PALETTE;
++ pngg.has_plte = TRUE;
++ pngg.palette = (png_colorp) gimp_image_get_colormap (image_ID,
++ &pngg.num_palette);
++ bit_depth = get_bit_depth_for_palette (pngg.num_palette);
+ break;
+
+ case GIMP_INDEXEDA_IMAGE:
+ bpp = 2;
+- info->color_type = PNG_COLOR_TYPE_PALETTE;
++ color_type = PNG_COLOR_TYPE_PALETTE;
+ /* fix up transparency */
+- respin_cmap (pp, info, remap, image_ID, drawable);
++ bit_depth = respin_cmap (pp, info, remap, image_ID, drawable);
+ break;
+
+ default:
+@@ -1349,21 +1354,29 @@ save_image (const gchar *filename,
+ return FALSE;
+ }
+
+- /*
+- * Fix bit depths for (possibly) smaller colormap images
+- */
++ /* Note: png_set_IHDR() must be called before any other png_set_*()
++ functions. */
++ png_set_IHDR (pp, info, drawable->width, drawable->height,
++ bit_depth,
++ color_type,
++ pngvals.interlaced ? PNG_INTERLACE_ADAM7 : PNG_INTERLACE_NONE,
++ PNG_COMPRESSION_TYPE_BASE,
++ PNG_FILTER_TYPE_BASE);
++
++ if (pngg.has_trns)
++ {
++ png_set_tRNS (pp, info, pngg.trans, pngg.num_trans, NULL);
++ }
+
+- if (info->valid & PNG_INFO_PLTE)
++ if (pngg.has_plte)
+ {
+- if (info->num_palette <= 2)
+- info->bit_depth = 1;
+- else if (info->num_palette <= 4)
+- info->bit_depth = 2;
+- else if (info->num_palette <= 16)
+- info->bit_depth = 4;
+- /* otherwise the default is fine */
++ png_set_PLTE (pp, info, pngg.palette, pngg.num_palette);
+ }
+
++ /* Set the compression level */
++
++ png_set_compression_level (pp, pngvals.compression_level);
++
+ /* All this stuff is optional extras, if the user is aiming for smallest
+ possible file size she can turn them all off */
+
+@@ -1462,6 +1475,52 @@ save_image (const gchar *filename,
+ }
+ #endif
+
++ if (pngvals.comment)
++ {
++ GimpParasite *parasite;
++#ifndef PNG_iTXt_SUPPORTED
++ gsize text_length = 0;
++#endif /* PNG_iTXt_SUPPORTED */
++
++ parasite = gimp_image_parasite_find (orig_image_ID, "gimp-comment");
++ if (parasite)
++ {
++ gchar *comment = g_strndup (gimp_parasite_data (parasite),
++ gimp_parasite_data_size (parasite));
++
++ gimp_parasite_free (parasite);
++
++ text = g_new0 (png_text, 1);
++ text->key = "Comment";
++
++#ifdef PNG_iTXt_SUPPORTED
++
++ text->compression = PNG_ITXT_COMPRESSION_NONE;
++ text->text = comment;
++ text->itxt_length = strlen (comment);
++
++#else
++
++ text->compression = PNG_TEXT_COMPRESSION_NONE;
++ text->text = g_convert (comment, -1,
++ "ISO-8859-1", "UTF-8",
++ NULL, &text_length,
++ NULL);
++ text->text_length = text_length;
++
++#endif
++
++ if (!text->text)
++ {
++ g_free (text);
++ text = NULL;
++ }
++ }
++ }
++
++ if (text)
++ png_set_text (pp, info, text, 1);
++
+ png_write_info (pp, info);
+
+ /*
+@@ -1477,7 +1536,8 @@ save_image (const gchar *filename,
+ * Convert unpacked pixels to packed if necessary
+ */
+
+- if (info->color_type == PNG_COLOR_TYPE_PALETTE && info->bit_depth < 8)
++ if (color_type == PNG_COLOR_TYPE_PALETTE &&
++ bit_depth < 8)
+ png_set_packing (pp);
+
+ /*
+@@ -1507,7 +1567,9 @@ save_image (const gchar *filename,
+
+ gimp_pixel_rgn_get_rect (&pixel_rgn, pixel, 0, begin,
+ drawable->width, num);
+- /*if we are with a RGBA image and have to pre-multiply the alpha channel */
++
++ /* If we are with a RGBA image and have to pre-multiply the
++ alpha channel */
+ if (bpp == 4 && ! pngvals.save_transp_pixels)
+ {
+ for (i = 0; i < num; ++i)
+@@ -1529,7 +1591,7 @@ save_image (const gchar *filename,
+
+ /* If we're dealing with a paletted image with
+ * transparency set, write out the remapped palette */
+- if (info->valid & PNG_INFO_tRNS)
++ if (png_get_valid (pp, info, PNG_INFO_tRNS))
+ {
+ guchar inverse_remap[256];
+
+@@ -1547,9 +1609,11 @@ save_image (const gchar *filename,
+ }
+ }
+ }
++
+ /* Otherwise if we have a paletted image and transparency
+ * couldn't be set, we ignore the alpha channel */
+- else if (info->valid & PNG_INFO_PLTE && bpp == 2)
++ else if (png_get_valid (pp, info, PNG_INFO_PLTE) &&
++ bpp == 2)
+ {
+ for (i = 0; i < num; ++i)
+ {
+@@ -1564,7 +1628,7 @@ save_image (const gchar *filename,
+ png_write_rows (pp, pixels, num);
+
+ gimp_progress_update (((double) pass + (double) end /
+- (double) info->height) /
++ (double) drawable->height) /
+ (double) num_passes);
+ }
+ }
+@@ -1694,14 +1758,14 @@ find_unused_ia_color (GimpDrawable *drawable,
+ }
+
+
+-static void
++static int
+ respin_cmap (png_structp pp,
+ png_infop info,
+ guchar *remap,
+ gint32 image_ID,
+ GimpDrawable *drawable)
+ {
+- static const guchar trans[] = { 0 };
++ static guchar trans[] = { 0 };
+
+ gint colors;
+ guchar *before;
+@@ -1728,10 +1792,13 @@ respin_cmap (png_structp pp,
+ * index - do like gif2png and swap
+ * index 0 and index transparent */
+ {
+- png_color palette[256];
++ static png_color palette[256];
+ gint i;
+
+- png_set_tRNS (pp, info, (png_bytep) trans, 1, NULL);
++ /* Set tRNS chunk values for writing later. */
++ pngg.has_trns = TRUE;
++ pngg.trans = trans;
++ pngg.num_trans = 1;
+
+ /* Transform all pixels with a value = transparent to
+ * 0 and vice versa to compensate for re-ordering in palette
+@@ -1752,7 +1819,10 @@ respin_cmap (png_structp pp,
+ palette[i].blue = before[3 * remap[i] + 2];
+ }
+
+- png_set_PLTE (pp, info, palette, colors);
++ /* Set PLTE chunk values for writing later. */
++ pngg.has_plte = TRUE;
++ pngg.palette = palette;
++ pngg.num_palette = colors;
+ }
+ else
+ {
+@@ -1760,14 +1830,22 @@ respin_cmap (png_structp pp,
+ * transparency & just use the full palette */
+ g_message (_("Couldn't losslessly save transparency, "
+ "saving opacity instead."));
+- png_set_PLTE (pp, info, (png_colorp) before, colors);
++
++ /* Set PLTE chunk values for writing later. */
++ pngg.has_plte = TRUE;
++ pngg.palette = (png_colorp) before;
++ pngg.num_palette = colors;
+ }
+ }
+ else
+ {
+- png_set_PLTE (pp, info, (png_colorp) before, colors);
++ /* Set PLTE chunk values for writing later. */
++ pngg.has_plte = TRUE;
++ pngg.palette = (png_colorp) before;
++ pngg.num_palette = colors;
+ }
+
++ return get_bit_depth_for_palette (colors);
+ }
+
+ static gboolean
diff --git a/testing/gimp/linux.gpl b/testing/gimp/linux.gpl
new file mode 100644
index 000000000..0a73d8979
--- /dev/null
+++ b/testing/gimp/linux.gpl
@@ -0,0 +1,19 @@
+GIMP Palette
+Name: linux
+#
+ 0 0 0
+ 0 0 170
+ 0 170 0
+ 0 170 170
+170 0 0
+170 0 170
+170 85 0
+170 170 170
+ 85 85 85
+ 85 85 255
+ 85 255 85
+ 85 255 255
+255 85 85
+255 85 255
+255 255 85
+255 255 255
diff --git a/testing/gimp/uri-backend-libcurl.patch b/testing/gimp/uri-backend-libcurl.patch
new file mode 100644
index 000000000..85da2fc7f
--- /dev/null
+++ b/testing/gimp/uri-backend-libcurl.patch
@@ -0,0 +1,77 @@
+diff -aur gimp-2.6.11/plug-ins/file-uri/uri-backend-libcurl.c gimp-2.6.11.patched/plug-ins/file-uri/uri-backend-libcurl.c
+--- gimp-2.6.11/plug-ins/file-uri/uri-backend-libcurl.c 2010-07-03 00:51:59.000000000 +0200
++++ gimp-2.6.11.patched/plug-ins/file-uri/uri-backend-libcurl.c 2011-06-23 19:15:30.000000000 +0200
+@@ -4,9 +4,9 @@
+ * libcurl backend for the URI plug-in
+ * Copyright (C) 2006 Mukund Sivaraman <muks@mukund.org>
+ *
+- * This program is free software; you can redistribute it and/or modify
++ * 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 2 of the License, or
++ * 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,
+@@ -15,8 +15,7 @@
+ * 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, write to the Free Software
+- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+ #include "config.h"
+@@ -24,7 +23,6 @@
+ #include <errno.h>
+
+ #include <curl/curl.h>
+-#include <curl/types.h>
+ #include <curl/easy.h>
+
+ #include <glib/gstdio.h>
+@@ -63,7 +61,7 @@
+
+ vinfo = curl_version_info (CURLVERSION_NOW);
+
+- protocols = g_string_new ("http:,ftp:");
++ protocols = g_string_new ("http:,ftp:,gopher:");
+
+ if (vinfo->features & CURL_VERSION_SSL)
+ {
+@@ -153,7 +151,7 @@
+ FILE *out_file;
+ CURL *curl_handle;
+ CURLcode result;
+- gint response_code;
++ glong response_code;
+
+ gimp_progress_init (_("Connecting to server"));
+
+@@ -195,12 +193,12 @@
+
+ curl_easy_getinfo (curl_handle, CURLINFO_RESPONSE_CODE, &response_code);
+
+- if (response_code != 200)
++ if (response_code != 200 && response_code != 226 && response_code != 0)
+ {
+ fclose (out_file);
+ g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
+ _("Opening '%s' for reading resulted in HTTP "
+- "response code: %d"),
++ "response code: %ld"),
+ uri, response_code);
+ curl_easy_cleanup (curl_handle);
+ return FALSE;
+@@ -224,3 +222,10 @@
+
+ return FALSE;
+ }
++
++gchar *
++uri_backend_map_image (const gchar *uri,
++ GimpRunMode run_mode)
++{
++ return NULL;
++}