diff --git a/png.h b/png.h index 644048557..7f162ba0b 100644 --- a/png.h +++ b/png.h @@ -1100,8 +1100,10 @@ PNG_EXPORT(34, png_byte, png_get_rgb_to_gray_status, (png_const_structp png_ptr)); #endif +#ifdef PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED PNG_EXPORT(35, void, png_build_grayscale_palette, (int bit_depth, png_colorp palette)); +#endif #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED PNG_EXPORT(36, void, png_set_strip_alpha, (png_structp png_ptr)); diff --git a/pngpread.c b/pngpread.c index d042eff7d..a50292a76 100644 --- a/pngpread.c +++ b/pngpread.c @@ -1026,8 +1026,10 @@ png_push_process_row(png_structp png_ptr) png_memcpy(png_ptr->prev_row, png_ptr->row_buf, png_ptr->rowbytes + 1); +#ifdef PNG_READ_TRANSFORMS_SUPPORTED if (png_ptr->transformations) png_do_read_transformations(png_ptr); +#endif #ifdef PNG_READ_INTERLACING_SUPPORTED /* Blow up interlaced rows to full size */ diff --git a/pngpriv.h b/pngpriv.h index 82fbac8a3..3486c13e2 100644 --- a/pngpriv.h +++ b/pngpriv.h @@ -743,9 +743,12 @@ PNG_EXTERN void png_read_finish_row PNGARG((png_structp png_ptr)); /* Initialize the row buffers, etc. */ PNG_EXTERN void png_read_start_row PNGARG((png_structp png_ptr)); + +#ifdef PNG_READ_TRANSFORMS_SUPPORTED /* Optional call to update the users info structure */ PNG_EXTERN void png_read_transform_info PNGARG((png_structp png_ptr, png_infop info_ptr)); +#endif /* These are the functions that do the transformations */ #ifdef PNG_READ_FILLER_SUPPORTED @@ -849,25 +852,13 @@ PNG_EXTERN void png_do_shift PNGARG((png_row_infop row_info, #endif #ifdef PNG_READ_BACKGROUND_SUPPORTED -# ifdef PNG_READ_GAMMA_SUPPORTED PNG_EXTERN void png_do_background PNGARG((png_row_infop row_info, - png_bytep row, png_const_color_16p trans_color, - png_const_color_16p background, png_const_color_16p background_1, - png_const_bytep gamma_table, png_const_bytep gamma_from_1, - png_const_bytep gamma_to_1, png_const_uint_16pp gamma_16, - png_const_uint_16pp gamma_16_from_1, png_const_uint_16pp gamma_16_to_1, - int gamma_shift)); -# else -PNG_EXTERN void png_do_background PNGARG((png_row_infop row_info, - png_bytep row, png_const_color_16p trans_color, - png_const_color_16p background)); -# endif + png_bytep row, png_structp png_ptr)); #endif #ifdef PNG_READ_GAMMA_SUPPORTED PNG_EXTERN void png_do_gamma PNGARG((png_row_infop row_info, - png_bytep row, png_const_bytep gamma_table, - png_const_uint_16pp gamma_16_table, int gamma_shift)); + png_bytep row, png_structp png_ptr)); #endif #ifdef PNG_READ_EXPAND_SUPPORTED @@ -987,10 +978,16 @@ PNG_EXTERN void png_check_chunk_name PNGARG((png_structp png_ptr, png_const_bytep chunk_name)); /* Handle the transformations for reading and writing */ +#ifdef PNG_READ_TRANSFORMS_SUPPORTED PNG_EXTERN void png_do_read_transformations PNGARG((png_structp png_ptr)); +#endif +#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED PNG_EXTERN void png_do_write_transformations PNGARG((png_structp png_ptr)); +#endif +#ifdef PNG_READ_TRANSFORMS_SUPPORTED PNG_EXTERN void png_init_read_transformations PNGARG((png_structp png_ptr)); +#endif #ifdef PNG_PROGRESSIVE_READ_SUPPORTED PNG_EXTERN void png_push_read_chunk PNGARG((png_structp png_ptr, diff --git a/pngread.c b/pngread.c index aa84001c4..07eb7628f 100644 --- a/pngread.c +++ b/pngread.c @@ -457,7 +457,11 @@ png_read_update_info(png_structp png_ptr, png_infop info_ptr) "Ignoring extra png_read_update_info() call;" " row buffer not reallocated"); +#ifdef PNG_READ_TRANSFORMS_SUPPORTED png_read_transform_info(png_ptr, info_ptr); +#else + PNG_UNUSED(info_ptr) +#endif } #ifdef PNG_SEQUENTIAL_READ_SUPPORTED @@ -704,8 +708,10 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row) #endif +#ifdef PNG_READ_TRANSFORMS_SUPPORTED if (png_ptr->transformations) png_do_read_transformations(png_ptr); +#endif #ifdef PNG_READ_INTERLACING_SUPPORTED /* Blow up interlaced rows to full size */ diff --git a/pngrtran.c b/pngrtran.c index ab78290d2..76892aed7 100644 --- a/pngrtran.c +++ b/pngrtran.c @@ -137,7 +137,6 @@ png_set_strip_16(png_structp png_ptr) return; png_ptr->transformations |= PNG_16_TO_8; - png_ptr->transformations &= ~PNG_EXPAND_16; } #endif @@ -700,8 +699,6 @@ png_set_expand_16(png_structp png_ptr) return; png_ptr->transformations |= (PNG_EXPAND_16 | PNG_EXPAND | PNG_EXPAND_tRNS); - png_ptr->transformations &= ~PNG_16_TO_8; - png_ptr->flags &= ~PNG_FLAG_ROW_INIT; } #endif @@ -827,6 +824,7 @@ png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr } #endif +#ifdef PNG_READ_TRANSFORMS_SUPPORTED /* Initialize everything needed for the read. This includes modifying * the palette. */ @@ -1559,16 +1557,7 @@ png_do_read_transformations(png_structp png_ptr) if ((png_ptr->transformations & PNG_BACKGROUND) && ((png_ptr->num_trans != 0) || (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) - png_do_background(&(png_ptr->row_info), png_ptr->row_buf + 1, - &(png_ptr->trans_color), &(png_ptr->background) -#ifdef PNG_READ_GAMMA_SUPPORTED - , &(png_ptr->background_1), - png_ptr->gamma_table, png_ptr->gamma_from_1, - png_ptr->gamma_to_1, png_ptr->gamma_16_table, - png_ptr->gamma_16_from_1, png_ptr->gamma_16_to_1, - png_ptr->gamma_shift -#endif - ); + png_do_background(&(png_ptr->row_info), png_ptr->row_buf + 1, png_ptr); #endif #ifdef PNG_READ_GAMMA_SUPPORTED @@ -1579,9 +1568,7 @@ png_do_read_transformations(png_structp png_ptr) (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) && #endif (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)) - png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1, - png_ptr->gamma_table, png_ptr->gamma_16_table, - png_ptr->gamma_shift); + png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1, png_ptr); #endif #ifdef PNG_READ_16_TO_8_SUPPORTED @@ -2721,11 +2708,13 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row) return rgb_error; } #endif +#endif /* PNG_READ_TRANSFORMS_SUPPORTED */ +#ifdef PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED /* Build a grayscale palette. Palette is assumed to be 1 << bit_depth * large of png_color. This lets grayscale images be treated as * paletted. Most useful for gamma correction and simplification - * of code. + * of code. This API is not used internally. */ void PNGAPI png_build_grayscale_palette(int bit_depth, png_colorp palette) @@ -2775,24 +2764,28 @@ png_build_grayscale_palette(int bit_depth, png_colorp palette) palette[i].blue = (png_byte)v; } } +#endif +#ifdef PNG_READ_TRANSFORMS_SUPPORTED #ifdef PNG_READ_BACKGROUND_SUPPORTED /* Replace any alpha or transparency with the supplied background color. * "background" is already in the screen gamma, while "background_1" is * at a gamma of 1.0. Paletted files have already been taken care of. */ void /* PRIVATE */ -png_do_background(png_row_infop row_info, png_bytep row, - png_const_color_16p trans_color, png_const_color_16p background -#ifdef PNG_READ_GAMMA_SUPPORTED - , png_const_color_16p background_1, png_const_bytep gamma_table, - png_const_bytep gamma_from_1, png_const_bytep gamma_to_1, - png_const_uint_16pp gamma_16, png_const_uint_16pp gamma_16_from_1, - png_const_uint_16pp gamma_16_to_1, int gamma_shift -#endif - ) +png_do_background(png_row_infop row_info, png_bytep row, png_structp png_ptr) { +#ifdef PNG_READ_GAMMA_SUPPORTED + png_const_bytep gamma_table = png_ptr->gamma_table; + png_const_bytep gamma_from_1 = png_ptr->gamma_from_1; + png_const_bytep gamma_to_1 = png_ptr->gamma_to_1; + png_const_uint_16pp gamma_16 = png_ptr->gamma_16_table; + png_const_uint_16pp gamma_16_from_1 = png_ptr->gamma_16_from_1; + png_const_uint_16pp gamma_16_to_1 = png_ptr->gamma_16_to_1; + int gamma_shift = png_ptr->gamma_shift; +#endif + png_bytep sp, dp; png_uint_32 i; png_uint_32 row_width = row_info->width; @@ -2800,9 +2793,8 @@ png_do_background(png_row_infop row_info, png_bytep row, png_debug(1, "in png_do_background"); - if (background != NULL && - (!(row_info->color_type & PNG_COLOR_MASK_ALPHA) || - (row_info->color_type != PNG_COLOR_TYPE_PALETTE && trans_color))) + if (!(row_info->color_type & PNG_COLOR_MASK_ALPHA) || + row_info->color_type != PNG_COLOR_TYPE_PALETTE) { switch (row_info->color_type) { @@ -2817,10 +2809,10 @@ png_do_background(png_row_infop row_info, png_bytep row, for (i = 0; i < row_width; i++) { if ((png_uint_16)((*sp >> shift) & 0x01) - == trans_color->gray) + == png_ptr->trans_color.gray) { *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff); - *sp |= (png_byte)(background->gray << shift); + *sp |= (png_byte)(png_ptr->background.gray << shift); } if (!shift) @@ -2845,10 +2837,10 @@ png_do_background(png_row_infop row_info, png_bytep row, for (i = 0; i < row_width; i++) { if ((png_uint_16)((*sp >> shift) & 0x03) - == trans_color->gray) + == png_ptr->trans_color.gray) { *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); - *sp |= (png_byte)(background->gray << shift); + *sp |= (png_byte)(png_ptr->background.gray << shift); } else @@ -2879,10 +2871,10 @@ png_do_background(png_row_infop row_info, png_bytep row, for (i = 0; i < row_width; i++) { if ((png_uint_16)((*sp >> shift) & 0x03) - == trans_color->gray) + == png_ptr->trans_color.gray) { *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); - *sp |= (png_byte)(background->gray << shift); + *sp |= (png_byte)(png_ptr->background.gray << shift); } if (!shift) @@ -2908,10 +2900,10 @@ png_do_background(png_row_infop row_info, png_bytep row, for (i = 0; i < row_width; i++) { if ((png_uint_16)((*sp >> shift) & 0x0f) - == trans_color->gray) + == png_ptr->trans_color.gray) { *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); - *sp |= (png_byte)(background->gray << shift); + *sp |= (png_byte)(png_ptr->background.gray << shift); } else @@ -2942,10 +2934,10 @@ png_do_background(png_row_infop row_info, png_bytep row, for (i = 0; i < row_width; i++) { if ((png_uint_16)((*sp >> shift) & 0x0f) - == trans_color->gray) + == png_ptr->trans_color.gray) { *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); - *sp |= (png_byte)(background->gray << shift); + *sp |= (png_byte)(png_ptr->background.gray << shift); } if (!shift) @@ -2969,8 +2961,8 @@ png_do_background(png_row_infop row_info, png_bytep row, sp = row; for (i = 0; i < row_width; i++, sp++) { - if (*sp == trans_color->gray) - *sp = (png_byte)background->gray; + if (*sp == png_ptr->trans_color.gray) + *sp = (png_byte)png_ptr->background.gray; else *sp = gamma_table[*sp]; @@ -2982,8 +2974,8 @@ png_do_background(png_row_infop row_info, png_bytep row, sp = row; for (i = 0; i < row_width; i++, sp++) { - if (*sp == trans_color->gray) - *sp = (png_byte)background->gray; + if (*sp == png_ptr->trans_color.gray) + *sp = (png_byte)png_ptr->background.gray; } } break; @@ -3001,11 +2993,11 @@ png_do_background(png_row_infop row_info, png_bytep row, v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - if (v == trans_color->gray) + if (v == png_ptr->trans_color.gray) { /* Background is already in screen gamma */ - *sp = (png_byte)((background->gray >> 8) & 0xff); - *(sp + 1) = (png_byte)(background->gray & 0xff); + *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff); } else @@ -3026,10 +3018,10 @@ png_do_background(png_row_infop row_info, png_bytep row, v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - if (v == trans_color->gray) + if (v == png_ptr->trans_color.gray) { - *sp = (png_byte)((background->gray >> 8) & 0xff); - *(sp + 1) = (png_byte)(background->gray & 0xff); + *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff); } } } @@ -3052,13 +3044,13 @@ png_do_background(png_row_infop row_info, png_bytep row, sp = row; for (i = 0; i < row_width; i++, sp += 3) { - if (*sp == trans_color->red && - *(sp + 1) == trans_color->green && - *(sp + 2) == trans_color->blue) + if (*sp == png_ptr->trans_color.red && + *(sp + 1) == png_ptr->trans_color.green && + *(sp + 2) == png_ptr->trans_color.blue) { - *sp = (png_byte)background->red; - *(sp + 1) = (png_byte)background->green; - *(sp + 2) = (png_byte)background->blue; + *sp = (png_byte)png_ptr->background.red; + *(sp + 1) = (png_byte)png_ptr->background.green; + *(sp + 2) = (png_byte)png_ptr->background.blue; } else @@ -3075,13 +3067,13 @@ png_do_background(png_row_infop row_info, png_bytep row, sp = row; for (i = 0; i < row_width; i++, sp += 3) { - if (*sp == trans_color->red && - *(sp + 1) == trans_color->green && - *(sp + 2) == trans_color->blue) + if (*sp == png_ptr->trans_color.red && + *(sp + 1) == png_ptr->trans_color.green && + *(sp + 2) == png_ptr->trans_color.blue) { - *sp = (png_byte)background->red; - *(sp + 1) = (png_byte)background->green; - *(sp + 2) = (png_byte)background->blue; + *sp = (png_byte)png_ptr->background.red; + *(sp + 1) = (png_byte)png_ptr->background.green; + *(sp + 2) = (png_byte)png_ptr->background.blue; } } } @@ -3102,16 +3094,17 @@ png_do_background(png_row_infop row_info, png_bytep row, png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) + *(sp + 5)); - if (r == trans_color->red && g == trans_color->green && - b == trans_color->blue) + if (r == png_ptr->trans_color.red && + g == png_ptr->trans_color.green && + b == png_ptr->trans_color.blue) { /* Background is already in screen gamma */ - *sp = (png_byte)((background->red >> 8) & 0xff); - *(sp + 1) = (png_byte)(background->red & 0xff); - *(sp + 2) = (png_byte)((background->green >> 8) & 0xff); - *(sp + 3) = (png_byte)(background->green & 0xff); - *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff); - *(sp + 5) = (png_byte)(background->blue & 0xff); + *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); + *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff); + *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff); + *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff); + *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); } else @@ -3145,15 +3138,16 @@ png_do_background(png_row_infop row_info, png_bytep row, png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) + *(sp + 5)); - if (r == trans_color->red && g == trans_color->green && - b == trans_color->blue) + if (r == png_ptr->trans_color.red && + g == png_ptr->trans_color.green && + b == png_ptr->trans_color.blue) { - *sp = (png_byte)((background->red >> 8) & 0xff); - *(sp + 1) = (png_byte)(background->red & 0xff); - *(sp + 2) = (png_byte)((background->green >> 8) & 0xff); - *(sp + 3) = (png_byte)(background->green & 0xff); - *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff); - *(sp + 5) = (png_byte)(background->blue & 0xff); + *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); + *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff); + *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff); + *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff); + *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); } } } @@ -3181,7 +3175,7 @@ png_do_background(png_row_infop row_info, png_bytep row, else if (a == 0) { /* Background is already in screen gamma */ - *dp = (png_byte)background->gray; + *dp = (png_byte)png_ptr->background.gray; } else @@ -3189,7 +3183,7 @@ png_do_background(png_row_infop row_info, png_bytep row, png_byte v, w; v = gamma_to_1[*sp]; - png_composite(w, v, a, background_1->gray); + png_composite(w, v, a, png_ptr->background_1.gray); *dp = gamma_from_1[w]; } } @@ -3208,13 +3202,13 @@ png_do_background(png_row_infop row_info, png_bytep row, #ifdef PNG_READ_GAMMA_SUPPORTED else if (a == 0) - *dp = (png_byte)background->gray; + *dp = (png_byte)png_ptr->background.gray; else - png_composite(*dp, *sp, a, background_1->gray); + png_composite(*dp, *sp, a, png_ptr->background_1.gray); #else - *dp = (png_byte)background->gray; + *dp = (png_byte)png_ptr->background.gray; #endif } } @@ -3248,8 +3242,8 @@ png_do_background(png_row_infop row_info, png_bytep row, #endif { /* Background is already in screen gamma */ - *dp = (png_byte)((background->gray >> 8) & 0xff); - *(dp + 1) = (png_byte)(background->gray & 0xff); + *dp = (png_byte)((png_ptr->background.gray >> 8) & 0xff); + *(dp + 1) = (png_byte)(png_ptr->background.gray & 0xff); } #ifdef PNG_READ_GAMMA_SUPPORTED @@ -3258,7 +3252,7 @@ png_do_background(png_row_infop row_info, png_bytep row, png_uint_16 g, v, w; g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; - png_composite_16(v, g, a, background_1->gray); + png_composite_16(v, g, a, png_ptr->background_1.gray); w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8]; *dp = (png_byte)((w >> 8) & 0xff); *(dp + 1) = (png_byte)(w & 0xff); @@ -3285,8 +3279,8 @@ png_do_background(png_row_infop row_info, png_bytep row, else #endif { - *dp = (png_byte)((background->gray >> 8) & 0xff); - *(dp + 1) = (png_byte)(background->gray & 0xff); + *dp = (png_byte)((png_ptr->background.gray >> 8) & 0xff); + *(dp + 1) = (png_byte)(png_ptr->background.gray & 0xff); } #ifdef PNG_READ_GAMMA_SUPPORTED @@ -3295,7 +3289,7 @@ png_do_background(png_row_infop row_info, png_bytep row, png_uint_16 g, v; g = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - png_composite_16(v, g, a, background_1->gray); + png_composite_16(v, g, a, png_ptr->background_1.gray); *dp = (png_byte)((v >> 8) & 0xff); *(dp + 1) = (png_byte)(v & 0xff); } @@ -3330,9 +3324,9 @@ png_do_background(png_row_infop row_info, png_bytep row, else if (a == 0) { /* Background is already in screen gamma */ - *dp = (png_byte)background->red; - *(dp + 1) = (png_byte)background->green; - *(dp + 2) = (png_byte)background->blue; + *dp = (png_byte)png_ptr->background.red; + *(dp + 1) = (png_byte)png_ptr->background.green; + *(dp + 2) = (png_byte)png_ptr->background.blue; } else @@ -3340,15 +3334,15 @@ png_do_background(png_row_infop row_info, png_bytep row, png_byte v, w; v = gamma_to_1[*sp]; - png_composite(w, v, a, background_1->red); + png_composite(w, v, a, png_ptr->background_1.red); *dp = gamma_from_1[w]; v = gamma_to_1[*(sp + 1)]; - png_composite(w, v, a, background_1->green); + png_composite(w, v, a, png_ptr->background_1.green); *(dp + 1) = gamma_from_1[w]; v = gamma_to_1[*(sp + 2)]; - png_composite(w, v, a, background_1->blue); + png_composite(w, v, a, png_ptr->background_1.blue); *(dp + 2) = gamma_from_1[w]; } } @@ -3371,20 +3365,20 @@ png_do_background(png_row_infop row_info, png_bytep row, else if (a == 0) { - *dp = (png_byte)background->red; - *(dp + 1) = (png_byte)background->green; - *(dp + 2) = (png_byte)background->blue; + *dp = (png_byte)png_ptr->background.red; + *(dp + 1) = (png_byte)png_ptr->background.green; + *(dp + 2) = (png_byte)png_ptr->background.blue; } else { - png_composite(*dp, *sp, a, background->red); + png_composite(*dp, *sp, a, png_ptr->background.red); png_composite(*(dp + 1), *(sp + 1), a, - background->green); + png_ptr->background.green); png_composite(*(dp + 2), *(sp + 2), a, - background->blue); + png_ptr->background.blue); } } } @@ -3422,12 +3416,12 @@ png_do_background(png_row_infop row_info, png_bytep row, else if (a == 0) { /* Background is already in screen gamma */ - *dp = (png_byte)((background->red >> 8) & 0xff); - *(dp + 1) = (png_byte)(background->red & 0xff); - *(dp + 2) = (png_byte)((background->green >> 8) & 0xff); - *(dp + 3) = (png_byte)(background->green & 0xff); - *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff); - *(dp + 5) = (png_byte)(background->blue & 0xff); + *dp = (png_byte)((png_ptr->background.red >> 8) & 0xff); + *(dp + 1) = (png_byte)(png_ptr->background.red & 0xff); + *(dp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff); + *(dp + 3) = (png_byte)(png_ptr->background.green & 0xff); + *(dp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff); + *(dp + 5) = (png_byte)(png_ptr->background.blue & 0xff); } else @@ -3435,21 +3429,21 @@ png_do_background(png_row_infop row_info, png_bytep row, png_uint_16 v, w, x; v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; - png_composite_16(w, v, a, background_1->red); + png_composite_16(w, v, a, png_ptr->background_1.red); x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8]; *dp = (png_byte)((x >> 8) & 0xff); *(dp + 1) = (png_byte)(x & 0xff); v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)]; - png_composite_16(w, v, a, background_1->green); + png_composite_16(w, v, a, png_ptr->background_1.green); x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8]; *(dp + 2) = (png_byte)((x >> 8) & 0xff); *(dp + 3) = (png_byte)(x & 0xff); v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)]; - png_composite_16(w, v, a, background_1->blue); + png_composite_16(w, v, a, png_ptr->background_1.blue); x = gamma_16_from_1[(w & 0xff) >> gamma_shift][w >> 8]; *(dp + 4) = (png_byte)((x >> 8) & 0xff); @@ -3475,12 +3469,12 @@ png_do_background(png_row_infop row_info, png_bytep row, else if (a == 0) { - *dp = (png_byte)((background->red >> 8) & 0xff); - *(dp + 1) = (png_byte)(background->red & 0xff); - *(dp + 2) = (png_byte)((background->green >> 8) & 0xff); - *(dp + 3) = (png_byte)(background->green & 0xff); - *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff); - *(dp + 5) = (png_byte)(background->blue & 0xff); + *dp = (png_byte)((png_ptr->background.red >> 8) & 0xff); + *(dp + 1) = (png_byte)(png_ptr->background.red & 0xff); + *(dp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff); + *(dp + 3) = (png_byte)(png_ptr->background.green & 0xff); + *(dp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff); + *(dp + 5) = (png_byte)(png_ptr->background.blue & 0xff); } else @@ -3493,15 +3487,15 @@ png_do_background(png_row_infop row_info, png_bytep row, png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) + *(sp + 5)); - png_composite_16(v, r, a, background->red); + png_composite_16(v, r, a, png_ptr->background.red); *dp = (png_byte)((v >> 8) & 0xff); *(dp + 1) = (png_byte)(v & 0xff); - png_composite_16(v, g, a, background->green); + png_composite_16(v, g, a, png_ptr->background.green); *(dp + 2) = (png_byte)((v >> 8) & 0xff); *(dp + 3) = (png_byte)(v & 0xff); - png_composite_16(v, b, a, background->blue); + png_composite_16(v, b, a, png_ptr->background.blue); *(dp + 4) = (png_byte)((v >> 8) & 0xff); *(dp + 5) = (png_byte)(v & 0xff); } @@ -3536,10 +3530,12 @@ png_do_background(png_row_infop row_info, png_bytep row, * build_gamma_table(). */ void /* PRIVATE */ -png_do_gamma(png_row_infop row_info, png_bytep row, - png_const_bytep gamma_table, png_const_uint_16pp gamma_16_table, - int gamma_shift) +png_do_gamma(png_row_infop row_info, png_bytep row, png_structp png_ptr) { + png_const_bytep gamma_table = png_ptr->gamma_table; + png_const_uint_16pp gamma_16_table = png_ptr->gamma_16_table; + int gamma_shift = png_ptr->gamma_shift; + png_bytep sp; png_uint_32 i; png_uint_32 row_width=row_info->width; @@ -4236,6 +4232,7 @@ png_do_quantize(png_row_infop row_info, png_bytep row, } } #endif /* PNG_READ_QUANTIZE_SUPPORTED */ +#endif /* PNG_READ_TRANSFORMS_SUPPORTED */ #ifdef PNG_MNG_FEATURES_SUPPORTED /* Undoes intrapixel differencing */ diff --git a/pngrutil.c b/pngrutil.c index 5b0ebce84..f73021b3c 100644 --- a/pngrutil.c +++ b/pngrutil.c @@ -3397,7 +3397,9 @@ png_read_start_row(png_structp png_ptr) png_debug(1, "in png_read_start_row"); png_ptr->zstream.avail_in = 0; +#ifdef PNG_READ_TRANSFORMS_SUPPORTED png_init_read_transformations(png_ptr); +#endif #ifdef PNG_READ_INTERLACING_SUPPORTED if (png_ptr->interlaced) { diff --git a/pngvalid.c b/pngvalid.c index 54c55dd4b..116184b40 100644 --- a/pngvalid.c +++ b/pngvalid.c @@ -108,6 +108,7 @@ static size_t safecatn(char *buffer, size_t bufsize, size_t pos, int n) return safecat(buffer, bufsize, pos, number); } +#ifdef PNG_READ_TRANSFORMS_SUPPORTED static size_t safecatd(char *buffer, size_t bufsize, size_t pos, double d, int precision) { @@ -115,6 +116,7 @@ static size_t safecatd(char *buffer, size_t bufsize, size_t pos, double d, sprintf(number, "%.*f", precision, d); return safecat(buffer, bufsize, pos, number); } +#endif static PNG_CONST char invalid[] = "invalid"; static PNG_CONST char sep[] = ": "; @@ -225,6 +227,7 @@ standard_name_from_id(char *buffer, size_t bufsize, size_t pos, png_uint_32 id) # define READ_BDHI 3 #endif +#ifdef PNG_READ_TRANSFORMS_SUPPORTED static int next_format(png_bytep colour_type, png_bytep bit_depth) { @@ -308,6 +311,7 @@ sample(png_const_bytep row, png_byte colour_type, png_byte bit_depth, bit_index &= 7; return (result >> (8-bit_index-bit_depth)) & ((1U<current->datacount; } +#ifdef PNG_READ_TRANSFORMS_SUPPORTED /* Return total bytes available for read. */ static size_t store_read_buffer_avail(png_store *ps) @@ -813,6 +820,7 @@ store_read_buffer_avail(png_store *ps) return 0; } +#endif static int store_read_buffer_next(png_store *ps) @@ -1358,35 +1366,6 @@ typedef struct png_modifier png_byte buffer[1024]; } png_modifier; -static double abserr(png_modifier *pm, png_byte bit_depth) -{ - return bit_depth == 16 ? pm->maxabs16 : pm->maxabs8; -} - -static double pcerr(png_modifier *pm, png_byte bit_depth) -{ - return (bit_depth == 16 ? pm->maxpc16 : pm->maxpc8) * .01; -} - -static double outerr(png_modifier *pm, png_byte bit_depth) -{ - /* There is a serious error in the 2 and 4 bit grayscale transform because - * the gamma table value (8 bits) is simply shifted, not rounded, so the - * error in 4 bit greyscale gamma is up to the value below. This is a hack - * to allow pngvalid to succeed: - */ - if (bit_depth == 2) - return .73182-.5; - - if (bit_depth == 4) - return .90644-.5; - - if (bit_depth == 16) - return pm->maxout16; - - return pm->maxout8; -} - /* This returns true if the test should be stopped now because it has already * failed and it is running silently. */ @@ -1424,6 +1403,36 @@ modifier_init(png_modifier *pm) /* Rely on the memset for all the other fields - there are no pointers */ } +#ifdef PNG_READ_TRANSFORMS_SUPPORTED +static double abserr(png_modifier *pm, png_byte bit_depth) +{ + return bit_depth == 16 ? pm->maxabs16 : pm->maxabs8; +} + +static double pcerr(png_modifier *pm, png_byte bit_depth) +{ + return (bit_depth == 16 ? pm->maxpc16 : pm->maxpc8) * .01; +} + +static double outerr(png_modifier *pm, png_byte bit_depth) +{ + /* There is a serious error in the 2 and 4 bit grayscale transform because + * the gamma table value (8 bits) is simply shifted, not rounded, so the + * error in 4 bit greyscale gamma is up to the value below. This is a hack + * to allow pngvalid to succeed: + */ + if (bit_depth == 2) + return .73182-.5; + + if (bit_depth == 4) + return .90644-.5; + + if (bit_depth == 16) + return pm->maxout16; + + return pm->maxout8; +} + /* One modification structure must be provided for each chunk to be modified (in * fact more than one can be provided if multiple separate changes are desired * for a single chunk.) Modifications include adding a new chunk when a @@ -1813,6 +1822,7 @@ set_modifier_for_read(png_modifier *pm, png_infopp ppi, png_uint_32 id, return set_store_for_read(&pm->this, ppi, id, name); } +#endif /* PNG_READ_TRANSFORMS_SUPPORTED */ /***************************** STANDARD PNG FILES *****************************/ /* Standard files - write and save standard files. */ @@ -2748,7 +2758,7 @@ standard_display_init(standard_display *dp, png_store* ps, png_uint_32 id, dp->ps = ps; dp->colour_type = COL_FROM_ID(id); dp->bit_depth = DEPTH_FROM_ID(id); - dp->alpha_sBIT = dp->blue_sBIT = dp->green_sBIT = dp->alpha_sBIT = + dp->red_sBIT = dp->blue_sBIT = dp->green_sBIT = dp->alpha_sBIT = dp->bit_depth; dp->interlace_type = INTERLACE_FROM_ID(id); dp->id = id; @@ -2765,7 +2775,6 @@ standard_display_init(standard_display *dp, png_store* ps, png_uint_32 id, memset(&dp->transparent, 0, sizeof dp->transparent); /* Preset the palette to full intensity/opaque througout: */ memset(dp->palette, 0xff, sizeof dp->palette); - } /* Call this only if the colour type is 3 - PNG_COLOR_TYPE_PALETTE - otherwise @@ -3073,12 +3082,14 @@ progressive_row(png_structp pp, png_bytep new_row, png_uint_32 y, int pass) */ if (dp->do_interlace && dp->interlace_type == PNG_INTERLACE_ADAM7) { +#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED /* Use this opportunity to validate the png 'current' APIs: */ if (y != png_get_current_row_number(pp)) png_error(pp, "png_get_current_row_number is broken"); if (pass != png_get_current_pass_number(pp)) png_error(pp, "png_get_current_pass_number is broken"); +#endif y = PNG_ROW_FROM_PASS_ROW(y, pass); } @@ -3471,6 +3482,7 @@ perform_size_test(png_modifier *pm) /******************************* TRANSFORM TESTS ******************************/ +#ifdef PNG_READ_TRANSFORMS_SUPPORTED /* A set of tests to validate libpng image transforms. The possibilities here * are legion because the transforms can be combined in a combinatorial * fashion. To deal with this some measure of restraint is required, otherwise @@ -4010,12 +4022,13 @@ transform_range_check(png_structp pp, unsigned int r, unsigned int g, /* Compare the scaled, digitzed, values of our local calculation (in+-err) * with the digitized values libpng produced; 'sample_depth' is the actual * digitization depth of the libpng output colors (the bit depth except for - * palette images where it is always 8.) + * palette images where it is always 8.) The check on 'err' is to detect + * internal errors in pngvalid itself (the threshold is about 1/255.) */ unsigned int max = (1U<= in_min && out <= in_max)) + if (err > 4E-3 || !(out >= in_min && out <= in_max)) { char message[256]; size_t pos; @@ -4228,12 +4241,12 @@ transform_test(png_modifier *pmIn, PNG_CONST png_uint_32 idIn, /* The transforms: */ #define ITSTRUCT(name) image_transform_##name -#define IT(name,prev)\ +#define IT(name)\ static image_transform ITSTRUCT(name) =\ {\ #name,\ 1, /*enable*/\ - &ITSTRUCT(prev), /*list*/\ + &PT, /*list*/\ 0, /*global_use*/\ 0, /*local_use*/\ 0, /*next*/\ @@ -4241,6 +4254,7 @@ static image_transform ITSTRUCT(name) =\ image_transform_png_set_##name##_mod,\ image_transform_png_set_##name##_add\ } +#define PT ITSTRUCT(end) /* stores the previous transform */ /* To save code: */ static int @@ -4256,6 +4270,7 @@ image_transform_default_add(image_transform *this, return 1; } +#ifdef PNG_READ_EXPAND_SUPPORTED /* png_set_palette_to_rgb */ static void image_transform_png_set_palette_to_rgb_set(PNG_CONST image_transform *this, @@ -4287,9 +4302,12 @@ image_transform_png_set_palette_to_rgb_add(image_transform *this, return colour_type == PNG_COLOR_TYPE_PALETTE; } -IT(palette_to_rgb, end); - +IT(palette_to_rgb); +#undef PT +#define PT ITSTRUCT(palette_to_rgb) +#endif /* PNG_READ_EXPAND_SUPPORTED */ +#ifdef PNG_READ_EXPAND_SUPPORTED /* png_set_tRNS_to_alpha */ static void image_transform_png_set_tRNS_to_alpha_set(PNG_CONST image_transform *this, @@ -4341,8 +4359,12 @@ image_transform_png_set_tRNS_to_alpha_add(image_transform *this, return (colour_type & PNG_COLOR_MASK_ALPHA) == 0; } -IT(tRNS_to_alpha,palette_to_rgb); +IT(tRNS_to_alpha); +#undef PT +#define PT ITSTRUCT(tRNS_to_alpha) +#endif /* PNG_READ_EXPAND_SUPPORTED */ +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED /* png_set_gray_to_rgb */ static void image_transform_png_set_gray_to_rgb_set(PNG_CONST image_transform *this, @@ -4395,8 +4417,12 @@ image_transform_png_set_gray_to_rgb_add(image_transform *this, return (colour_type & PNG_COLOR_MASK_COLOR) == 0; } -IT(gray_to_rgb,tRNS_to_alpha); +IT(gray_to_rgb); +#undef PT +#define PT ITSTRUCT(gray_to_rgb) +#endif /* PNG_READ_GRAY_TO_RGB_SUPPORTED */ +#ifdef PNG_READ_EXPAND_SUPPORTED /* png_set_expand */ static void image_transform_png_set_expand_set(PNG_CONST image_transform *this, @@ -4437,8 +4463,12 @@ image_transform_png_set_expand_add(image_transform *this, return (colour_type & PNG_COLOR_MASK_ALPHA) == 0; } -IT(expand,gray_to_rgb); +IT(expand); +#undef PT +#define PT ITSTRUCT(expand) +#endif /* PNG_READ_EXPAND_SUPPORTED */ +#ifdef PNG_READ_EXPAND_SUPPORTED /* png_set_expand_gray_1_2_4_to_8 * LIBPNG BUG: this just does an 'expand' */ @@ -4467,7 +4497,12 @@ image_transform_png_set_expand_gray_1_2_4_to_8_add(image_transform *this, bit_depth); } -IT(expand_gray_1_2_4_to_8, expand); +IT(expand_gray_1_2_4_to_8); +#undef PT +#define PT ITSTRUCT(expand_gray_1_2_4_to_8) +#endif /* PNG_READ_EXPAND_SUPPORTED */ + +#ifdef PNG_READ_EXPAND_16_SUPPORTED /* png_set_expand_16 */ static void image_transform_png_set_expand_16_set(PNG_CONST image_transform *this, @@ -4509,8 +4544,12 @@ image_transform_png_set_expand_16_add(image_transform *this, return bit_depth < 16; } -IT(expand_16, expand_gray_1_2_4_to_8); +IT(expand_16); +#undef PT +#define PT ITSTRUCT(expand_16) +#endif /* PNG_READ_EXPAND_16_SUPPORTED */ +#ifdef PNG_READ_16_TO_8_SUPPORTED /* png_set_strip_16 */ static void image_transform_png_set_strip_16_set(PNG_CONST image_transform *this, @@ -4561,8 +4600,12 @@ image_transform_png_set_strip_16_add(image_transform *this, return bit_depth > 8; } -IT(strip_16, expand_16); +IT(strip_16); +#undef PT +#define PT ITSTRUCT(strip_16) +#endif /* PNG_READ_16_TO_8_SUPPORTED */ +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED /* png_set_strip_alpha */ static void image_transform_png_set_strip_alpha_set(PNG_CONST image_transform *this, @@ -4600,8 +4643,12 @@ image_transform_png_set_strip_alpha_add(image_transform *this, return (colour_type & PNG_COLOR_MASK_ALPHA) != 0; } -IT(strip_alpha,strip_16); +IT(strip_alpha); +#undef PT +#define PT ITSTRUCT(strip_alpha) +#endif /* PNG_READ_STRIP_ALPHA_SUPPORTED */ +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED /* png_set_rgb_to_gray(png_structp, int err_action, double red, double green) * png_set_rgb_to_gray_fixed(png_structp, int err_action, png_fixed_point red, * png_fixed_point green) @@ -4677,8 +4724,12 @@ image_transform_png_set_rgb_to_gray_add(image_transform *this, return (colour_type & PNG_COLOR_MASK_COLOR) != 0; } -IT(rgb_to_gray,strip_alpha); +IT(rgb_to_gray); +#undef PT +#define PT ITSTRUCT(rgb_to_gray) +#endif /* PNG_READ_RGB_TO_GRAY_SUPPORTED */ +#ifdef PNG_READ_BACKGROUND_SUPPORTED /* png_set_background(png_structp, png_const_color_16p background_color, * int background_gamma_code, int need_expand, double background_gamma) * png_set_background_fixed(png_structp, png_const_color_16p background_color, @@ -4760,9 +4811,13 @@ image_transform_png_set_background_mod(PNG_CONST image_transform *this, #define image_transform_png_set_background_add image_transform_default_add -IT(background,rgb_to_gray); +IT(background); +#undef PT +#define PT ITSTRUCT(background) +#endif /* PNG_READ_BACKGROUND_SUPPORTED */ -static image_transform *PNG_CONST image_transform_first = &ITSTRUCT(background); +/* This may just be 'end' if all the transforms are disabled! */ +static image_transform *PNG_CONST image_transform_first = &PT; static void transform_enable(PNG_CONST char *name) @@ -5071,9 +5126,11 @@ perform_transform_test(png_modifier *pm) if (!test_transform(pm, 6, 3, READ_BDHI, 1)) return; } +#endif /* PNG_READ_TRANSFORMS_SUPPORTED */ /********************************* GAMMA TESTS ********************************/ +#ifdef PNG_READ_GAMMA_SUPPORTED /* Gamma test images. */ typedef struct gamma_modification { @@ -6016,6 +6073,7 @@ perform_gamma_test(png_modifier *pm, int speed, int summary) } #endif } +#endif /* PNG_READ_GAMMA_SUPPORTED */ /* INTERLACE MACRO VALIDATION */ /* This is copied verbatim from the specification, it is simply the pass @@ -6467,6 +6525,7 @@ int main(int argc, PNG_CONST char **argv) else if (strcmp(*argv, "--notransform") == 0) pm.test_transform = 0; +#ifdef PNG_READ_TRANSFORMS_SUPPORTED else if (strncmp(*argv, "--transform-disable=", sizeof "--transform-disable") == 0) { @@ -6480,6 +6539,7 @@ int main(int argc, PNG_CONST char **argv) pm.test_transform = 1; transform_enable(*argv + sizeof "--transform-enable"); } +#endif /* PNG_READ_TRANSFORMS_SUPPORTED */ else if (strcmp(*argv, "--gamma") == 0) { @@ -6620,13 +6680,17 @@ int main(int argc, PNG_CONST char **argv) perform_size_test(&pm); } +#ifdef PNG_READ_TRANSFORMS_SUPPORTED /* Combinatorial transforms: */ if (pm.test_transform) perform_transform_test(&pm); +#endif /* PNG_READ_TRANSFORMS_SUPPORTED */ +#ifdef PNG_READ_GAMMA_SUPPORTED if (pm.ngammas > 0) perform_gamma_test(&pm, pm.this.speed != 0, summary && !pm.this.speed); +#endif } Catch(fault) diff --git a/pngwrite.c b/pngwrite.c index 7b7b10dac..bce00c0b3 100644 --- a/pngwrite.c +++ b/pngwrite.c @@ -805,9 +805,11 @@ png_write_row(png_structp png_ptr, png_const_bytep row) } #endif +#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED /* Handle other transformations */ if (png_ptr->transformations) png_do_write_transformations(png_ptr); +#endif #ifdef PNG_MNG_FEATURES_SUPPORTED /* Write filter_method 64 (intrapixel differencing) only if diff --git a/pngwtran.c b/pngwtran.c index 2473d1406..a5003d0a5 100644 --- a/pngwtran.c +++ b/pngwtran.c @@ -15,6 +15,7 @@ #ifdef PNG_WRITE_SUPPORTED +#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED /* Transform the data according to the user's wishes. The order of * transformations is significant. */ @@ -563,6 +564,7 @@ png_do_write_invert_alpha(png_row_infop row_info, png_bytep row) } } #endif +#endif /* PNG_WRITE_TRANSFORMS_SUPPORTED */ #ifdef PNG_MNG_FEATURES_SUPPORTED /* Undoes intrapixel differencing */ diff --git a/scripts/pnglibconf.dfa b/scripts/pnglibconf.dfa index a5c2048cf..71aab3385 100644 --- a/scripts/pnglibconf.dfa +++ b/scripts/pnglibconf.dfa @@ -340,6 +340,10 @@ option READ_COMPOSITE_NODIV requires READ option INCH_CONVERSIONS = INCH_CONVERSIONS INCH_CONVERSIONS +# API to build a grayscale palette + +option BUILD_GRAYSCALE_PALETTE + # IN DEVELOPMENT # These are currently experimental features, define them if you want diff --git a/scripts/pnglibconf.h.prebuilt b/scripts/pnglibconf.h.prebuilt index a27650267..b240c34a8 100644 --- a/scripts/pnglibconf.h.prebuilt +++ b/scripts/pnglibconf.h.prebuilt @@ -43,6 +43,7 @@ #define PNG_ALIGN_MEMORY_SUPPORTED #define PNG_BENIGN_ERRORS_SUPPORTED #define PNG_bKGD_SUPPORTED +#define PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED #define PNG_CHECK_cHRM_SUPPORTED #define PNG_cHRM_SUPPORTED #define PNG_CONSOLE_IO_SUPPORTED