From f70c7d02e920aff3e58afa9fab15aecb31531b6b Mon Sep 17 00:00:00 2001 From: John Bowler Date: Tue, 10 May 2011 22:54:37 -0500 Subject: [PATCH] [devel] Added named value and 'flag' gamma support to png_set_gamma. Made a minor change from the previous (unreleased) ABI/API to hide the exact value used for Macs - it's not a good idea to embed this in the ABI! --- ANNOUNCE | 7 +++- CHANGES | 5 ++- png.h | 33 ++++++++++++----- pngpriv.h | 5 +++ pngrtran.c | 105 +++++++++++++++++++++++++++++++++++++---------------- pngset.c | 2 +- 6 files changed, 112 insertions(+), 45 deletions(-) diff --git a/ANNOUNCE b/ANNOUNCE index 666323245..23c6d6b68 100644 --- a/ANNOUNCE +++ b/ANNOUNCE @@ -1,5 +1,5 @@ -Libpng 1.5.3beta07 - May 9, 2011 +Libpng 1.5.3beta07 - May 11, 2011 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. @@ -101,8 +101,11 @@ Version 1.5.3beta06 [May 8, 2011] Removed the -D_ALL_SOURCE from definitions for AIX in CMakeLists.txt Implemented premultiplied alpha support: png_set_alpha_mode API -Version 1.5.3beta07 [May 9, 2011] +Version 1.5.3beta07 [May 11, 2011] Added expand_16 support to the high level interface. + Added named value and 'flag' gamma support to png_set_gamma. Made a minor + change from the previous (unreleased) ABI/API to hide the exact value used + for Macs - it's not a good idea to embed this in the ABI! Send comments/corrections/commendations to png-mng-implement at lists.sf.net: (subscription required; visit diff --git a/CHANGES b/CHANGES index d40d01a81..6ed3dd6ce 100644 --- a/CHANGES +++ b/CHANGES @@ -3360,8 +3360,11 @@ Version 1.5.3beta06 [May 8, 2011] Removed the -D_ALL_SOURCE from definitions for AIX in CMakeLists.txt Implemented premultiplied alpha support: png_set_alpha_mode API -Version 1.5.3beta07 [May 9, 2011] +Version 1.5.3beta07 [May 11, 2011] Added expand_16 support to the high level interface. + Added named value and 'flag' gamma support to png_set_gamma. Made a minor + change from the previous (unreleased) ABI/API to hide the exact value used + for Macs - it's not a good idea to embed this in the ABI! Send comments/corrections/commendations to png-mng-implement at lists.sf.net (subscription required; visit diff --git a/png.h b/png.h index fb188d799..19a9296c8 100644 --- a/png.h +++ b/png.h @@ -1,7 +1,7 @@ /* png.h - header file for PNG reference library * - * libpng version 1.5.3beta07 - May 9, 2011 + * libpng version 1.5.3beta07 - May 11, 2011 * Copyright (c) 1998-2011 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) @@ -11,7 +11,7 @@ * Authors and maintainers: * 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.97, January 1998, through 1.5.3beta07 - May 9, 2011: Glenn + * libpng versions 0.97, January 1998, through 1.5.3beta07 - May 11, 2011: Glenn * See also "Contributing Authors", below. * * Note about libpng version numbers: @@ -182,7 +182,7 @@ * * This code is released under the libpng license. * - * libpng versions 1.2.6, August 15, 2004, through 1.5.3beta07, May 9, 2011, are + * libpng versions 1.2.6, August 15, 2004, through 1.5.3beta07, May 11, 2011, are * Copyright (c) 2004, 2006-2011 Glenn Randers-Pehrson, and are * distributed according to the same disclaimer and license as libpng-1.2.5 * with the following individual added to the list of Contributing Authors: @@ -294,7 +294,7 @@ * Y2K compliance in libpng: * ========================= * - * May 9, 2011 + * May 11, 2011 * * Since the PNG Development group is an ad-hoc body, we can't make * an official declaration. @@ -357,7 +357,7 @@ /* Version information for png.h - this should match the version in png.c */ #define PNG_LIBPNG_VER_STRING "1.5.3beta07" #define PNG_HEADER_VERSION_STRING \ - " libpng version 1.5.3beta07 - May 9, 2011\n" + " libpng version 1.5.3beta07 - May 11, 2011\n" #define PNG_LIBPNG_VER_SONUM 15 #define PNG_LIBPNG_VER_DLLNUM 15 @@ -1176,7 +1176,9 @@ PNG_FP_EXPORT(227, void, png_set_alpha_mode, (png_structp png_ptr, int mode, double output_gamma)); PNG_FIXED_EXPORT(228, void, png_set_alpha_mode_fixed, (png_structp png_ptr, int mode, png_fixed_point output_gamma)); +#endif +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_ALPHA_MODE_SUPPORTED) /* The output_gamma value is a screen gamma in libpng terminology: it expresses * how to decode the output values, not how they are encoded. The values used * correspond to the normal numbers used to describe the overall gamma of a @@ -1230,14 +1232,22 @@ PNG_FIXED_EXPORT(228, void, png_set_alpha_mode_fixed, (png_structp png_ptr, * better to call png_set_alpha_mode() with PNG_DEFAULT_sRGB than rely on the * default if you don't know what the right answer is! * + * The special value PNG_GAMMA_MAC_18 indicates an older Mac system (pre Mac OS + * 10.6) which used a correction table to implement a somewhat lower gamma on an + * otherwise sRGB system. + * + * Both these values are reserved (not simple gamma values) in order to allow + * more precise correction internally in the future. + * * NOTE: the following values can be passed to either the fixed or floating * point APIs, but the floating point API will also accept floating point * values. */ -#define PNG_DEFAULT_sRGB 0 /* sRGB gamma and color space */ +#define PNG_DEFAULT_sRGB -1 /* sRGB gamma and color space */ +#define PNG_GAMMA_MAC_18 -2 /* Old Mac '1.8' gamma and color space */ #define PNG_GAMMA_sRGB 220000 /* Television standards--matches sRGB gamma */ -#define PNG_GAMMA_MAC 151724 /* Television with a 1.45 correction table */ #define PNG_GAMMA_LINEAR PNG_FP_1 /* Linear */ +#endif /* The following are examples of calls to png_set_alpha_mode to achieve the * required overall gamma correction and, where necessary, alpha @@ -1314,7 +1324,6 @@ PNG_FIXED_EXPORT(228, void, png_set_alpha_mode_fixed, (png_structp png_ptr, * made in the same read operation, however multiple calls with PNG_ALPHA_PNG * are ignored. */ -#endif #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED PNG_EXPORT(36, void, png_set_strip_alpha, (png_structp png_ptr)); @@ -1421,7 +1430,13 @@ PNG_EXPORT(49, void, png_set_quantize, /* Handle gamma correction. Screen_gamma=(display_exponent). * NOTE: this API simply sets the screen and file gamma values. It will * therefore override the value for gamma in a PNG file if it is called after - * the file header has been read - use with care! + * the file header has been read - use with care - call before reading the PNG + * file for best results! + * + * These routines accept the same gamma values as png_set_alpha_mode (described + * above). The PNG_GAMMA_ defines and PNG_DEFAULT_sRGB can be passed to either + * API (floating point or fixed.) Notice, however, that the 'file_gamma' value + * is the inverse of a 'screen gamma' value. */ PNG_FP_EXPORT(50, void, png_set_gamma, (png_structp png_ptr, double screen_gamma, diff --git a/pngpriv.h b/pngpriv.h index d6849c317..dfe0ca2aa 100644 --- a/pngpriv.h +++ b/pngpriv.h @@ -459,6 +459,11 @@ PNG_EXTERN png_fixed_point png_fixed PNGARG((png_structp png_ptr, double fp, #define PNG_tRNS PNG_CONST png_byte png_tRNS[5] = {116, 82, 78, 83, '\0'} #define PNG_zTXt PNG_CONST png_byte png_zTXt[5] = {122, 84, 88, 116, '\0'} +/* Gamma values (new at libpng-1.5.3): */ +#define PNG_GAMMA_MAC_OLD 151724 /* Assume '1.8' is really 2.2/1.45! */ +#define PNG_GAMMA_MAC_INVERSE 65909 +#define PNG_GAMMA_sRGB_INVERSE 45455 + /* Inhibit C++ name-mangling for libpng functions but not for system calls. */ #ifdef __cplusplus diff --git a/pngrtran.c b/pngrtran.c index cdf84cedb..dda48c0a2 100644 --- a/pngrtran.c +++ b/pngrtran.c @@ -159,6 +159,68 @@ png_set_strip_alpha(png_structp png_ptr) } #endif +#if defined(PNG_READ_ALPHA_MODE_SUPPORTED) || defined(PNG_READ_GAMMA_SUPPORTED) +static png_fixed_point +translate_gamma_flags(png_structp png_ptr, png_fixed_point output_gamma, + int is_screen) +{ + /* Check for flag values. The main reason for having the old Mac value as a + * flag is that it is pretty near impossible to work out what the correct + * value is from Apple documentation - a working Mac system is needed to + * discover the value! + */ + if (output_gamma == PNG_DEFAULT_sRGB || + output_gamma == PNG_FP_1 / PNG_DEFAULT_sRGB) + { + /* If there is no sRGB support this just sets the gamma to the standard + * sRGB value. (This is a side effect of using this function!) + */ +# ifdef PNG_READ_sRGB_SUPPORTED + png_ptr->flags |= PNG_FLAG_ASSUME_sRGB; +# endif + if (is_screen) + output_gamma = PNG_GAMMA_sRGB; + else + output_gamma = PNG_GAMMA_sRGB_INVERSE; + } + + else if (output_gamma == PNG_GAMMA_MAC_18 || + output_gamma == PNG_FP_1 / PNG_GAMMA_MAC_18) + { + if (is_screen) + output_gamma = PNG_GAMMA_MAC_OLD; + else + output_gamma = PNG_GAMMA_MAC_INVERSE; + } + + return output_gamma; +} + +# ifdef PNG_FLOATING_POINT_SUPPORTED +static png_fixed_point +convert_gamma_value(png_structp png_ptr, double output_gamma) +{ + /* The following silently ignores cases where fixed point (times 100,000) + * gamma values are passed to the floating point API. This is safe and it + * means the fixed point constants work just fine with the floating point + * API. The alternative would just lead to undetected errors and spurious + * bug reports. Negative values fail inside the _fixed API unless they + * correspond to the flag values. + */ + if (output_gamma > 0 && output_gamma < 128) + output_gamma *= PNG_FP_1; + + /* This preserves -1 and -2 exactly: */ + output_gamma = floor(output_gamma + .5); + + if (output_gamma > PNG_FP_MAX || output_gamma < PNG_FP_MIN) + png_fixed_error(png_ptr, "gamma value"); + + return (png_fixed_point)output_gamma; +} +# endif +#endif /* READ_ALPHA_MODE || READ_GAMMA */ + #ifdef PNG_READ_ALPHA_MODE_SUPPORTED void PNGFAPI png_set_alpha_mode_fixed(png_structp png_ptr, int mode, @@ -172,28 +234,15 @@ png_set_alpha_mode_fixed(png_structp png_ptr, int mode, if (png_ptr == NULL) return; - /* If the default_gamma value is 0 then switch on the whole sRGB - * edifice by this flag (note: this is a flag to the later code, - * not a transformation!) - */ - if (output_gamma == PNG_DEFAULT_sRGB) - { - /* If there is no sRGB support this just sets the gamma to the standard - * sRGB value. - */ -# ifdef PNG_READ_sRGB_SUPPORTED - png_ptr->flags |= PNG_FLAG_ASSUME_sRGB; -# endif - output_gamma = PNG_GAMMA_sRGB; - } + output_gamma = translate_gamma_flags(png_ptr, output_gamma, 1/*screen*/); - /* Else validate the value to ensure it is in a reasonable range. The value + /* Validate the value to ensure it is in a reasonable range. The value * is expected to be 1 or greater, but this range test allows for some * viewing correction values. The intent is to weed out users of this API * who use the inverse of the gamma value accidentally! Since some of these * values are reasonable this may have to be changed. */ - else if (output_gamma < 70000 || output_gamma > 300000) + if (output_gamma < 70000 || output_gamma > 300000) png_error(png_ptr, "output gamma out of expected range"); /* The default file gamma is the inverse of the output gamma; the output @@ -286,19 +335,8 @@ png_set_alpha_mode_fixed(png_structp png_ptr, int mode, void PNGAPI png_set_alpha_mode(png_structp png_ptr, int mode, double output_gamma) { - /* The following silently ignores cases where fixed point (times 100,000) - * gamma values are passed to the floating point API. This is safe and it - * means the fixed point constants work just fine with the floating point - * API. The alternative would just lead to undetected errors and spurious - * bug reports. Negative values fail inside the _fixed API. - */ - if (output_gamma > -128 && output_gamma < 128) - output_gamma *= PNG_FP_1; - - if (output_gamma <= PNG_FP_MAX && output_gamma >= PNG_FP_MIN) - png_set_alpha_mode_fixed(png_ptr, mode, (png_fixed_point)output_gamma); - else - png_fixed_error(png_ptr, "png_set_alpha_mode gamma"); + png_set_alpha_mode_fixed(png_ptr, mode, convert_gamma_value(png_ptr, + output_gamma)); } # endif #endif @@ -719,6 +757,10 @@ png_set_gamma_fixed(png_structp png_ptr, png_fixed_point scrn_gamma, if (png_ptr == NULL) return; + /* New in libpng-1.5.3 - reserve particular negative values as flags. */ + scrn_gamma = translate_gamma_flags(png_ptr, scrn_gamma, 1/*screen*/); + file_gamma = translate_gamma_flags(png_ptr, file_gamma, 0/*file*/); + #if PNG_LIBPNG_VER >= 10600 /* Checking the gamma values for being >0 was added in 1.5.3 along with the * premultiplied alpha support; this actually hides an undocumented feature @@ -749,9 +791,8 @@ png_set_gamma_fixed(png_structp png_ptr, png_fixed_point scrn_gamma, void PNGAPI png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma) { - png_set_gamma_fixed(png_ptr, - png_fixed(png_ptr, scrn_gamma, "png_set_gamma screen gamma"), - png_fixed(png_ptr, file_gamma, "png_set_gamma file gamma")); + png_set_gamma_fixed(png_ptr, convert_gamma_value(png_ptr, scrn_gamma), + convert_gamma_value(png_ptr, file_gamma)); } # endif /* FLOATING_POINT_SUPPORTED */ #endif /* READ_GAMMA */ diff --git a/pngset.c b/pngset.c index 1b0fd1d17..2c58f7fc7 100644 --- a/pngset.c +++ b/pngset.c @@ -545,7 +545,7 @@ png_set_sRGB_gAMA_and_cHRM(png_structp png_ptr, png_infop info_ptr, png_set_sRGB(png_ptr, info_ptr, srgb_intent); # ifdef PNG_gAMA_SUPPORTED - png_set_gAMA_fixed(png_ptr, info_ptr, 45455L); + png_set_gAMA_fixed(png_ptr, info_ptr, PNG_GAMMA_sRGB_INVERSE); # endif # ifdef PNG_cHRM_SUPPORTED