[gimp] Bug 757783 - When opening linear gamma pngs or tiffs...
- From: Michael Natterer <mitch src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] Bug 757783 - When opening linear gamma pngs or tiffs...
- Date: Mon, 23 Nov 2015 17:45:16 +0000 (UTC)
commit 3cc80b0a5c630c70b5989f45e68c3f4f4c925215
Author: Michael Natterer <mitch gimp org>
Date: Mon Nov 23 18:44:17 2015 +0100
Bug 757783 - When opening linear gamma pngs or tiffs...
...many operations give wrong results
Fix PNG loading to get the embedded profile first, and create a
linear RGB image if the profile says so.
plug-ins/common/file-png.c | 226 +++++++++++++++++++++++---------------------
1 files changed, 118 insertions(+), 108 deletions(-)
---
diff --git a/plug-ins/common/file-png.c b/plug-ins/common/file-png.c
index 4c825e3..55e7bb2 100644
--- a/plug-ins/common/file-png.c
+++ b/plug-ins/common/file-png.c
@@ -784,6 +784,34 @@ get_bit_depth_for_palette (int num_palette)
return 8;
}
+static GimpColorProfile *
+load_color_profile (png_structp pp,
+ png_infop info,
+ gchar **profile_name)
+{
+ GimpColorProfile *profile = NULL;
+
+#if defined(PNG_iCCP_SUPPORTED)
+ png_uint_32 proflen;
+ png_charp profname;
+ png_charp prof;
+ int profcomp;
+
+ if (png_get_iCCP (pp, info, &profname, &profcomp, &prof, &proflen))
+ {
+ profile = gimp_color_profile_new_from_icc_profile ((guint8 *) prof,
+ proflen, NULL);
+ if (profile && profname)
+ {
+ *profile_name = g_convert (profname, strlen (profname),
+ "ISO-8859-1", "UTF-8", NULL, NULL, NULL);
+ }
+ }
+#endif
+
+ return profile;
+}
+
/*
* 'load_image()' - Load a PNG image into a new image window.
*/
@@ -793,37 +821,37 @@ load_image (const gchar *filename,
gboolean *resolution_loaded,
GError **error)
{
- int i, /* Looping var */
- trns, /* Transparency present */
- bpp, /* Bytes per pixel */
- width, /* image width */
- height, /* image height */
- empty, /* Number of fully transparent indices */
- num_passes, /* Number of interlace passes in file */
- pass, /* Current pass in file */
- tile_height, /* Height of tile in GIMP */
- begin, /* Beginning tile row */
- end, /* Ending tile row */
- num; /* Number of rows to load */
- GimpImageBaseType image_type; /* Type of image */
- GimpPrecision image_precision;/* Precision of image */
- GimpImageType layer_type; /* Type of drawable/layer */
- FILE *fp; /* File pointer */
- volatile gint32 image = -1; /* Image -- preserved against setjmp() */
- gint32 layer; /* Layer */
- GeglBuffer *buffer; /* GEGL buffer for layer */
- const Babl *file_format; /* BABL format for layer */
- png_structp pp; /* PNG read pointer */
- png_infop info; /* PNG info pointers */
- guchar **pixels, /* Pixel rows */
- *pixel; /* Pixel data */
- guchar alpha[256], /* Index -> Alpha */
- *alpha_ptr; /* Temporary pointer */
- struct read_error_data
- error_data;
-
- png_textp text;
- gint num_texts;
+ gint i; /* Looping var */
+ gint trns; /* Transparency present */
+ gint bpp; /* Bytes per pixel */
+ gint width; /* image width */
+ gint height; /* image height */
+ gint empty; /* Number of fully transparent indices */
+ gint num_passes; /* Number of interlace passes in file */
+ gint pass; /* Current pass in file */
+ gint tile_height; /* Height of tile in GIMP */
+ gint begin; /* Beginning tile row */
+ gint end; /* Ending tile row */
+ gint num; /* Number of rows to load */
+ GimpImageBaseType image_type; /* Type of image */
+ GimpPrecision image_precision; /* Precision of image */
+ GimpImageType layer_type; /* Type of drawable/layer */
+ GimpColorProfile *profile = NULL; /* Color profile */
+ gchar *profile_name = NULL; /* Profile's name */
+ gboolean linear = FALSE; /* Linear RGB */
+ FILE *fp; /* File pointer */
+ volatile gint32 image = -1; /* Image -- protected for setjmp() */
+ gint32 layer; /* Layer */
+ GeglBuffer *buffer; /* GEGL buffer for layer */
+ const Babl *file_format; /* BABL format for layer */
+ png_structp pp; /* PNG read pointer */
+ png_infop info; /* PNG info pointers */
+ guchar **pixels; /* Pixel rows */
+ guchar *pixel; /* Pixel data */
+ guchar alpha[256]; /* Index -> Alpha */
+ png_textp text;
+ gint num_texts;
+ struct read_error_data error_data;
pp = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!pp)
@@ -873,22 +901,41 @@ load_image (const gchar *filename,
png_set_compression_buffer_size (pp, 512);
/*
- * Get the image dimensions and create the image...
+ * Get the image info
*/
png_read_info (pp, info);
+ if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
+ png_set_swap (pp);
+
/*
- * Latest attempt, this should be my best yet :)
+ * Get the iCCP (color profile) chunk, if any, and figure if it's
+ * a linear RGB profile
+ */
+ profile = load_color_profile (pp, info, &profile_name);
+
+ if (profile)
+ linear = gimp_color_profile_is_linear (profile);
+
+ /*
+ * Get image precision and color model
*/
if (png_get_bit_depth (pp, info) == 16)
- image_precision = GIMP_PRECISION_U16_GAMMA;
+ {
+ if (linear)
+ image_precision = GIMP_PRECISION_U16_LINEAR;
+ else
+ image_precision = GIMP_PRECISION_U16_GAMMA;
+ }
else
- image_precision = GIMP_PRECISION_U8_GAMMA;
-
- if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
- png_set_swap (pp);
+ {
+ if (linear)
+ image_precision = GIMP_PRECISION_U8_LINEAR;
+ else
+ image_precision = GIMP_PRECISION_U8_GAMMA;
+ }
if (png_get_bit_depth (pp, info) < 8)
{
@@ -921,13 +968,18 @@ load_image (const gchar *filename,
if (png_get_valid (pp, info, PNG_INFO_tRNS) &&
png_get_color_type (pp, info) == PNG_COLOR_TYPE_PALETTE)
{
+ guchar *alpha_ptr;
+
png_get_tRNS (pp, info, &alpha_ptr, &num, NULL);
+
/* Copy the existing alpha values from the tRNS chunk */
for (i = 0; i < num; ++i)
alpha[i] = alpha_ptr[i];
+
/* And set any others to fully opaque (255) */
for (i = num; i < 256; ++i)
alpha[i] = 255;
+
trns = 1;
}
else
@@ -941,53 +993,34 @@ load_image (const gchar *filename,
png_read_update_info (pp, info);
- file_format = NULL;
-
switch (png_get_color_type (pp, info))
{
- case PNG_COLOR_TYPE_RGB: /* RGB */
+ case PNG_COLOR_TYPE_RGB:
image_type = GIMP_RGB;
layer_type = GIMP_RGB_IMAGE;
- if (image_precision == GIMP_PRECISION_U8_GAMMA)
- file_format = babl_format ("R'G'B' u8");
- else
- file_format = babl_format ("R'G'B' u16");
break;
- case PNG_COLOR_TYPE_RGB_ALPHA: /* RGBA */
+ case PNG_COLOR_TYPE_RGB_ALPHA:
image_type = GIMP_RGB;
layer_type = GIMP_RGBA_IMAGE;
- if (image_precision == GIMP_PRECISION_U8_GAMMA)
- file_format = babl_format ("R'G'B'A u8");
- else
- file_format = babl_format ("R'G'B'A u16");
break;
- case PNG_COLOR_TYPE_GRAY: /* Grayscale */
+ case PNG_COLOR_TYPE_GRAY:
image_type = GIMP_GRAY;
layer_type = GIMP_GRAY_IMAGE;
- if (image_precision == GIMP_PRECISION_U8_GAMMA)
- file_format = babl_format ("Y' u8");
- else
- file_format = babl_format ("Y' u16");
break;
- case PNG_COLOR_TYPE_GRAY_ALPHA: /* Grayscale + alpha */
+ case PNG_COLOR_TYPE_GRAY_ALPHA:
image_type = GIMP_GRAY;
layer_type = GIMP_GRAYA_IMAGE;
- if (image_precision == GIMP_PRECISION_U8_GAMMA)
- file_format = babl_format ("Y'A u8");
- else
- file_format = babl_format ("Y'A u16");
break;
- case PNG_COLOR_TYPE_PALETTE: /* Indexed */
+ case PNG_COLOR_TYPE_PALETTE:
image_type = GIMP_INDEXED;
layer_type = GIMP_INDEXED_IMAGE;
- /* we can get the format only after creating the layer */
break;
- default: /* Aie! Unknown type */
+ default:
g_set_error (error, 0, 0,
_("Unknown color model in PNG file '%s'."),
gimp_filename_to_utf8 (filename));
@@ -1015,8 +1048,7 @@ load_image (const gchar *filename,
layer_type, 100, GIMP_NORMAL_MODE);
gimp_image_insert_layer (image, layer, -1, 0);
- if (layer_type == GIMP_INDEXED_IMAGE)
- file_format = gimp_drawable_get_format (layer);
+ file_format = gimp_drawable_get_format (layer);
/*
* Find out everything we can about the image resolution
@@ -1245,52 +1277,30 @@ load_image (const gchar *filename,
g_free (comment);
}
-#if defined(PNG_iCCP_SUPPORTED)
/*
- * Get the iCCP (color profile) chunk, if any, and attach it as
- * a parasite
+ * Attach the color profile, if any
*/
- {
- png_uint_32 proflen;
- png_charp profname;
- png_charp prof;
- int profcomp;
+ if (profile)
+ {
+ gimp_image_set_color_profile (image, profile);
+ g_object_unref (profile);
- if (png_get_iCCP (pp, info, &profname, &profcomp, &prof, &proflen))
- {
- GimpColorProfile *profile;
+ if (profile_name)
+ {
+ GimpParasite *parasite;
- profile = gimp_color_profile_new_from_icc_profile ((guint8 *) prof,
- proflen, NULL);
- if (profile)
- {
- gimp_image_set_color_profile (image, profile);
- g_object_unref (profile);
+ parasite = gimp_parasite_new ("icc-profile-name",
+ GIMP_PARASITE_PERSISTENT |
+ GIMP_PARASITE_UNDOABLE,
+ strlen (profile_name),
+ profile_name);
+ gimp_image_attach_parasite (image, parasite);
+ gimp_parasite_free (parasite);
- if (profname)
- {
- gchar *tmp = g_convert (profname, strlen (profname),
- "ISO-8859-1", "UTF-8", NULL, NULL, NULL);
-
- if (tmp)
- {
- GimpParasite *parasite;
-
- parasite = gimp_parasite_new ("icc-profile-name",
- GIMP_PARASITE_PERSISTENT |
- GIMP_PARASITE_UNDOABLE,
- strlen (tmp), tmp);
- gimp_image_attach_parasite (image, parasite);
- gimp_parasite_free (parasite);
-
- g_free (tmp);
- }
- }
- }
- }
- }
-#endif
+ g_free (profile_name);
+ }
+ }
/*
* Done with the file...
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]