gimp/gimp-2.6.11-libpng.patch
2011-11-17 16:38:32 +01:00

1143 lines
37 KiB
Diff

From 0b404f55ca2e8b6ad3967146dbe78c88302cb1bf Mon Sep 17 00:00:00 2001
From: Nils Philippsen <nils@redhat.com>
Date: Thu, 17 Nov 2011 15:55:46 +0100
Subject: [PATCH] patch: libpng
Squashed commit of the following:
commit 4ffa25b23f392b3b05ba8d6a2eb51e81697527b6
Author: Mukund Sivaraman <muks@banu.com>
Date: Tue Oct 11 10:22:24 2011 +0530
file-png: Remove redundant assignment
(cherry picked from commit f40453be3c90b6e9157c5b6f25c278948e5f90b4)
commit 2d3ffbe665de920819a8c4dd926f066950274a2e
Author: Mukund Sivaraman <muks@banu.com>
Date: Tue Oct 11 10:22:00 2011 +0530
file-png: Move comment to correct function
(cherry picked from commit e0298effdf758f5beb9c01dfe161d33448f4130c)
commit 5d0e8a0d51cc3067e9e365425dcecef59234369f
Author: Mukund Sivaraman <muks@banu.com>
Date: Tue Sep 27 19:22:50 2011 +0530
file-png: Add comments about the struct checks
(cherry picked from commit 5769acd3db0c726914c2a399e59b71eb4d8a9d7d)
commit 1ef55c0057ecf4ac8cd20ef940d819dce7c6810f
Author: Mukund Sivaraman <muks@banu.com>
Date: Wed Sep 21 17:16:54 2011 +0530
file-png: Return correct type of error value
(cherry picked from commit ff2b9ee727586b431e17f283825be3444b5ef496)
commit 45f1586ff0159e450111264962b082d71595d320
Author: Mukund Sivaraman <muks@banu.com>
Date: Wed Sep 21 17:08:53 2011 +0530
file-png: Check that PNG structs are created properly
If there's a version mismatch between compiled version (header) and
installed shared libpng library, structs are not created and NULL is
returned.
(cherry picked from commit 1ac6c7b85c461b29fc84c9ed5446e7ae98102e00)
commit 38b07f3759478536c3e0570ab570ebdf43e4f9b7
Author: Mukund Sivaraman <muks@banu.com>
Date: Fri May 6 17:51:09 2011 +0530
file-png: Indent some code
(cherry picked from commit 5b999ab3f9c5e1bb5937111bb1d2fb4222381b98)
commit 3a6c9bf27d91d42bcd97e508758c622cbb960277
Author: Mukund Sivaraman <muks@banu.com>
Date: Thu May 5 20:47:53 2011 +0530
file-png: Update comment for png_set_IHDR()
(cherry picked from commit ae654a7aaea25a1ae445b702f57792562e1d3763)
commit f463360d5e1235d98ff1b4a6eb4293d4062c8127
Author: Mukund Sivaraman <muks@banu.com>
Date: Thu May 5 20:36:45 2011 +0530
file-png: Call png_set_*() functions after png_set_IHDR()
(cherry picked from commit fbbeb8d629eb78728396025432bb8be2078461fe)
commit 76a768f10ad9fa3f50ea55b772f55f76a50b78b0
Author: Mukund Sivaraman <muks@banu.com>
Date: Thu May 5 20:15:02 2011 +0530
file-png: Move setting the comment text after IHDR is set
(cherry picked from commit dbecc7b7053e0b8429eb00ab0a732d252c688381)
Conflicts:
plug-ins/common/file-png.c
commit 41b09a75861a7bf401a373ffe2d9e0f9769e81c9
Author: Mukund Sivaraman <muks@banu.com>
Date: Thu May 5 18:53:11 2011 +0530
file-png: Specify the interlace type explicitly
(cherry picked from commit 4fa2bbabf9959dc8bebc45fe263e737198c30e99)
commit 3d74018f4c1ade9b8f9a06ef8751af940985e476
Author: Mukund Sivaraman <muks@banu.com>
Date: Tue Apr 26 15:18:27 2011 +0530
file-png: Get num_colors properly before passing it on
(cherry picked from commit 5b5d88a2f1d9f0e37d07b24148f76a14d0f2789b)
commit 3bed4f1a982a3b204adda568b82d2aedaadc3324
Author: Mukund Sivaraman <muks@banu.com>
Date: Tue Apr 26 08:06:27 2011 +0530
file-png: Don't access inside PNG structs directly (contd.)
(cherry picked from commit 92684a25e95ce3da7954140b6f88f2cbfe3cd62d)
commit e55ab29c628e32d849211be90d1520d7cd5bbd65
Author: Mukund Sivaraman <muks@banu.com>
Date: Mon Apr 25 20:12:54 2011 +0530
file-png: Conditionally declare text_length
(cherry picked from commit a1c7606d51541ba0a99f556de90d3f79d1a2ca00)
commit 4862b920e0b7df479f42cc4b4c056cc63d4300a1
Author: Mukund Sivaraman <muks@banu.com>
Date: Mon Apr 25 20:09:15 2011 +0530
file-png: Don't access inside PNG structs directly
(cherry picked from commit f610aa4375213d556bc6881ce00fecbb67d50aec)
commit a97f84e1d5c4ac07802a0cde73bf8a61b85a2bb8
Author: Mukund Sivaraman <muks@banu.com>
Date: Fri May 6 19:33:20 2011 +0530
file-mng: Indent some code
(cherry picked from commit 904d3452b9087bcdc6366cf98b4b2d04b1fc6a37)
commit d0aeaa0dae65cb3b505ab48bac7b0f48d8a650e8
Author: Mukund Sivaraman <muks@banu.com>
Date: Fri May 6 16:28:25 2011 +0530
file-mng: Call png_set_*() functions after png_set_IHDR()
(cherry picked from commit 17c5e114c3df3aeabe5316f7a85da67f21f65961)
commit b401448ab1817fcc6e536e4b0f4a5492c8469312
Author: Mukund Sivaraman <muks@banu.com>
Date: Fri May 6 16:17:56 2011 +0530
file-mng: Specify the interlace type explicitly
(cherry picked from commit cbc2ffc7c2cd2103c81064d56b135fd66987422c)
commit 640d357c3e62238727d6e0612ed543ac82acb8f3
Author: Mukund Sivaraman <muks@banu.com>
Date: Tue Apr 26 15:19:43 2011 +0530
file-mng: Rename more variables
(cherry picked from commit 8868a044ea266618e06c984e5ac500db59f0c1cf)
commit 067140cf06c241dc7e57e8261072b4ca3715ee4b
Author: Mukund Sivaraman <muks@banu.com>
Date: Tue Apr 26 15:18:45 2011 +0530
file-mng: Don't access inside PNG structs directly
(cherry picked from commit c6a60d79c451f9f13825443fc1836f2fbd492c51)
commit e6927634b249ff9c8da1f6ce541a2a663b6d637b
Author: Mukund Sivaraman <muks@banu.com>
Date: Tue Apr 26 15:00:07 2011 +0530
file-mng: Rename variables
(cherry picked from commit 838ba0b78e6c2a1d60a00da52c89f6bc5ddd5385)
---
plug-ins/common/file-mng.c | 158 ++++++++++++++--------
plug-ins/common/file-png.c | 324 +++++++++++++++++++++++++++-----------------
2 files changed, 304 insertions(+), 178 deletions(-)
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
--
1.7.7.1