Commit e404e6ba authored by Michael Natterer's avatar Michael Natterer 😴
Browse files

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.
parent 8bff597c
......@@ -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
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment