[libpng16] Corrected simplified API default gamma for color-mapped output, added

a flag to change default. In 1.6.0 when the simplified API was used
to produce color-mapped output from an input image with no gamma
information the gamma assumed for the input could be different from
that assumed for non-color-mapped output.  In particular 16-bit depth
input files were assumed to be sRGB encoded, whereas in the 'direct'
case they were assumed to have linear data.  This was an error.  The
fix makes the simplified API treat all input files the same way and
adds a new flag to the png_image::flags member to allow the
application/user to specify that 16-bit files contain sRGB data
rather than the default linear.
Fixed bugs in the pngpixel and makepng test programs.
This commit is contained in:
John Bowler 2013-03-06 22:15:25 -06:00 committed by Glenn Randers-Pehrson
parent 1f24cb74f2
commit 59ae38984f
7 changed files with 90 additions and 14 deletions

View File

@ -1,5 +1,5 @@
Libpng 1.6.1beta07 - March 4, 2013 Libpng 1.6.1beta07 - March 7, 2013
This is not intended to be a public release. It will be replaced This is not intended to be a public release. It will be replaced
within a few weeks by a public version or by another test version. within a few weeks by a public version or by another test version.
@ -79,7 +79,19 @@ Version 1.6.1beta06 [March 4, 2013]
settings to depend on options and options can now set (or override) the settings to depend on options and options can now set (or override) the
defaults for settings. defaults for settings.
Version 1.6.1beta07 [March 4, 2013] Version 1.6.1beta07 [March 7, 2013]
Corrected simplified API default gamma for color-mapped output, added
a flag to change default. In 1.6.0 when the simplified API was used
to produce color-mapped output from an input image with no gamma
information the gamma assumed for the input could be different from
that assumed for non-color-mapped output. In particular 16-bit depth
input files were assumed to be sRGB encoded, whereas in the 'direct'
case they were assumed to have linear data. This was an error. The
fix makes the simplified API treat all input files the same way and
adds a new flag to the png_image::flags member to allow the
application/user to specify that 16-bit files contain sRGB data
rather than the default linear.
Fixed bugs in the pngpixel and makepng test programs.
Send comments/corrections/commendations to png-mng-implement at lists.sf.net Send comments/corrections/commendations to png-mng-implement at lists.sf.net
(subscription required; visit (subscription required; visit

14
CHANGES
View File

@ -4435,7 +4435,19 @@ Version 1.6.1beta06 [March 4, 2013]
settings to depend on options and options can now set (or override) the settings to depend on options and options can now set (or override) the
defaults for settings. defaults for settings.
Version 1.6.1beta07 [March 4, 2013] Version 1.6.1beta07 [March 7, 2013]
Corrected simplified API default gamma for color-mapped output, added
a flag to change default. In 1.6.0 when the simplified API was used
to produce color-mapped output from an input image with no gamma
information the gamma assumed for the input could be different from
that assumed for non-color-mapped output. In particular 16-bit depth
input files were assumed to be sRGB encoded, whereas in the 'direct'
case they were assumed to have linear data. This was an error. The
fix makes the simplified API treat all input files the same way and
adds a new flag to the png_image::flags member to allow the
application/user to specify that 16-bit files contain sRGB data
rather than the default linear.
Fixed bugs in the pngpixel and makepng test programs.
Send comments/corrections/commendations to png-mng-implement at lists.sf.net Send comments/corrections/commendations to png-mng-implement at lists.sf.net
(subscription required; visit (subscription required; visit

View File

@ -37,7 +37,7 @@ component(png_const_bytep row, png_uint_32 x, unsigned int c,
* bytes wide. Since the row fitted into memory, however, the following must * bytes wide. Since the row fitted into memory, however, the following must
* work: * work:
*/ */
png_uint_32 bit_offset_hi = bit_depth * ((x >> 6) * channels + c); png_uint_32 bit_offset_hi = bit_depth * ((x >> 6) * channels);
png_uint_32 bit_offset_lo = bit_depth * ((x & 0x3f) * channels + c); png_uint_32 bit_offset_lo = bit_depth * ((x & 0x3f) * channels + c);
row = (png_const_bytep)(((PNG_CONST png_byte (*)[8])row) + bit_offset_hi); row = (png_const_bytep)(((PNG_CONST png_byte (*)[8])row) + bit_offset_hi);

View File

@ -440,7 +440,7 @@ generate_row(png_bytep row, size_t rowbytes, unsigned int y, int color_type,
/* Palette with fixed color: the image rows are all 0 and the image width /* Palette with fixed color: the image rows are all 0 and the image width
* is 16. * is 16.
*/ */
memset(row, rowbytes, 0); memset(row, 0, rowbytes);
} }
else if (colors[0] == channels_of_type(color_type)) else if (colors[0] == channels_of_type(color_type))
@ -624,8 +624,8 @@ write_png(const char **name, FILE *fp, int color_type, int bit_depth,
gamma_table[0] = 0; gamma_table[0] = 0;
for (i=0; i<255; ++i) for (i=1; i<255; ++i)
gamma_table[i] = (png_byte)floor(pow(i/255.,conv) * 255 + 127.5); gamma_table[i] = (png_byte)floor(pow(i/255.,conv) * 255 + .5);
gamma_table[255] = 255; gamma_table[255] = 255;
} }

View File

@ -315,6 +315,7 @@ compare_16bit(int v1, int v2, int error_limit, int multiple_algorithms)
#define KEEP_GOING 32 #define KEEP_GOING 32
#define ACCUMULATE 64 #define ACCUMULATE 64
#define FAST_WRITE 128 #define FAST_WRITE 128
#define sRGB_16BIT 256
static void static void
print_opts(png_uint_32 opts) print_opts(png_uint_32 opts)
@ -335,6 +336,8 @@ print_opts(png_uint_32 opts)
printf(" --accumulate"); printf(" --accumulate");
if (!(opts & FAST_WRITE)) /* --fast is currently the default */ if (!(opts & FAST_WRITE)) /* --fast is currently the default */
printf(" --slow"); printf(" --slow");
if (opts & sRGB_16BIT)
printf(" --sRGB-16bit");
} }
#define FORMAT_NO_CHANGE 0x80000000 /* additional flag */ #define FORMAT_NO_CHANGE 0x80000000 /* additional flag */
@ -3026,6 +3029,10 @@ read_file(Image *image, png_uint_32 format, png_const_colorp background)
return logerror(image, "file init: ", image->file_name, ""); return logerror(image, "file init: ", image->file_name, "");
} }
/* This must be set after the begin_read call: */
if (image->opts & sRGB_16BIT)
image->image.flags |= PNG_IMAGE_FLAG_16BIT_sRGB;
/* Have an initialized image with all the data we need plus, maybe, an /* Have an initialized image with all the data we need plus, maybe, an
* allocated file (myfile) or buffer (mybuffer) that need to be freed. * allocated file (myfile) or buffer (mybuffer) that need to be freed.
*/ */
@ -3488,6 +3495,10 @@ main(int argc, char **argv)
opts &= ~KEEP_GOING; opts &= ~KEEP_GOING;
else if (strcmp(arg, "--strict") == 0) else if (strcmp(arg, "--strict") == 0)
opts |= STRICT; opts |= STRICT;
else if (strcmp(arg, "--sRGB-16bit") == 0)
opts |= sRGB_16BIT;
else if (strcmp(arg, "--linear-16bit") == 0)
opts &= ~sRGB_16BIT;
else if (strcmp(arg, "--tmpfile") == 0) else if (strcmp(arg, "--tmpfile") == 0)
{ {
if (c+1 < argc) if (c+1 < argc)

30
png.h
View File

@ -1,7 +1,7 @@
/* png.h - header file for PNG reference library /* png.h - header file for PNG reference library
* *
* libpng version 1.6.1beta07 - March 4, 2013 * libpng version 1.6.1beta07 - March 7, 2013
* Copyright (c) 1998-2013 Glenn Randers-Pehrson * Copyright (c) 1998-2013 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
@ -11,7 +11,7 @@
* Authors and maintainers: * Authors and maintainers:
* libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat * libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat
* libpng versions 0.89c, June 1996, through 0.96, May 1997: Andreas Dilger * libpng versions 0.89c, June 1996, through 0.96, May 1997: Andreas Dilger
* libpng versions 0.97, January 1998, through 1.6.1beta07 - March 4, 2013: Glenn * libpng versions 0.97, January 1998, through 1.6.1beta07 - March 7, 2013: Glenn
* See also "Contributing Authors", below. * See also "Contributing Authors", below.
* *
* Note about libpng version numbers: * Note about libpng version numbers:
@ -201,7 +201,7 @@
* *
* This code is released under the libpng license. * This code is released under the libpng license.
* *
* libpng versions 1.2.6, August 15, 2004, through 1.6.1beta07, March 4, 2013, are * libpng versions 1.2.6, August 15, 2004, through 1.6.1beta07, March 7, 2013, are
* Copyright (c) 2004, 2006-2013 Glenn Randers-Pehrson, and are * Copyright (c) 2004, 2006-2013 Glenn Randers-Pehrson, and are
* distributed according to the same disclaimer and license as libpng-1.2.5 * distributed according to the same disclaimer and license as libpng-1.2.5
* with the following individual added to the list of Contributing Authors: * with the following individual added to the list of Contributing Authors:
@ -313,7 +313,7 @@
* Y2K compliance in libpng: * Y2K compliance in libpng:
* ========================= * =========================
* *
* March 4, 2013 * March 7, 2013
* *
* Since the PNG Development group is an ad-hoc body, we can't make * Since the PNG Development group is an ad-hoc body, we can't make
* an official declaration. * an official declaration.
@ -381,7 +381,7 @@
/* Version information for png.h - this should match the version in png.c */ /* Version information for png.h - this should match the version in png.c */
#define PNG_LIBPNG_VER_STRING "1.6.1beta07" #define PNG_LIBPNG_VER_STRING "1.6.1beta07"
#define PNG_HEADER_VERSION_STRING \ #define PNG_HEADER_VERSION_STRING \
" libpng version 1.6.1beta07 - March 4, 2013\n" " libpng version 1.6.1beta07 - March 7, 2013\n"
#define PNG_LIBPNG_VER_SONUM 16 #define PNG_LIBPNG_VER_SONUM 16
#define PNG_LIBPNG_VER_DLLNUM 16 #define PNG_LIBPNG_VER_DLLNUM 16
@ -3098,6 +3098,24 @@ typedef struct
* slight speed gain. * slight speed gain.
*/ */
#define PNG_IMAGE_FLAG_16BIT_sRGB 0x04
/* On read if the image is a 16-bit per component image and there is no gAMA
* or sRGB chunk assume that the components are sRGB encoded. Notice that
* images output by the simplified API always have gamma information; setting
* this flag only affects the interpretation of 16-bit images from an
* external source. It is recommended that the application expose this flag
* to the user; the user can normally easily recognize the difference between
* linear and sRGB encoding. This flag has no effect on write - the data
* passed to the write APIs must have the correct encoding (as defined
* above.)
*
* If the flag is not set (the default) input 16-bit per component data is
* assumed to be linear.
*
* NOTE: the flag can only be set after the png_image_begin_read_ call,
* because that call initializes the 'flags' field.
*/
#ifdef PNG_SIMPLIFIED_READ_SUPPORTED #ifdef PNG_SIMPLIFIED_READ_SUPPORTED
/* READ APIs /* READ APIs
* --------- * ---------
@ -3148,7 +3166,7 @@ PNG_EXPORT(237, int, png_image_finish_read, (png_imagep image,
* PNG_FORMAT_FLAG_LINEAR *not* set. * PNG_FORMAT_FLAG_LINEAR *not* set.
* *
* For linear output removing the alpha channel is always done by compositing * For linear output removing the alpha channel is always done by compositing
* on black and background is ignored.: * on black and background is ignored.
* *
* colormap must be supplied when PNG_FORMAT_FLAG_COLORMAP is set. It must * colormap must be supplied when PNG_FORMAT_FLAG_COLORMAP is set. It must
* be at least the size (in bytes) returned by PNG_IMAGE_COLORMAP_SIZE. * be at least the size (in bytes) returned by PNG_IMAGE_COLORMAP_SIZE.

View File

@ -2004,6 +2004,28 @@ png_image_read_colormap(png_voidp argument)
else else
back_b = back_r = back_g = 255; back_b = back_r = back_g = 255;
/* Default the input file gamma if required - this is necessary because
* libpng assumes that if no gamma information is present the data is in the
* output format, but the simplified API deduces the gamma from the input
* format.
*/
if ((png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) == 0)
{
/* Do this directly, not using the png_colorspace functions, to ensure
* that it happens even if the colorspace is invalid (though probably if
* it is the setting will be ignored) Note that the same thing can be
* achieved at the application interface with png_set_gAMA.
*/
if (png_ptr->bit_depth == 16 &&
(image->flags & PNG_IMAGE_FLAG_16BIT_sRGB) == 0)
png_ptr->colorspace.gamma = PNG_GAMMA_LINEAR;
else
png_ptr->colorspace.gamma = PNG_GAMMA_sRGB_INVERSE;
png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
}
/* Decide what to do based on the PNG color type of the input data. The /* Decide what to do based on the PNG color type of the input data. The
* utility function png_create_colormap_entry deals with most aspects of the * utility function png_create_colormap_entry deals with most aspects of the
* output transformations; this code works out how to produce bytes of * output transformations; this code works out how to produce bytes of
@ -3547,7 +3569,8 @@ png_image_read_direct(png_voidp argument)
{ {
png_fixed_point input_gamma_default; png_fixed_point input_gamma_default;
if (base_format & PNG_FORMAT_FLAG_LINEAR) if ((base_format & PNG_FORMAT_FLAG_LINEAR) &&
(image->flags & PNG_IMAGE_FLAG_16BIT_sRGB) == 0)
input_gamma_default = PNG_GAMMA_LINEAR; input_gamma_default = PNG_GAMMA_LINEAR;
else else
input_gamma_default = PNG_DEFAULT_sRGB; input_gamma_default = PNG_DEFAULT_sRGB;