[gimp] Bug 770853 - Opening and overwriting a linear gamma png produces wrong colors
- From: Michael Natterer <mitch src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] Bug 770853 - Opening and overwriting a linear gamma png produces wrong colors
- Date: Sun, 4 Sep 2016 23:04:45 +0000 (UTC)
commit e404e6ba93ca70183d9f063b5eb2d1543c956e9b
Author: Michael Natterer <mitch gimp org>
Date: Sun Sep 4 22:12:30 2016 +0200
Bug 770853 - Opening and overwriting a linear gamma png produces wrong colors
Add support for writing linear PNGs. But only if we also save a color
profile, otherwise we would get loaders confused. Please test, I might
have a knot in my brain...
Also clean up some formatting and fix compile warnings, now let's wait
for bugs about shit libpng versions which break the build.
plug-ins/common/file-png.c | 232 ++++++++++++++++++++++++++++----------------
1 files changed, 150 insertions(+), 82 deletions(-)
---
diff --git a/plug-ins/common/file-png.c b/plug-ins/common/file-png.c
index 70d6eaa..fd04a7f 100644
--- a/plug-ins/common/file-png.c
+++ b/plug-ins/common/file-png.c
@@ -794,7 +794,7 @@ load_color_profile (png_structp pp,
#if defined(PNG_iCCP_SUPPORTED)
png_uint_32 proflen;
png_charp profname;
- png_charp prof;
+ png_bytep prof;
int profcomp;
if (png_get_iCCP (pp, info, &profname, &profcomp, &prof, &proflen))
@@ -1426,49 +1426,83 @@ save_image (const gchar *filename,
gint32 orig_image_ID,
GError **error)
{
- gint i, k, /* Looping vars */
- bpp = 0, /* Bytes per pixel */
- type, /* Type of drawable/layer */
- num_passes, /* Number of interlace passes in file */
- pass, /* Current pass in file */
- tile_height, /* Height of tile in GIMP */
- width, /* image width */
- height, /* image height */
- begin, /* Beginning tile row */
- end, /* Ending tile row */
- num; /* Number of rows to load */
- FILE *fp; /* File pointer */
- GeglBuffer *buffer; /* GEGL buffer for layer */
- const Babl *file_format; /* BABL format of file */
- png_structp pp; /* PNG read pointer */
- png_infop info; /* PNG info pointer */
- gint offx, offy; /* Drawable offsets from origin */
- guchar **pixels, /* Pixel rows */
- *fixed, /* Fixed-up pixel data */
- *pixel; /* Pixel data */
- gdouble xres, yres; /* GIMP resolution (dpi) */
- png_color_16 background; /* Background color */
- png_time mod_time; /* Modification time (ie NOW) */
- 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 (gimp_image_get_precision (image_ID) == GIMP_PRECISION_U8_GAMMA)
- bit_depth = 8;
- else
- bit_depth = 16;
+ gint i, k; /* Looping vars */
+ gint bpp = 0; /* Bytes per pixel */
+ gint type; /* Type of drawable/layer */
+ gint num_passes; /* Number of interlace passes in file */
+ gint pass; /* Current pass in file */
+ gint tile_height; /* Height of tile in GIMP */
+ gint width; /* image width */
+ gint height; /* image height */
+ gint begin; /* Beginning tile row */
+ gint end; /* Ending tile row */
+ gint num; /* Number of rows to load */
+ FILE *fp; /* File pointer */
+ GimpColorProfile *profile = NULL; /* Color profile */
+ gboolean linear; /* Save linear RGB */
+ GeglBuffer *buffer; /* GEGL buffer for layer */
+ const Babl *file_format; /* BABL format of file */
+ png_structp pp; /* PNG read pointer */
+ png_infop info; /* PNG info pointer */
+ gint offx, offy; /* Drawable offsets from origin */
+ guchar **pixels; /* Pixel rows */
+ guchar *fixed; /* Fixed-up pixel data */
+ guchar *pixel; /* Pixel data */
+ gdouble xres, yres; /* GIMP resolution (dpi) */
+ png_color_16 background; /* Background color */
+ png_time mod_time; /* Modification time (ie NOW) */
+ time_t cutime; /* Time since epoch */
+ struct tm *gmt; /* GMT broken down */
+ gint color_type; /* PNG color type */
+ gint bit_depth = 16; /* Default to bit bepth 16 */
+
+ guchar remap[256]; /* Re-mapping for the palette */
+
+ png_textp text = NULL;
+
+#if defined(PNG_iCCP_SUPPORTED)
+ profile = gimp_image_get_color_profile (orig_image_ID);
+#endif
+
+ switch (gimp_image_get_precision (image_ID))
+ {
+ case GIMP_PRECISION_U8_LINEAR:
+ /* only keep 8 bit linear RGB if we also save a profile */
+ if (profile)
+ bit_depth = 8;
+
+ case GIMP_PRECISION_U16_LINEAR:
+ case GIMP_PRECISION_U32_LINEAR:
+ case GIMP_PRECISION_HALF_LINEAR:
+ case GIMP_PRECISION_FLOAT_LINEAR:
+ case GIMP_PRECISION_DOUBLE_LINEAR:
+ /* save linear RGB only if we save a profile, or a loader won't
+ * do the right thing
+ */
+ if (profile)
+ linear = TRUE;
+ else
+ linear = FALSE;
+ break;
+
+ case GIMP_PRECISION_U8_GAMMA:
+ bit_depth = 8;
+
+ case GIMP_PRECISION_U16_GAMMA:
+ case GIMP_PRECISION_U32_GAMMA:
+ case GIMP_PRECISION_HALF_GAMMA:
+ case GIMP_PRECISION_FLOAT_GAMMA:
+ case GIMP_PRECISION_DOUBLE_GAMMA:
+ linear = FALSE;
+ break;
+ }
pp = png_create_write_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. */
-
+ * versions do not match.
+ */
g_set_error (error, 0, 0,
_("Error creating PNG write struct while exporting '%s'."),
gimp_filename_to_utf8 (filename));
@@ -1513,9 +1547,9 @@ save_image (const gchar *filename,
*/
buffer = gimp_drawable_get_buffer (drawable_ID);
- width = gegl_buffer_get_width (buffer);
+ width = gegl_buffer_get_width (buffer);
height = gegl_buffer_get_height (buffer);
- type = gimp_drawable_type (drawable_ID);
+ type = gimp_drawable_type (drawable_ID);
/*
* Initialise remap[]
@@ -1532,33 +1566,73 @@ save_image (const gchar *filename,
case GIMP_RGB_IMAGE:
color_type = PNG_COLOR_TYPE_RGB;
if (bit_depth == 8)
- file_format = babl_format ("R'G'B' u8");
+ {
+ if (linear)
+ file_format = babl_format ("RGB u8");
+ else
+ file_format = babl_format ("R'G'B' u8");
+ }
else
- file_format = babl_format ("R'G'B' u16");
+ {
+ if (linear)
+ file_format = babl_format ("RGB u16");
+ else
+ file_format = babl_format ("R'G'B' u16");
+ }
break;
case GIMP_RGBA_IMAGE:
color_type = PNG_COLOR_TYPE_RGB_ALPHA;
if (bit_depth == 8)
- file_format = babl_format ("R'G'B'A u8");
+ {
+ if (linear)
+ file_format = babl_format ("RGBA u8");
+ else
+ file_format = babl_format ("R'G'B'A u8");
+ }
else
- file_format = babl_format ("R'G'B'A u16");
+ {
+ if (linear)
+ file_format = babl_format ("RGBA u16");
+ else
+ file_format = babl_format ("R'G'B'A u16");
+ }
break;
case GIMP_GRAY_IMAGE:
color_type = PNG_COLOR_TYPE_GRAY;
if (bit_depth == 8)
- file_format = babl_format ("Y' u8");
+ {
+ if (linear)
+ file_format = babl_format ("Y u8");
+ else
+ file_format = babl_format ("Y' u8");
+ }
else
- file_format = babl_format ("Y' u16");
+ {
+ if (linear)
+ file_format = babl_format ("Y u16");
+ else
+ file_format = babl_format ("Y' u16");
+ }
break;
case GIMP_GRAYA_IMAGE:
color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
if (bit_depth == 8)
- file_format = babl_format ("Y'A u8");
+ {
+ if (linear)
+ file_format = babl_format ("YA u8");
+ else
+ file_format = babl_format ("Y'A u8");
+ }
else
- file_format = babl_format ("Y'A u16");
+ {
+ if (linear)
+ file_format = babl_format ("YA u16");
+ else
+ file_format = babl_format ("Y'A u16");
+ }
break;
case GIMP_INDEXED_IMAGE:
@@ -1664,39 +1738,33 @@ save_image (const gchar *filename,
}
#if defined(PNG_iCCP_SUPPORTED)
- {
- GimpColorProfile *profile;
-
- profile = gimp_image_get_color_profile (orig_image_ID);
-
- if (profile)
- {
- GimpParasite *parasite;
- gchar *profile_name = NULL;
- const guint8 *icc_data;
- gsize icc_length;
-
- icc_data = gimp_color_profile_get_icc_profile (profile, &icc_length);
-
- parasite = gimp_image_get_parasite (orig_image_ID,
- "icc-profile-name");
- if (parasite)
- profile_name = g_convert (gimp_parasite_data (parasite),
- gimp_parasite_data_size (parasite),
- "UTF-8", "ISO-8859-1", NULL, NULL, NULL);
-
- png_set_iCCP (pp,
- info,
- profile_name ? profile_name : "ICC profile",
- 0,
- (png_charp) icc_data,
- icc_length);
-
- g_free (profile_name);
-
- g_object_unref (profile);
- }
- }
+ if (profile)
+ {
+ GimpParasite *parasite;
+ gchar *profile_name = NULL;
+ const guint8 *icc_data;
+ gsize icc_length;
+
+ icc_data = gimp_color_profile_get_icc_profile (profile, &icc_length);
+
+ parasite = gimp_image_get_parasite (orig_image_ID,
+ "icc-profile-name");
+ if (parasite)
+ profile_name = g_convert (gimp_parasite_data (parasite),
+ gimp_parasite_data_size (parasite),
+ "UTF-8", "ISO-8859-1", NULL, NULL, NULL);
+
+ png_set_iCCP (pp,
+ info,
+ profile_name ? profile_name : "ICC profile",
+ 0,
+ icc_data,
+ icc_length);
+
+ g_free (profile_name);
+
+ g_object_unref (profile);
+ }
#endif
#ifdef PNG_zTXt_SUPPORTED
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]