diff --git a/ANNOUNCE b/ANNOUNCE index 329a3f0f2..c9fb10090 100644 --- a/ANNOUNCE +++ b/ANNOUNCE @@ -1,5 +1,5 @@ -Libpng 1.6.0beta31 - October 27, 2012 +Libpng 1.6.0beta31 - November 1, 2012 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. @@ -525,7 +525,7 @@ Version 1.6.0beta30 [October 24, 2012] Fixed build when using #define PNG_NO_READ_GAMMA in png_do_compose() in pngrtran.c (Domani Hannes). -Version 1.6.0beta31 [October 27, 2012] +Version 1.6.0beta31 [November 1, 2012] Undid the erroneous change to vstudio/pngvalid build in libpng-1.6.0beta30. Made pngvalid so that it will build outside the libpng source tree. Changed ICC profile support to allow use of an external color management @@ -550,6 +550,9 @@ Version 1.6.0beta31 [October 27, 2012] question (typically most users who disable it won't). Fixed GUIDs in projects/vstudio. Some were duplicated or missing, resulting in VS2010 having to update the files. + Removed non-working ICC profile support code. There was too much code + for too little gain; implementing full ICC color correction is maybe + desireable but is left up to applications. Send comments/corrections/commendations to png-mng-implement at lists.sf.net (subscription required; visit diff --git a/CHANGES b/CHANGES index b38a2ca61..6f72fe4d8 100644 --- a/CHANGES +++ b/CHANGES @@ -4277,7 +4277,7 @@ Version 1.6.0beta30 [October 24, 2012] Fixed build when using #define PNG_NO_READ_GAMMA in png_do_compose() in pngrtran.c (Domani Hannes). -Version 1.6.0beta31 [October 27, 2012] +Version 1.6.0beta31 [November 1, 2012] Undid the erroneous change to vstudio/pngvalid build in libpng-1.6.0beta30. Made pngvalid so that it will build outside the libpng source tree. Changed ICC profile support to allow use of an external color management @@ -4302,6 +4302,9 @@ Version 1.6.0beta31 [October 27, 2012] question (typically most users who disable it won't). Fixed GUIDs in projects/vstudio. Some were duplicated or missing, resulting in VS2010 having to update the files. + Removed non-working ICC profile support code. There was too much code + for too little gain; implementing full ICC color correction is maybe + desireable but is left up to applications. Send comments/corrections/commendations to png-mng-implement at lists.sf.net (subscription required; visit diff --git a/png.c b/png.c index 27d31d357..4ff33df38 100644 --- a/png.c +++ b/png.c @@ -668,7 +668,7 @@ png_init_io(png_structrp png_ptr, png_FILE_p fp) * complement format. If this isn't the case, then this routine needs to * be modified to write data in two's complement format. Note that, * the following works correctly even if png_int_32 has more than 32 bits - * (compare the more complex code required on read for sign extention.) + * (compare the more complex code required on read for sign extension.) */ void PNGAPI png_save_int_32(png_bytep buf, png_int_32 i) @@ -766,13 +766,13 @@ png_get_copyright(png_const_structrp png_ptr) #else # ifdef __STDC__ return PNG_STRING_NEWLINE \ - "libpng version 1.6.0beta31 - October 26, 2012" PNG_STRING_NEWLINE \ + "libpng version 1.6.0beta31 - November 1, 2012" PNG_STRING_NEWLINE \ "Copyright (c) 1998-2012 Glenn Randers-Pehrson" PNG_STRING_NEWLINE \ "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \ "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \ PNG_STRING_NEWLINE; # else - return "libpng version 1.6.0beta31 - October 26, 2012\ + return "libpng version 1.6.0beta31 - November 1, 2012\ Copyright (c) 1998-2012 Glenn Randers-Pehrson\ Copyright (c) 1996-1997 Andreas Dilger\ Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc."; @@ -1780,7 +1780,7 @@ png_colorspace_set_sRGB(png_const_structrp png_ptr, png_colorspacerp colorspace, if ((colorspace->flags & PNG_COLORSPACE_FROM_sRGB) != 0) { png_benign_error(png_ptr, "duplicate sRGB information ignored"); - return 0; /* not set */ + return 0; } /* If the standard sRGB cHRM chunk does not match the one from the PNG file @@ -1816,7 +1816,7 @@ png_colorspace_set_sRGB(png_const_structrp png_ptr, png_colorspacerp colorspace, colorspace->flags |= (PNG_COLORSPACE_MATCHES_sRGB|PNG_COLORSPACE_FROM_sRGB); - return 1/*set*/; + return 1; /* set */ } #endif /* sRGB */ @@ -1850,7 +1850,6 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, png_const_bytep profile/* first 132 bytes only */, int color_type) { png_uint_32 temp; - png_uint_32 info = 0; /* bitmask of profile info */ /* Length check; this cannot be ignored in this code because profile_length * is used later to check the tag table, so even if the profile seems over @@ -1938,7 +1937,6 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, if (!(color_type & PNG_COLOR_MASK_COLOR)) return png_icc_profile_error(png_ptr, colorspace, name, temp, "RGB color space not permitted on grayscale PNG"); - info |= PNG_ICC_RGB; break; case 0x47524159: /* 'GRAY' */ @@ -2013,9 +2011,6 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, switch (temp) { case 0x58595A20: /* 'XYZ ' */ - info |= PNG_ICC_PCSXYZ; - break; - case 0x4C616220: /* 'Lab ' */ break; @@ -2024,676 +2019,9 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, "unexpected ICC PCS encoding"); } - /* Store the profile info flags */ - colorspace->icc_info = info; return 1; } -#ifdef PNG_ICC_SUPPORTED -static png_uint_32 -png_icc_find_tag(png_const_bytep profile, png_uint_32 tag, png_uint_32p length) - /* Find a single tag in the tag table, returns 0 if the tag is not found, - * else returns the offset in the profile of the tag and, via *length, the - * length from the tag table. - * - * TODO: this can probably be avoided by caching the values. - */ -{ - png_uint_32 tag_count = png_get_uint_32(profile+128); - - profile += 132; - - while (tag_count-- > 0) - { - if (png_get_uint_32(profile) == tag) - { - *length = png_get_uint_32(profile+8); - return png_get_uint_32(profile+4); - } - profile += 12; - } - - return 0; -} - -/* Useful types used for the math. - * NOTE: the use of const on array types here actually creates the type (const - * png_int_32)[], not (const (png_int_32[])), consequently a compiler may object - * to passing a (png_int_32[]) (which does not have const elements). - */ -#if __GNUC__ == 4 && __GNUC_MINOR__ == 2 - /* GCC 4.2 has an optimization bug which means that if this code is compiled - * with any optimization (i.e. not -O0) it somehow manages to make casts to - * png_const_icc_matrixrp not work in some cases and so warns for some - * function calls. This works round the problem without harming optimization - * with other compilers. - */ -# define PNG_ICC_CONST -#else -# define PNG_ICC_CONST const -#endif -typedef png_int_32 png_icc_vector[3]; -typedef png_int_32 (*PNG_RESTRICT png_icc_vectorrp)[3]; -typedef PNG_ICC_CONST png_int_32 (*PNG_RESTRICT png_const_icc_vectorrp)[3]; -#define png_cpv(vector) png_constcast(PNG_ICC_CONST png_icc_vector*,&vector) - -typedef png_int_32 png_icc_matrix[3][3]; -typedef png_int_32 (*PNG_RESTRICT png_icc_matrixrp)[3][3]; -typedef PNG_ICC_CONST png_int_32 (*PNG_RESTRICT png_const_icc_matrixrp)[3][3]; -#define png_cpm(matrix) png_constcast(PNG_ICC_CONST png_icc_matrix*,&matrix) - -/* These two painfully complex routines are to detect under or overflow on - * addition or subtraction of two 32-bit signed integers. There's probably a - * better way of doing this. - * - * TODO: look at the on-line resources for this kind of bit banging. - */ -static int -png_add(png_int_32 * PNG_RESTRICT result, png_int_32 a, png_int_32 b) -{ - if ((a ^ b) < 0 || /* Signs differ */ - (a >= 0 && b <= 0x7fffffff-a) || - (a < 0 && b >= (-0x7fffffff-1)-a)) - { - *result = a+b; - return 1; - } - - return 0; /* overflow */ -} - -static int -png_sub(png_int_32 * PNG_RESTRICT result, png_int_32 a, png_int_32 b) -{ - if ((a ^ b) > 0 || /* Signs the same, and neither is zero */ - (a >= 0 && b >= a-0x7fffffff) || - (a < 0 && a >= (-0x7fffffff-1)+b)) - { - *result = a-b; - return 1; - } - - return 0; /* overflow */ -} - -static int -png_matrix_x_vector(png_const_icc_matrixrp m, png_const_icc_vectorrp v, - png_icc_vectorrp o) - /* Apply the matrix (prefixed) to the column vector, updating the vector with - * the result. - */ -{ - int row; - - /* NOTE: this makes no attempt to avoid intermediate sum overflow. */ - for (row=0; row<3; ++row) - { - int column; - png_int_32 e = 0; - - for (column=0; column<3; ++column) - { - png_int_32 temp; - - if (!png_muldiv(&temp, (*m)[row][column], (*v)[column], 65536) || - !png_add(&e, e, temp)) - return 0; /* overflow */ - } - - (*o)[row] = e; - } - - return 1; -} - -static int -png_matrix_x_TmatrixT(png_const_icc_matrixrp m1, png_const_icc_matrixrp m2, - png_icc_matrixrp o) - /* NOTE: this passes in the transpose of the input matrix (because it passes - * rows, not columns to x_vector) and then transposes the output too. To get - * correct matrix multiplication of two matrices it is necessary to transpose - * the second matrix both before and after this function. - */ -{ - int row; - - for (row=0; row<3; ++row) - if (!png_matrix_x_vector(m1, &(*m2)[row], &(*o)[row])) - return 0; - - return 1; -} - -static int -png_cofactor(png_int_32 *PNG_RESTRICT d, png_const_icc_matrixrp m, int i, int j) -{ - /* The determinant of a 2x2 matrix is m[0][0]m[1][1] - m[0][1]m[1][0], i and - * j are in the range 0..2 and select out m[i][] and m[][j]. - */ - png_int_32 a, b; - const int i_0 = (i>0?0:1); - const int i_1 = (i<2?2:1); - const int j_0 = (j>0?0:1); - const int j_1 = (j<2?2:1); - - if (png_muldiv(&a, (*m)[i_0][j_0], (*m)[i_1][j_1], 65536) && - png_muldiv(&b, (*m)[i_0][j_1], (*m)[i_1][j_0], 65536)) - { - png_int_32 temp; - - /* The cofactor is (a-b) times (-1)^(i+j): */ - if (((i+j) & 1) != 0) - temp = a, a = b, b = temp; - - if (png_sub(d, a, b)) - return 1; - } - - return 0; /* overflow */ -} - -static int -png_determinant(png_int_32 * PNG_RESTRICT result, png_const_icc_matrixrp m) -{ - /* Develop from the first row: */ - int j; - png_int_32 d = 0; - - for (j=0; j<3; ++j) - { - png_int_32 cofactor, product; - - if (png_cofactor(&cofactor, m, 0, j) && - png_muldiv(&product, (*m)[0][j], cofactor, 65536) && - png_add(&d, d, product)) - continue; - - return 0; /* overflow */ - } - - *result = d; - return 1; -} - -static int -png_invert_matrix(png_const_icc_matrixrp m, png_icc_matrixrp o) - /* Invert the given matrix. */ -{ - /* This is the algorithm you learnt in highschool; the cofactor method. Each - * element (i,j) of the original matrix is replaced by the 2x2 determinant of - * the matrix obtained by striking out everything in the same row or column - * as the transposed element (j,i), negated if j+i is odd, and the whole - * divided by the determinant of the original. - */ - png_int_32 d; - - if (png_determinant(&d, m) && d != 0) - { - int i; - - for (i=0; i<3; ++i) - { - int j; - - for (j=0; j<3; ++j) - { - png_int_32 cofactor; - - if (png_cofactor(&cofactor, m, j, i/*transposed*/) && - png_muldiv(&(*o)[i][j], cofactor, 65536, d)) - continue; - - return 0; /* overflow in element calculation */ - } - } - - return 1; - } - - return 0; /* overflow in determinant or zero determinant */ -} - -static int -png_icc_XYZ_compare(png_const_bytep xyz1, png_const_bytep xyz2) - /* The arguments are 12 byte big-endian XYZ values as s15Fixed16 values, they - * are compared and the routine returns 0 if they are within about +/-1/1024 - * else 1. The input values are always big-endian. - */ -{ - int i; - - for (i=0; i<3; ++i) - { - int diff = 0; - int j; - - /* This won't overflow. */ - for (j=0; j<3; ++j) - diff = (diff << 8) + (*xyz1++ - *xyz2++); - - if (diff < -1 || diff > 1) - return 1; /* Too big a difference */ - - diff = (diff << 8) + (*xyz1++ - *xyz2++); - - /* This is the limit on the difference, 64/65536 or +/- 1/1024 (determined - * by experiment) at present. - */ - if (diff <= -64 || diff >= 64) - return 1; - } - - return 0; -} - -static int -png_icc_check_wtpt(png_const_structrp png_ptr, png_const_charp name, - png_const_bytep profile, png_icc_vectorrp adapted_white_point) - /* The mediaWhitePointTag contains an adapted white point (the observer - * white point) expressed as XYZ tristimulus values. It is always adapted - * to the PCS illuminant (but is XYZ even when the PCS is PCSLAB encoded.) - */ -{ - png_uint_32 tag_length; - png_uint_32 tag_start = png_icc_find_tag(profile, 0x77747074/*'wtpt'*/, - &tag_length); - - if (tag_start > 0 && tag_length == 20) - { - png_const_bytep tag = profile+tag_start; - png_uint_32 temp = png_get_uint_32(tag); - - if (temp == 0x58595A20 /* 'XYZ ' */) - { - /* The media white point tag is chromatically adapted using the - * chromatic adaptation matrix and so the adaptation must be inverted - * to find the original white point. The tag should match the PCS - * illuminant for display ('mntr') profiles (9.2.34 of the 2010 spec) - * and, for color space profiles, it is meaningless and apparently - * unspecified what happens if it does not. - * - * This is just a warning at present - one old sRGB profile triggers - * it; see the note below on the sRGB profile signatures (for the - * profile "sRGB Profile.icc".) In that profile the mediaWhitePointTag - * is incorrectly recorded with the D65 (not D50) values. - */ - if (adapted_white_point != NULL) - { - (*adapted_white_point)[0] = png_get_int_32(tag+ 8); - (*adapted_white_point)[1] = png_get_int_32(tag+12); - (*adapted_white_point)[2] = png_get_int_32(tag+16); - } - - if (png_icc_XYZ_compare(profile+68, tag+8) == 0) - return 1; - - /* The media white point differs from the PCS illuminant. - * - * This deserves a warning; the PNG data stream is technically invalid - * because either the ICC profile is wrong or the color data in the - * image is not encoded in the way the PNG specification expects, such - * that colors with r==g==b are achromatic. - * - * Notice that on write the application can write a cHRM chunk to - * attempt to minimize the problems this might cause, however the data - * has the property that the maximum of all the colorants (r,g,b == - * 1,1,1) does not correspond to an achromatic color and this is - * impossible to represent in PNG with just cHRM. - * - * If this is a monitor of color-space class profile then the profile - * is wrong (the white point should always be the same as the image - * adopted white), otherwise a simple warning is produced. - */ - temp = png_get_uint_32(profile+12); - - if (temp == 0x6D6E7472 /* 'mntr' */ || - temp == 0x73706163 /* 'spac' */) - (void)png_icc_profile_error(png_ptr, NULL, name, temp, - "media white point differs from image adopted white"); - - else - png_warning(png_ptr, "ICC profile indicates that image data does " - "not conform to the PNG specification"); - - return 0; - } - - else - { - (void)png_icc_profile_error(png_ptr, NULL, name, temp, - "invalid type for mediaWhitePointTag"); - /* Assume it matches the PCS illuminant */ - } - } - - /* else: no mediaWhitePointTag, already reported */ - - /* Here if the mediaWhitePointTag is absent or invalid, assume the PCS - * illuminant; this is an error in the profile, but is mostly harmless. - */ - if (adapted_white_point != NULL) - { - (*adapted_white_point)[0] = png_get_int_32(profile+68); - (*adapted_white_point)[1] = png_get_int_32(profile+72); - (*adapted_white_point)[2] = png_get_int_32(profile+76); - } - - return 1; -} - -static int /* 0: fail, 1: identity, 2: not identity */ -png_icc_find_chad(png_const_structrp png_ptr, png_const_charp name, - png_const_bytep profile, png_icc_matrixrp adaptation_matrix, - png_icc_matrixrp inverted_adaptation_matrix) - /* The PNG cHRM chunk records the chromaticities of the colorants. - * Chromaticities are a measure of the appearance of the colors to a - * typical human observer in a specified viewing environment. The PNG - * specification does not list a viewing environment, thus we must - * assume that the values have not been adjusted (adapted) for a - * particular viewing environment. This means, implicitly, that a PNG - * image is actually adapted for a white point equivalent to the - * maximum colorant values, and this is also implied by storing a - * chromaticity which has a white point derived simply from maximum - * colorant values. - * - * All of the methods for determining the cHRM values depend on - * reversing the adaptatation to the PCS adopted white (D50); this is - * because in all cases one or other PCS value has to be used. - * - * This routine determines if 'chad' tag is present (if not the adopted white - * of the scene is D50 and no adaptation was performed) and returns the - * inverted matrix. - */ - { - png_uint_32 tag_start, tag_length; - - tag_start = png_icc_find_tag(profile, 0x63686164/*'chad'*/, &tag_length); - - if (tag_start > 0) - { - if (tag_length == 44) /* This was checked before */ - { - png_const_bytep tag = profile+tag_start; - png_uint_32 temp = png_get_uint_32(tag); - - if (temp == 0x73663332 /* 'sf32' */) - { - /* And the arguments are 9 15.16 values left to right then top - * to bottom for the forward adaptation matrix, these must be - * invertible and we need the inverted matrix here. - */ - png_int_32 * PNG_RESTRICT op = &(*adaptation_matrix)[0][0]; - int i; - - tag += 8; - - for (i=0; i<9; ++i, tag += 4) - *op++ = png_get_int_32(tag); - - if (png_invert_matrix( - png_constcast(png_const_icc_matrixrp, adaptation_matrix), - inverted_adaptation_matrix)) - return 2; - - (void)png_icc_profile_error(png_ptr, NULL, name, temp, - "singular or overflowed ICC profile chromaticAdaptationTag"); - } - - else - (void)png_icc_profile_error(png_ptr, NULL, name, temp, - "invalid type for ICC profile chromaticAdaptationTag"); - } - - else /* Internal libpng error */ - (void)png_icc_profile_error(png_ptr, NULL, name, tag_length, - "invalid length for ICC profile chromaticAdaptationTag"); - } - - else - { - /* No 'chad' means no adaptation, so return the identity matrix and '1' to - * indicate identity. - */ - memset(adaptation_matrix, 0, sizeof *adaptation_matrix); - (*adaptation_matrix)[0][0] = 0x10000; - (*adaptation_matrix)[1][1] = 0x10000; - (*adaptation_matrix)[2][2] = 0x10000; - memcpy(inverted_adaptation_matrix, adaptation_matrix, - sizeof *inverted_adaptation_matrix); - return 1; - } - - /* Error return */ - return 0; -} - -static void -png_icc_set_cHRM_from_endpoints(png_const_structrp png_ptr, - png_colorspacerp colorspace, png_const_charp name, png_const_bytep profile, - png_const_uint_16p pcsxyz) - /* The input XYZ values are the three red, green, blue endpoints still - * adapted to the PCS illuminant. The adaptation is inverted and the result - * applied to the profile. The result is also checked against the - * PCS illuminant, which should match the sum of the end points. - */ -{ - png_icc_matrix adaptation, inverted_adaptation; - int chad = png_icc_find_chad(png_ptr, name, profile, &adaptation, - &inverted_adaptation); - - if (chad) /* else error finding 'chad' */ - { - png_byte end_point_white[3*4]; - png_icc_matrix XYZ, end_points; - - /* Sanity check the adapted colorants against the PCS white point - - * because of the checks performed before calling this routine the adapted - * colorant white point should always match the PCS illuminant. - */ - { - int i; - - for (i=0; i<3; ++i) - { - png_int_32 c = pcsxyz[i]; - - c += pcsxyz[i+3]; - c += pcsxyz[i+6]; - /* Convert u1Fixed15Number to s15Fixed16Number */ - png_save_int_32(end_point_white+4*i, 2*c); - } - - if (png_icc_XYZ_compare(profile+68, end_point_white) != 0) - { - /* The colorant (media) white point differs from the PCS illuminant. - */ - (void)png_icc_profile_error(png_ptr, NULL, name, - colorspace->icc_info, - "colorant white point differs from image adopted white"); - return; - } - } - - { - int row, col; - - /* The png_icc_matrix is a matrix of s15Fixed16Number, the pcsxyz - * returned by the CMS is u1Fixed15, so multiply by 65536/32768 - */ - for (row=0; row<3; ++row) for (col=0; col<3; ++col) - XYZ[row][col] = 2 * pcsxyz[3*row + col]; - } - - if (chad == 1) /* identity */ - memcpy(&end_points, XYZ, sizeof end_points); - - else /* apply the matrix */ - { - /* The input XYZ rows are unadapted using the 'chad' matrix and - * assigned to the end_points rows. - */ - if (!png_matrix_x_TmatrixT(png_cpm(inverted_adaptation), png_cpm(XYZ), - &end_points)) - { - (void)png_icc_profile_error(png_ptr, NULL, name, 0, - "overflow unadapting colorant end-points"); - return; - } - } - - { - png_XYZ cHRM_XYZ; - - /* Now we have colorant XYZ values in their unadapted form - * (i.e. implicitly with an adopted white of the original scene). - * This is what PNG uses for cHRM, but they need to be - * converted to the libpng structure. - * - * The scaling required is 100000/0x8000, because the input - * values have been unadapted however they may be well out of the - * original 16-bit range, so use png_muldiv here. - * - * fp = pcs * 100000 / 32768 - * = pcs * 3125 / 1024; - */ - if (png_muldiv(&cHRM_XYZ.red_X, end_points[0][0], 3125, 1024) && - png_muldiv(&cHRM_XYZ.red_Y, end_points[0][1], 3125, 1024) && - png_muldiv(&cHRM_XYZ.red_Z, end_points[0][2], 3125, 1024) && - png_muldiv(&cHRM_XYZ.green_X, end_points[1][0], 3125, 1024) && - png_muldiv(&cHRM_XYZ.green_Y, end_points[1][1], 3125, 1024) && - png_muldiv(&cHRM_XYZ.green_Z, end_points[1][2], 3125, 1024) && - png_muldiv(&cHRM_XYZ.blue_X, end_points[2][0], 3125, 1024) && - png_muldiv(&cHRM_XYZ.blue_Y, end_points[2][1], 3125, 1024) && - png_muldiv(&cHRM_XYZ.blue_Z, end_points[2][2], 3125, 1024)) - { - png_xy xy; - - /* This function returns 0 on success: */ - if (!png_colorspace_check_XYZ(&xy, &cHRM_XYZ)) - { - /* TODO: review this, it currently overwrites an explicit cHRM - * chunk, this seems safer as the cHRM chunk is often calculated - * incorrectly. In release builds this overwrites silently, - * in pre-release it will cause an error. - */ - (void)png_colorspace_set_xy_and_XYZ(png_ptr, - colorspace, &xy, &cHRM_XYZ, - (PNG_LIBPNG_BUILD_BASE_TYPE < PNG_LIBPNG_BUILD_RC) ? 1 : 2); - return; - } - - /* Else the XYZ value was invalid */ - (void)png_icc_profile_error(png_ptr, NULL, name, 0, - "invalid colorant end-points"); - } - - else - (void)png_icc_profile_error(png_ptr, NULL, name, 0, - "overflow converting colorant end-points to cHRM"); - } - } -} - -#ifndef PNG_FLOATING_ARITHMETIC_SUPPORTED -/* This is defined below, so a forward declaration is needed here. */ -static png_int_32 png_log16bit(png_uint_32 x); -#endif - -static void -png_icc_set_gAMA_from_Y(png_const_structrp png_ptr, png_colorspacerp colorspace, - png_uint_32 y, int is_u1Fixed15/*scale of y*/) -{ - /* PNG gAMA approximates the actual transfer function used to encode - * the image data with a single number in a power law equation: - * - * image = sample ^ gAMA - * - * So given a test image value (GRAY_TEST) and the value of Y, 'y', - * which the transform produces we can simply deduce the value of gAMA: - * - * gAMA = log(GRAY_TEST)/log(y) - * - * However this will produce different answers for each point on the - * profile, unless the profile really is a simple power law transform - * (this is hardly ever found in practice.) - * - * In fact most image encoding uses some variant of a linear segment - * followed by a power law - sRGB, ITU REC709 and L*a*b* all do this. - * We know (from the PNG spec) that sRGB should be encoded with a gAMA - * of .45455 (1/2.2) and it is easy to find that the sRGB transfer - * function crosses this power law transfer at about 0.389222. This is - * 25508 as a 16-bit value or 99.25 in 8-bits. - */ -# define GRAY_TEST 99 /* /255 */ - /* - * Feeding this number through the above equations (see - * contrib/tools/icc-gamma.bc) gives the following results: - * - * sRGB: 45455 - * L*a*b*: 42069 - * 2.2 power law: 45455 - * ITU REC-709: 52333 (because of the linear segment) - * Apple Mac: 65087 (by applying a 1.45 power law to sRGB) - */ -# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED - double dl; - - if (is_u1Fixed15) y *= 2; - - /* The constant is 100000*log(99/255) */ - dl = floor(.5 - 94614.36950238362194 / log(y / 65535.)); - - /* We expect a reasonable gAMA value from this calculation; check for a - * number in the range 20,000 (.2) to 200,000 (2). - */ - if (dl > 20000. && dl < 200000.) - { - png_int_32 l = (png_int_32)dl; -# else - /* The fixed point calculation is somewhat more complex. - * - * Because PCSXYZ is scaled by 32768, whereas the input to png_log16bit - * is scaled by 65535 the value of 'l' corresponds to y*32768/65535, - * thus the required calculation is: - * - * 100000 * 89456.43138 - * gAMA = -------------------- - * l + 65535 - * - * l = 65536*-log2(y) - * 89456 = -65536*log2(99/255) - * 65535 = -65536*log2(32768/65535) (but only for PCSXYZ) - * - * 8945643138 = 1581061 * 5658 - */ - png_int_32 l = png_log16bit(y); - - if (is_u1Fixed15 && l >= 0) - l += 65535; /* Overflow will just make this negative */ - - if (png_muldiv(&l, 1581061, 5658, l) && l >= 20000 && l <= 200000) - { -# endif - if (png_colorspace_check_gamma(png_ptr, colorspace, l, - 0/*from profile*/)) - { - /* Store this gamma value. */ - colorspace->gamma = l; - colorspace->flags |= PNG_COLORSPACE_HAVE_GAMMA; - } - } - - else - { - /* This is just a warning that the algorithm has failed in an - * apparently extreme way. (This is here mainly to discover - * profiles on which the algorithm doesn't work.) - */ - png_warning(png_ptr, "ICC profile gamma value out of range"); - } -} -#endif /* PNG_ICC_SUPPORTED */ - int /* PRIVATE */ png_icc_check_tag_table(png_const_structrp png_ptr, png_colorspacerp colorspace, png_const_charp name, png_uint_32 profile_length, @@ -2702,7 +2030,6 @@ png_icc_check_tag_table(png_const_structrp png_ptr, png_colorspacerp colorspace, png_uint_32 tag_count = png_get_uint_32(profile+128); png_uint_32 itag; png_const_bytep tag = profile+132; /* The first tag */ - png_uint_32 tags = colorspace->icc_info; /* Bitmask of significant tags */ /* First scan all the tags in the table and add bits to the icc_info value * (temporarily in 'tags'). @@ -2712,7 +2039,6 @@ png_icc_check_tag_table(png_const_structrp png_ptr, png_colorspacerp colorspace, png_uint_32 tag_id = png_get_uint_32(tag+0); png_uint_32 tag_start = png_get_uint_32(tag+4); /* must be aligned */ png_uint_32 tag_length = png_get_uint_32(tag+8);/* not padded */ - png_uint_32 tag_flag = 0; /* The ICC specification does not exclude zero length tags, therefore the * start might actually be anywhere if there is no data, but this would be @@ -2730,345 +2056,12 @@ png_icc_check_tag_table(png_const_structrp png_ptr, png_colorspacerp colorspace, "ICC profile tag start not a multiple of 4"); } - /* Skip short tags, even if there is enough space for the type signature - * all the types used by libpng need data. - */ - if (tag_length < 8) - { - (void)png_icc_profile_error(png_ptr, NULL, name, tag_id, - "short ICC profile tag skipped"); - continue; - } - /* This is a hard error; potentially it can cause read outside the * profile. */ if (tag_start > profile_length || tag_length > profile_length - tag_start) return png_icc_profile_error(png_ptr, colorspace, name, tag_id, "ICC profile tag outside profile"); - - /* Check the tag_id for the specific tags which must be present for the - * profile to be valid and for those which are needed to generate cHRM and - * gAMA values. The errors in here are all soft; they just cause a - * warning on read and the tag is skipped. On write by they cause a - * png_app_error, which the application can override. - */ - switch (tag_id) - { - case 0x64657363: /* 'desc' - profileDescriptionTag */ - tags |= PNG_ICC_profileDescriptionTag; - break; - - case 0x63707274: /* 'cprt' - copyrightTag */ - tags |= PNG_ICC_copyrightTag; - break; - - case 0x77747074: /* 'wtpt' - mediaWhitePointTag */ - /* The length is fixed because the tag has to be an XYZType (12 - * bytes). - */ - if (tag_length != 20) - (void)png_icc_profile_error(png_ptr, NULL, name, tag_length, - "invalid media white point length"); - - else - tags |= PNG_ICC_mediaWhitePointTag; - break; - - case 0x63686164: /* 'chad' - chromaticAdaptationTag */ - /* The tag must be a 9 element array of s15Fixed16ArrayType, the tag - * is optional, if absent it indicates that the original adapted - * white was the same as the PCS adopted white - D50. - */ - if (tag_length != 44) - (void)png_icc_profile_error(png_ptr, NULL, name, tag_start, - "invalid chromatic adaptation matrix length"); - - else - tags |= PNG_ICC_chromaticAdaptationTag; - break; - - case 0x7258595A: /* 'rXYZ' - redMatrixColumnTag */ - tag_flag = PNG_ICC_redMatrixColumnTag; - goto check_MatrixColumnTag_length; - - case 0x6758595A: /* 'gXYZ' - greenMatrixColumnTag */ - tag_flag = PNG_ICC_greenMatrixColumnTag; - goto check_MatrixColumnTag_length; - - case 0x6258595A: /* 'bXYZ' - blueMatrixColumnTag */ - tag_flag = PNG_ICC_blueMatrixColumnTag; - goto check_MatrixColumnTag_length; - - check_MatrixColumnTag_length: - /* Tag must be an XYZType with one XYZNumber element, the PCS - * encoding should be PCSXYZ, however lcms seems to use these tags - * to record the end-point XYZ (i.e. it is using MatrixColumnTag in - * place of colorantTableTag!) This is probably eroneous but is not - * clearly outlawed by the specification. - */ - if (tag_length != 20) - (void)png_icc_profile_error(png_ptr, NULL, name, tag_id, - "invalid MatrixColumnTag length"); - - else if (!(tags & PNG_ICC_RGB)) - (void)png_icc_profile_error(png_ptr, NULL, name, tag_id, - "invalid MatrixColumnTag on monochrome profile"); - - else - tags |= tag_flag; - break; - - case 0x72545243: /* 'rTRC' - redTRCTag */ - tag_flag = PNG_ICC_redTRCTag; - goto check_rgbTRCTag_encoding; - - case 0x67545243: /* 'gTRC' - greenTRCTag */ - tag_flag = PNG_ICC_greenTRCTag; - goto check_rgbTRCTag_encoding; - - case 0x62545243: /* 'bTRC' - blueTRCTag */ - tag_flag = PNG_ICC_blueTRCTag; - goto check_rgbTRCTag_encoding; - - check_rgbTRCTag_encoding: - /* The TRCTags feed into the MatrixColumnTag matrix and this is - * never going to work if the encoding is PCSLAB, so disallow the - * TRC tags here. The MatrixColumnTags are still accumulated, this - * requires special handling below. - */ - if (!(tags & PNG_ICC_RGB)) - (void)png_icc_profile_error(png_ptr, NULL, name, tag_id, - "invalid TRCTag on monochrome profile"); - - else if (!(tags & PNG_ICC_PCSXYZ)) - (void)png_icc_profile_error(png_ptr, NULL, name, tag_id, - "invalid TRCTag (requires PCSXYZ encoding)"); - - else - goto check_TRCTag_length; - - break; /* skip on error */ - - case 0x6B545243: /* 'kTRC' - grayTRCTag */ - if ((tags & PNG_ICC_RGB) != 0) - (void)png_icc_profile_error(png_ptr, NULL, name, tag_id, - "invalid grayTRCTag on RGB profile"); - - else - { - tag_flag = PNG_ICC_grayTRCTag; - goto check_TRCTag_length; - } - - break; /* skip on error */ - - check_TRCTag_length: - /* Permitted types are curveType or parametricCurveType, curveType - * is shortest, only 12 bytes for an identity response. - */ - if (tag_length < 12) - (void)png_icc_profile_error(png_ptr, NULL, name, tag_id, - "invalid TRCTag length"); - - else - tags |= tag_flag; - break; - - case 0x41324230: /* 'A2B0' - AToB0Tag */ - tag_flag = PNG_ICC_AToB0Tag; - goto check_AToBxTag_length; - - case 0x42324130: /* 'B2A0' - BToA0Tag */ - tag_flag = PNG_ICC_BToA0Tag; - goto check_AToBxTag_length; - - case 0x41324231: /* 'A2B1' - AToB1Tag */ - tag_flag = PNG_ICC_AToB1Tag; - goto check_AToBxTag_length; - - case 0x42324131: /* 'B2A1' - BToA1Tag */ - tag_flag = PNG_ICC_BToA1Tag; - goto check_AToBxTag_length; - - case 0x41324232: /* 'A2B2' - AToB2Tag */ - tag_flag = PNG_ICC_AToB2Tag; - goto check_AToBxTag_length; - - case 0x42324132: /* 'B2A2' - BToA2Tag */ - tag_flag = PNG_ICC_BToA2Tag; - goto check_AToBxTag_length; - - check_AToBxTag_length: - /* Permitted types are lut8Type, lut16Type and one or other of - * lutAToBType or lutBToAType (which are the same length.) The - * CLUT forms have a 32 byte header, the headers on the others are - * longer. In fact all need more data than this in practice. - */ - if (tag_length < 32) - (void)png_icc_profile_error(png_ptr, NULL, name, tag_id, - "invalid LUT Tag length"); - - else - tags |= tag_flag; - break; - - /* NOTE: the DToB and BToD tags, while permitted, cannot be used on - * PNG data because it can never be floating point. - */ - - case 0x6368726D: /* 'chrm' - chromaticityTag */ - /* May exist for RGB or GRAY color spaces and this determines the - * number of channels, the permitted type is chromaticityType. - */ - if (tag_length != 12 + 8*PNG_ICC_CHANNELS(tags)) - (void)png_icc_profile_error(png_ptr, NULL, name, tag_id, - "invalid chromaticityTag length"); - - else - tags |= PNG_ICC_chromaticityTag; - break; - - case 0x636C7274: /* 'clrt' - colorantTableTag */ - /* The permitted type is colorantTableType and the number of - * colorants are determined by the number of channels, as above. - */ - if (tag_length != 12 + 38*PNG_ICC_CHANNELS(tags)) - (void)png_icc_profile_error(png_ptr, NULL, name, tag_id, - "invalid colorantTableTag length"); - - else - tags |= PNG_ICC_colorantTableTag; - break; - - case 0x67616D74: /* 'gamt' - gamutTag */ - /* The permitted types are lut8Type, lut16Type or lutBToAType - * (required by output LUT based profiles.) - */ - tag_flag = PNG_ICC_gamutTag; - goto check_AToBxTag_length; - - default: - break; - } - } - - /* Cache the list of found tags for use later */ - colorspace->icc_info = tags; - - /* The required tags depend on the profile class and, within the class, - * the type of profile - N-component LUT based ('LUT'), Three-component - * matrix-based ('RGB Matrix'), or monochrome ('monochrome'). - * - * All profiles except DeviceLink profiles require PNG_ICC_REQUIRED_ALL. - */ - { - png_uint_32 profile_class = png_get_uint_32(profile+12); - png_uint_32 required_tags = PNG_ICC_REQUIRED_BASE; - png_uint_32 permitted_tags = ~PNG_ICC_ALL_TRC; /* LUT based */ - int LUT_based = 1; - - /* Work out a profile independent setting then update this below if the - * profile had different requirements. - */ - if (tags & PNG_ICC_ALL_TRC) - { - /* A TRCTag is present, check the colorspace to find out what is - * permitted and required. - */ - if (tags & PNG_ICC_RGB) /* 3-component */ - { - required_tags |= PNG_ICC_REQUIRED_RGB_MATRIXTRC; - permitted_tags |= PNG_ICC_REQUIRED_RGB_MATRIXTRC; - } - - else /* monochrome */ - { - required_tags |= PNG_ICC_grayTRCTag; - permitted_tags |= PNG_ICC_grayTRCTag; - } - - LUT_based = 0; - } - - else - { - /* No MatrixTRC - must be LUT based, the AToB0Tag is required */ - required_tags |= PNG_ICC_AToB0Tag; - } - - switch (profile_class) - { - case 0x73636E72: /* 'scnr' - the input profile class */ - /* All conditions match the default. */ - break; - - case 0x6D6E7472: /* 'mntr' - a display device profile */ - /* On a monitor profile the N-Component LUT-based profiles require a - * BToA0 tag. - */ - if (LUT_based) - required_tags |= PNG_ICC_BToA0Tag; - - break; - - case 0x70727472: /* 'prtr' - an output device profile */ - /* For output profiles the three-component matrix based variant is - * not permitted, and all the various LUT-based tags are required. - * For LUT based profiles the colorantTableTag is only required for - * xCLR profiles, which have already been excluded. - */ - if (LUT_based) - required_tags |= PNG_ICC_ALL_LUT | PNG_ICC_gamutTag; - - else - permitted_tags &= ~PNG_ICC_REQUIRED_RGB_MATRIXTRC; - - break; - - case 0x6C696E6B: /* 'link' */ - case 0x61627374: /* 'abst' */ - /* Already excluded, but for reference: */ - required_tags |= PNG_ICC_AToB0Tag; - /* 'link' + PNG_ICC_profileSequenceDescTag */ - permitted_tags &= ~(PNG_ICC_ALL_TRC | PNG_ICC_ALL_LUT); - permitted_tags |= PNG_ICC_AToB0Tag; - break; - - case 0x73706163: /* 'spac' */ - /* The Matrix/TRC tags are not permitted on color-space profiles, - * and BToA0 must be present. - */ - required_tags |= PNG_ICC_AToB0Tag | PNG_ICC_BToA0Tag; - permitted_tags &= ~PNG_ICC_ALL_TRC; - break; - - case 0x6E6D636C: /* 'nmcl' */ - /* Not supported at all. */ - required_tags = PNG_ICC_REQUIRED_BASE; - permitted_tags = PNG_ICC_REQUIRED_BASE; - break; - - default: - /* To allow for future expansion just use the base input device - * settings. - */ - break; - } - - /* Then the test is that all the required tags are present and all the - * present tags are permitted. The warning message is somewhat difficult - * to decode, however occurences are extremely rare. Note that tags which - * were previously detected to be invalid won't be in the 'tags' - * information and will probably result in a second warning here. - */ - if ((required_tags & ~tags) != 0) - (void)png_icc_profile_error(png_ptr, NULL, name, - (required_tags & ~tags), "required tags missing"); - - if ((tags & ~permitted_tags) != 0) - (void)png_icc_profile_error(png_ptr, NULL, name, - (tags & ~permitted_tags), "unpermitted tags present"); } return 1; /* success, maybe with warnings */ @@ -3250,140 +2243,19 @@ png_compare_ICC_profile_with_sRGB(png_const_structrp png_ptr, } #endif +#ifdef PNG_sRGB_SUPPORTED void /* PRIVATE */ -png_icc_set_gAMA_and_cHRM(png_const_structrp png_ptr, - png_colorspacerp colorspace, png_const_charp name, png_const_bytep profile, - uLong adler) +png_icc_set_sRGB(png_const_structrp png_ptr, + png_colorspacerp colorspace, png_const_bytep profile, uLong adler) { -# ifdef PNG_sRGB_SUPPORTED - { - /* 1) Is this profile one of the known ICC sRGB profiles? If it is, just - * set the sRGB information. - */ - int set = png_compare_ICC_profile_with_sRGB(png_ptr, profile, adler); - - /* It is, simply set the profile intent. */ - if (set && png_colorspace_set_sRGB(png_ptr, colorspace, - (int)/*already checked*/png_get_uint_32(profile+64))) - { -# if PNG_LIBPNG_BUILD_BASE_TYPE < PNG_LIBPNG_BUILD_RC - /* In pre-RC builds run sRGB profiles through the profile checking - * code; this is because it is a useful validation of that code and - * because there is some evidence that not all sRGB profiles are - * created alike. Don't do this for the known-broken sRGB profiles, - * it just produces extra errors. (So this looks a little - * confusing; if set is '1', a believed-ok sRGB profile, continue - * checking, but if it '2' or more stop here. - */ - if (set >= 2) -# endif - return; - } - } -# else - PNG_UNUSED(adler) -# ifndef PNG_ICC_SUPPORTED - PNG_UNUSED(png_ptr) - PNG_UNUSED(colorspace) - PNG_UNUSED(profile) -# endif -# endif - -#ifdef PNG_ICC_SUPPORTED - /* 2) Attempt to extract the gAMA and cHRM information from non-sRGB - * profiles. Always set the rendering intent from the profile. - * - * Doing this requires a large body of code to parse an ICC profile and - * implement ICC color correction. This is because the profile tags that - * store colorant information are rarely, if ever, present in practice. - * It is therefore necessary to follow the algorithm described in section - * 10.4 (colorantTableType) and transform the RGB colorants through the - * full profile. - * - * Similarly to calculate a value for the PNG gAMA chunk it is necessary - * to process at least one gray level through the transform. - * - * The code to do this relies on a CMS implementation provided by the - * application. + /* Is this profile one of the known ICC sRGB profiles? If it is, just set + * the sRGB information. */ - if (png_ptr->cms_transform_fn != NULL) /* Else no support */ - { - png_uint_32 info = colorspace->icc_info; - png_alloc_size_t sample_bytes = 0/*error*/; - png_uint_16 pcsxyz[4/*samples*/ * 3/*components*/]; - - /* The input array; we want one sample to work out the gAMA chunk value - * and, for color images, three samples with the colorant endpoints. The - * sample used for gAMA calculation is discussed below. This gives the - * following byte array which works for either case (RGB or grayscale): - */ - static const png_byte samples[] = - { - GRAY_TEST, GRAY_TEST, GRAY_TEST, /* see png_icc_set_gAMA_from_Y */ - 255, 0, 0, /* red */ - 0, 255, 0, /* green */ - 0, 0, 255 /* blue */ - }; - - /* The cHRM chunk is only useful for an RGB image/profile, note that the - * check on 'set' causes pre-RC builds to do a spurious check on sRGB - * profiles, this validates the libpng algorithms because the known sRGB - * profiles are known to be correct (except for the 'broken' ones which - * are excluded by the 'set >= 2' test above.) - */ - if ((info & PNG_ICC_RGB) != 0) - { - if ((info & PNG_ICC_mediaWhitePointTag) == 0 /* Assume D50 */ || - png_icc_check_wtpt(png_ptr, name, profile, NULL)) - { - /* The mediaWhitePointTag is absent (an error, but we assume - * it was meant to be D50) or is sufficiently close to the PCS - * illuminant. This is the normal case. - * - * The code does not actually need the media white point, - * because it is the same as the PCS illuminant if we get to - * this point. - */ - sample_bytes = sizeof samples; /* i.e. all of them */ - } - - else - { - /* The mediaWhitePointTag has a major problem or doesn't match - * the PCS illuminant. A cHRM chunk cannot be generated for - * this profile, so just do gAMA: - */ - sample_bytes = 3; /* Just the gray value */ - } - } - - else - { - /* This is a grayscale image/profile, so just do gAMA */ - sample_bytes = 1; - } - - /* Now apply the transform. */ - if (png_ptr->cms_transform_fn(png_ptr, png_ptr->cms_data_ptr, samples, - sample_bytes, pcsxyz, sizeof pcsxyz, 0/*format*/, - PNG_sRGB_INTENT_RELATIVE)) - { - /* First handle the gAMA based on the 'Y' value in pcsxyz, it is either - * a grayscale 16-bit achromatic value with 1.0 represented as 65535 or - * a the Y part of a PCSXYZ value with 1.0 represented as 32768. - */ - png_uint_32 y = (sample_bytes != 1 ? pcsxyz[1] : pcsxyz[0]); - png_icc_set_gAMA_from_Y(png_ptr, colorspace, y, sample_bytes != 1); - - if (sample_bytes == sizeof samples) /* RGB samples too */ - png_icc_set_cHRM_from_endpoints(png_ptr, colorspace, name, - profile, pcsxyz+3/*skip the gamma sample*/); - } /* sample_bytes > 0 */ - } -#else - PNG_UNUSED(name) -#endif /* PNG_ICC_SUPPORTED */ + if (png_compare_ICC_profile_with_sRGB(png_ptr, profile, adler)) + (void)png_colorspace_set_sRGB(png_ptr, colorspace, + (int)/*already checked*/png_get_uint_32(profile+64)); } +#endif /* PNG_READ_sRGB_SUPPORTED */ int /* PRIVATE */ png_colorspace_set_ICC(png_const_structrp png_ptr, png_colorspacerp colorspace, @@ -3399,7 +2271,7 @@ png_colorspace_set_ICC(png_const_structrp png_ptr, png_colorspacerp colorspace, png_icc_check_tag_table(png_ptr, colorspace, name, profile_length, profile)) { - png_icc_set_gAMA_and_cHRM(png_ptr, colorspace, name, profile, 0); + png_icc_set_sRGB(png_ptr, colorspace, profile, 0); return 1; } diff --git a/png.h b/png.h index 897416b8f..b6f70e262 100644 --- a/png.h +++ b/png.h @@ -1,7 +1,7 @@ /* png.h - header file for PNG reference library * - * libpng version 1.6.0beta31 - October 26, 2012 + * libpng version 1.6.0beta31 - November 1, 2012 * Copyright (c) 1998-2012 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.6.0beta31 - October 26, 2012: Glenn + * libpng versions 0.97, January 1998, through 1.6.0beta31 - November 1, 2012: Glenn * See also "Contributing Authors", below. * * Note about libpng version numbers: @@ -198,7 +198,7 @@ * * This code is released under the libpng license. * - * libpng versions 1.2.6, August 15, 2004, through 1.6.0beta31, October 26, 2012, are + * libpng versions 1.2.6, August 15, 2004, through 1.6.0beta31, November 1, 2012, are * Copyright (c) 2004, 2006-2012 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: @@ -310,7 +310,7 @@ * Y2K compliance in libpng: * ========================= * - * October 26, 2012 + * November 1, 2012 * * Since the PNG Development group is an ad-hoc body, we can't make * an official declaration. @@ -378,7 +378,7 @@ /* Version information for png.h - this should match the version in png.c */ #define PNG_LIBPNG_VER_STRING "1.6.0beta31" #define PNG_HEADER_VERSION_STRING \ - " libpng version 1.6.0beta31 - October 26, 2012\n" + " libpng version 1.6.0beta31 - November 1, 2012\n" #define PNG_LIBPNG_VER_SONUM 16 #define PNG_LIBPNG_VER_DLLNUM 16 @@ -3204,90 +3204,6 @@ PNG_EXPORT(242, void, png_set_check_for_invalid_index, (png_structrp png_ptr, int allowed)); #endif -/******************************************************************************* - * CMS (Color Management System) SUPPORT - ******************************************************************************* - * - * The PNG file format supports embedding of ICC profiles, however libpng - * provides only limited support for handling these profiles. In particular - * libpng includes no support for using the profile to transform data into a - * different color space. If PNG_ICC_SUPPORTED is set, however, libpng allows - * an external CMS to be registered into the png_struct after it is created. - * This simply records a single callback function to transform samples between - * two color spaces. - */ -typedef struct png_cms_data *png_cms_datap, * PNG_RESTRICT png_cms_datarp; - /* An opaque type defined by a specific implementation to hold whatever data - * is required. The implementation is responsible for all storage management - * of this data. - */ - -typedef PNG_CALLBACK(png_uint_32, *png_cms_transform_ptr, - (png_const_structrp png_ptr, png_cms_datarp data_ptr, png_const_voidp input, - png_alloc_size_t input_bytes, png_voidp output, - png_alloc_size_t output_bytes, int format, int intent)); - /* Transform input[input_bytes] of samples to output[output_bytes]. The - * format of the input and output is given by 'format'. The function shall - * transform only so much input as there is space for in the output buffer. - * 'intent' is the ICC intent required for the transformation. - * - * The connection space data (which may be either the input or output) is - * always either 16-bit achromatic data (as described in Annex F.2 of the v4 - * ICC specification) for grayscale PNG files or 16-bit PCSXYZ data for RGB - * PNG files. Any alpha channel may be present in the connection space, in - * which case it is a 16-bit channel and the alpha value follows each sample. - * Samples are not pre-multiplied by the alpha. The connection space data - * is stored as an array of png_uint_16 values in the native representation - * of the machine. - * - * For transforms to the connection space the input is in the PNG format - * using either 8-bit or big-endian 16-bit components. 16-bit quantities use - * the PNG layout - big-endian in two bytes. - * - * By default a transform from the connection space will be to 8-bit sRGB - * (with an optional alpha value) or 8-bit gray encoded with the inverse of - * the sRGB transfer function. If png_set_cms_output is called, however, the - * transform may produce arbitrary output in a format potentially not handled - * by libpng. - * - * It is valid to register a CMS when writing a PNG image, however the CMS - * will only be used to generate appropriate values for cHRM and gAMA of the - * profile. - * - * The format parameter is made up of the following flags: - */ -#define PNG_CMS_FORMAT_FLAG_ALPHA 0x01 /* data has alpha channel */ -#define PNG_CMS_FORMAT_FLAG_16BIT 0x02 /* 16-bit image components else 8-bit */ -#define PNG_CMS_FORMAT_FLAG_PCS 0x04 /* input is PCS data, else image data */ - -#ifdef PNG_ICC_SUPPORTED -PNG_EXPORT(243, void, png_set_cms, (png_structrp png_ptr, - png_cms_datap cms_data_ptr, png_cms_transform_ptr cms_transform_function)); - /* Register the CMS transform function. The given pointer will be passed to - * every call to the function. - */ - -#ifdef PNG_READ_SUPPORTED -PNG_EXPORT(244, void, png_set_cms_output, (png_structrp png_ptr, - int bytes_per_pixel, int rendering_intent)); - /* Inform libpng that the transform function will write output requiring - * bytes_per_pixel bytes for each sample. The output need not be in any - * particular format, for example the transform could produce a print - * separation. libpng will provide a buffer equal in size to the row width - * of the image times the bytes_per_pixel value (and the application must - * provide this size buffer.) - * - * This also forces the CMS transform to be used even when it is apparently - * not necessary (e.g. for sRGB input data, or for PNG files with no ICC - * profile information and no sRGB data.) The intent overrides the default, - * which is perceptual. - */ -#endif -#endif -/******************************************************************************* - * END OF CMS (Color Management System) SUPPORT - ******************************************************************************/ - /* Maintainer: Put new public prototypes here ^, in libpng.3, and project * defs */ @@ -3297,7 +3213,7 @@ PNG_EXPORT(244, void, png_set_cms_output, (png_structrp png_ptr, * scripts/symbols.def as well. */ #ifdef PNG_EXPORT_LAST_ORDINAL - PNG_EXPORT_LAST_ORDINAL(244); + PNG_EXPORT_LAST_ORDINAL(242); #endif #ifdef __cplusplus diff --git a/pngpriv.h b/pngpriv.h index 6c46e47e0..1a5636389 100644 --- a/pngpriv.h +++ b/pngpriv.h @@ -1467,16 +1467,15 @@ PNG_INTERNAL_FUNCTION(int,png_icc_check_tag_table,(png_const_structrp png_ptr, png_colorspacerp colorspace, png_const_charp name, png_uint_32 profile_length, png_const_bytep profile /* header plus whole tag table */), PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_icc_set_gAMA_and_cHRM,( +#ifdef PNG_sRGB_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_icc_set_sRGB,( png_const_structrp png_ptr, png_colorspacerp colorspace, - png_const_charp name, png_const_bytep profile, uLong adler), PNG_EMPTY); + png_const_bytep profile, uLong adler), PNG_EMPTY); /* 'adler' is the Adler32 checksum of the uncompressed profile data. It may * be zero to indicate that it is not available. It is used, if provided, * as a fast check on the profile when checking to see if it is sRGB. - * The routine may not set gAMA or cHRM if there are problems in the profile, - * however none of these problems are fatal (the profile has already been - * checked.) */ +#endif #endif /* iCCP */ #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED diff --git a/pngrutil.c b/pngrutil.c index b76b8dd8a..bb4c1df75 100644 --- a/pngrutil.c +++ b/pngrutil.c @@ -1276,7 +1276,7 @@ png_handle_sRGB(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) return; } - png_colorspace_set_sRGB(png_ptr, &png_ptr->colorspace, intent); + (void)png_colorspace_set_sRGB(png_ptr, &png_ptr->colorspace, intent); png_colorspace_sync(png_ptr, info_ptr); } #endif /* PNG_READ_sRGB_SUPPORTED */ @@ -1447,13 +1447,12 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) png_crc_finish(png_ptr, length); finished = 1; - /* Set the gAMA and cHRM information, this - * checks for a known sRGB profile. The - * result is 0 on error. - */ - png_icc_set_gAMA_and_cHRM(png_ptr, - &png_ptr->colorspace, keyword, profile, - png_ptr->zstream.adler); +# ifdef PNG_sRGB_SUPPORTED + /* Check for a match against sRGB */ + png_icc_set_sRGB(png_ptr, + &png_ptr->colorspace, profile, + png_ptr->zstream.adler); +# endif /* Steal the profile for info_ptr. */ if (info_ptr != NULL) diff --git a/pngset.c b/pngset.c index 30a348e6a..85a1c14bc 100644 --- a/pngset.c +++ b/pngset.c @@ -578,7 +578,7 @@ png_set_sRGB(png_const_structrp png_ptr, png_inforp info_ptr, int srgb_intent) if (png_ptr == NULL || info_ptr == NULL) return; - png_colorspace_set_sRGB(png_ptr, &info_ptr->colorspace, srgb_intent); + (void)png_colorspace_set_sRGB(png_ptr, &info_ptr->colorspace, srgb_intent); png_colorspace_sync_info(png_ptr, info_ptr); } @@ -1549,35 +1549,4 @@ png_set_check_for_invalid_index(png_structrp png_ptr, int allowed) png_ptr->num_palette_max = -1; } #endif - -#ifdef PNG_ICC_SUPPORTED -void PNGAPI -png_set_cms(png_structrp png_ptr, png_cms_datap cms_data_ptr, - png_cms_transform_ptr cms_transform_function) -{ - png_ptr->cms_transform_fn = cms_transform_function; - png_ptr->cms_data_ptr = cms_data_ptr; -} - -#ifdef PNG_READ_SUPPORTED -void PNGAPI -png_set_cms_output(png_structrp png_ptr, int bytes_per_pixel, - int rendering_intent) -{ - if (png_ptr->mode & PNG_IS_READ_STRUCT) - { - png_ptr->cms_bytes_per_pixel = bytes_per_pixel; - png_ptr->cms_intent = rendering_intent; - - /* A CMS must be registered before calling this */ - if (png_ptr->cms_transform_fn == NULL) - png_app_error(png_ptr, "no CMS registered to transform output"); - } - - else - png_app_error(png_ptr, "attempt to do CMS tranform on write"); -} -#endif /* PNG_READ_SUPPORTED */ -#endif /* PNG_ICC_SUPPORTED */ - #endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/pngstruct.h b/pngstruct.h index ab1d789ad..3179165f1 100644 --- a/pngstruct.h +++ b/pngstruct.h @@ -119,7 +119,6 @@ typedef struct png_colorspace #ifdef PNG_COLORSPACE_SUPPORTED png_xy end_points_xy; /* End points as chromaticities */ png_XYZ end_points_XYZ; /* End points as CIE XYZ colorant values */ - png_uint_32 icc_info; /* Record of information from the colorspace */ png_uint_16 rendering_intent; /* Rendering intent of a profile */ #endif @@ -129,74 +128,6 @@ typedef struct png_colorspace typedef const png_colorspace * PNG_RESTRICT png_const_colorspacerp; -/* ICC specific flags for the 'icc_info' field. */ -/* The first four bits are for information defined from the profile, the - * remainder of the bits indicate the presence of specific tags. The #define - * names are derived from the tag name in the ICC 2010 (v4) specification. - */ -# define PNG_ICC_PCSXYZ 0x00000001U /* PCSXYS, else PCSLAB */ -# define PNG_ICC_RGB 0x00000002U /* 'RGB ', else 'GRAY ' */ - /* 0x00000004U reserved */ - /* 0x00000008U reserved */ - - /* A utility to return the number of channels on the A side of the transform - * given an info value (can be optimized). - */ -# define PNG_ICC_CHANNELS(info) ((((info)&PNG_ICC_RGB)?2U:0U)+1U) - - /* The profile description and copyright must be present in all valid ICC - * profiles, however libpng does not use them so absence is just reported as - * a warning. The media white point should be present too, but if it isn't - * all we lose is the ability to know if it differs from the adopted white - * (i.e. the information that the device maxima are actually colored; - * a non-white substrate for a printer, or an uncorrected scan for example.) - * The chromaticAdaptationTag tells us that the adopted white of the original - * differs from the PCS adopted white (which is identical to the PCS - * illuminant and should always be D50). - */ -# define PNG_ICC_profileDescriptionTag 0x00000010U /* required */ -# define PNG_ICC_copyrightTag 0x00000020U /* required */ -# define PNG_ICC_mediaWhitePointTag 0x00000040U /* required */ -# define PNG_ICC_chromaticAdaptationTag 0x00000080U /* optional */ - - /* Tags that are required in all profiles (except DeviceLink): */ -# define PNG_ICC_REQUIRED_BASE 0x00000070U - - /* Other tags have to appear in specific profiles. In general a profile must - * either contain appropriate TRC and (for RGB profiles) matrix tags *or* it - * must contain AToB0 and BToA0 - the CLUT based transforms to an absolute - * colorimetric PCS. In the TRC case the PCS encoding must be PCSXYZ. - */ -# define PNG_ICC_redMatrixColumnTag 0x00000100U -# define PNG_ICC_greenMatrixColumnTag 0x00000200U -# define PNG_ICC_blueMatrixColumnTag 0x00000400U - /* 0x00000800U reserved */ -# define PNG_ICC_redTRCTag 0x00001000U -# define PNG_ICC_greenTRCTag 0x00002000U -# define PNG_ICC_blueTRCTag 0x00004000U -# define PNG_ICC_grayTRCTag 0x00008000U -# define PNG_ICC_REQUIRED_RGB_MATRIXTRC 0x00007700U /* Required for RGB TRC */ -# define PNG_ICC_ALL_TRC 0x0000f000U /* Includes all TRCTags */ -# define PNG_ICC_REQUIRED_MATRIX 0x00000700U /* All MatrixColumnTags */ - -# define PNG_ICC_AToB0Tag 0x00010000U -# define PNG_ICC_BToA0Tag 0x00020000U -# define PNG_ICC_AToB1Tag 0x00040000U -# define PNG_ICC_BToA1Tag 0x00080000U -# define PNG_ICC_AToB2Tag 0x00100000U -# define PNG_ICC_BToA2Tag 0x00200000U -# define PNG_ICC_AToB_TAGS 0x00050000U /* Just AToB0 and AToB1 */ -# define PNG_ICC_ALL_LUT 0x003f0000U - /* 0x00400000U reserved */ - /* 0x00800000U reserved */ - - /* The ICC profile specification allows for shortcuts in the cHRM calculation - * via the colorant table (clrt) or the chromaticity tag (chrm). - */ -# define PNG_ICC_chromaticityTag 0x01000000U -# define PNG_ICC_colorantTableTag 0x02000000U -# define PNG_ICC_gamutTag 0x04000000U - /* General flags for the 'flags' field */ #define PNG_COLORSPACE_HAVE_GAMMA 0x0001 #define PNG_COLORSPACE_HAVE_ENDPOINTS 0x0002 @@ -548,17 +479,5 @@ struct png_struct_def png_colorspace colorspace; #endif #endif - -#ifdef PNG_ICC_SUPPORTED - /* Full ICC support requires an external CMS be registered in the png_struct - * after it is created. The registration stores this information. - */ - png_cms_transform_ptr cms_transform_fn; - png_cms_datap cms_data_ptr; -#ifdef PNG_READ_SUPPORTED - int cms_bytes_per_pixel; /* non-standard output size */ - int cms_intent; /* for non-standard output */ -#endif -#endif /* PNG_ICC_SUPPORTED */ }; #endif /* PNGSTRUCT_H */ diff --git a/scripts/pnglibconf.dfa b/scripts/pnglibconf.dfa index e42f450c5..b66ca80e1 100644 --- a/scripts/pnglibconf.dfa +++ b/scripts/pnglibconf.dfa @@ -151,7 +151,7 @@ logunsupported = 1 # These are currently experimental features; define them if you want (NOTE: # experimental options must be disabled before they are defined in this file!) -option ICC disabled +# NONE # Note that PNG_USR_CONFIG only has an effect when building # pnglibconf.h @@ -318,20 +318,6 @@ setting USER_CHUNK_MALLOC_MAX option SAFE_LIMITS enables USER_LIMITS disabled = SAFE_LIMITS SAFE_LIMITS -# ICC profile support; basic ICC profile support is enabled if iCCP chunk read -# or write is enabled. The application must perform all iCCP profile handling -# itself. If full support is enabled with the option below libpng will attempt -# to do more processing using the profile data itself, this includes setting -# appropriate values for cHRM and gAMA chunks if not present in the stream. -# -# ICC profile support is not build in to core libpng because of the size of the -# code required; an external ICC implementation must be passed to libpng to -# enable it. -# -# WARNING: this option is CURRENTLY UNTESTED because a test CMS implementation -# has not yet been written, as a result it is disabled in current beta builds. -option ICC requires iCCP enables SAVE_INT_32 - # All of the following options relate to code capabilities for # processing image data before creating a PNG or after reading one. # You can remove these capabilities safely and still be PNG diff --git a/scripts/pnglibconf.h.prebuilt b/scripts/pnglibconf.h.prebuilt index 59cc1ce95..759e16b2b 100644 --- a/scripts/pnglibconf.h.prebuilt +++ b/scripts/pnglibconf.h.prebuilt @@ -3,7 +3,7 @@ /* pnglibconf.h - library build configuration */ -/* Libpng 1.6.0beta31 - October 26, 2012 */ +/* Libpng 1.6.0beta31 - November 1, 2012 */ /* Copyright (c) 1998-2012 Glenn Randers-Pehrson */ @@ -63,7 +63,6 @@ #define PNG_HANDLE_AS_UNKNOWN_SUPPORTED #define PNG_hIST_SUPPORTED #define PNG_iCCP_SUPPORTED -/*#undef PNG_ICC_SUPPORTED*/ #define PNG_INCH_CONVERSIONS_SUPPORTED #define PNG_INFO_IMAGE_SUPPORTED #define PNG_IO_STATE_SUPPORTED diff --git a/scripts/symbols.def b/scripts/symbols.def index 92c0a703c..8f8311848 100644 --- a/scripts/symbols.def +++ b/scripts/symbols.def @@ -247,5 +247,3 @@ EXPORTS png_image_write_to_stdio @240 png_convert_to_rfc1123_buffer @241 png_set_check_for_invalid_index @242 - png_set_cms @243 - png_set_cms_output @244 diff --git a/scripts/symbols.dfn b/scripts/symbols.dfn index 7d0d3d050..d790929e7 100644 --- a/scripts/symbols.dfn +++ b/scripts/symbols.dfn @@ -42,7 +42,6 @@ #define PNG_READ_BIG_ENDIAN_SUPPORTED /* should do nothing! */ #define PNG_INCH_CONVERSIONS_SUPPORTED #define PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED -#define PNG_ICC_SUPPORTED /* currently disabled */ #undef PNG_H #include "../png.h"