X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/1f0299c17dc878540bf190c290392db241b425ad..0fccf28fe6cfd00c63eac76d5aa27b8ce1330467:/src/png/pngrtran.c diff --git a/src/png/pngrtran.c b/src/png/pngrtran.c index 684bf5f253..489554c7e4 100644 --- a/src/png/pngrtran.c +++ b/src/png/pngrtran.c @@ -1,61 +1,29 @@ /* pngrtran.c - transforms the data in a row for PNG readers * - * libpng 1.0.1 + * libpng 1.0.3 - January 14, 1999 * For conditions of distribution and use, see copyright notice in png.h * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc. * Copyright (c) 1996, 1997 Andreas Dilger - * Copyright (c) 1998, Glenn Randers-Pehrson - * March 15, 1998 + * Copyright (c) 1998, 1999 Glenn Randers-Pehrson * - * This file contains functions optionally called by an application + * This file contains functions optionally called by an application * in order to tell libpng how to handle data when reading a PNG. - * Transformations which are used in both reading and writing are + * Transformations that are used in both reading and writing are * in pngtrans.c. */ #define PNG_INTERNAL -#include "../png/png.h" - -#ifdef PNG_READ_COMPOSITE_NODIV_SUPPORTED -/* With these routines, we avoid an integer divide, which will be slower on - * many machines. However, it does take more operations than the corresponding - * divide method, so it may be slower on some RISC systems. There are two - * shifts (by 8 or 16 bits) and an addition, versus a single integer divide. - * - * Note that the rounding factors are NOT supposed to be the same! 128 and - * 32768 are correct for the NODIV code; 127 and 32767 are correct for the - * standard method. - * - * [Optimized code by Greg Roelofs and Mark Adler...blame us for bugs. :-) ] - */ - - /* fg and bg should be in `gamma 1.0' space; alpha is the opacity */ -# define png_composite(composite, fg, alpha, bg) \ - { png_uint_16 temp = ((png_uint_16)(fg) * (png_uint_16)(alpha) + \ - (png_uint_16)(bg)*(png_uint_16)(255 - \ - (png_uint_16)(alpha)) + (png_uint_16)128); \ - (composite) = (png_byte)((temp + (temp >> 8)) >> 8); } -# define png_composite_16(composite, fg, alpha, bg) \ - { png_uint_32 temp = ((png_uint_32)(fg) * (png_uint_32)(alpha) + \ - (png_uint_32)(bg)*(png_uint_32)(65535L - \ - (png_uint_32)(alpha)) + (png_uint_32)32768L); \ - (composite) = (png_uint_16)((temp + (temp >> 16)) >> 16); } - -#else /* standard method using integer division */ - - /* fg and bg should be in `gamma 1.0' space; alpha is the opacity */ -# define png_composite(composite, fg, alpha, bg) \ - (composite) = (png_byte)(((png_uint_16)(fg) * (png_uint_16)(alpha) + \ - (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) + \ - (png_uint_16)127) / 255) -# define png_composite_16(composite, fg, alpha, bg) \ - (composite) = (png_uint_16)(((png_uint_32)(fg) * (png_uint_32)(alpha) + \ - (png_uint_32)(bg)*(png_uint_32)(65535L - (png_uint_32)(alpha)) + \ - (png_uint_32)32767) / (png_uint_32)65535L) - -#endif /* ?PNG_READ_COMPOSITE_NODIV_SUPPORTED */ +#include "png.h" +#if defined(_MSC_VER) && !defined(__MWERKS__) +#define __VISUALC__ _MSC_VER +#endif +#ifdef __VISUALC__ +#ifndef WIN32 +#pragma warning(disable:4135) +#endif +#endif /* Set the action on getting a CRC error for an ancillary or critical chunk. */ void @@ -125,11 +93,21 @@ png_set_background(png_structp png_ptr, } png_ptr->transformations |= PNG_BACKGROUND; - png_memcpy(&(png_ptr->background), background_color, - sizeof(png_color_16)); + png_memcpy(&(png_ptr->background), background_color, sizeof(png_color_16)); png_ptr->background_gamma = (float)background_gamma; png_ptr->background_gamma_type = (png_byte)(background_gamma_code); png_ptr->transformations |= (need_expand ? PNG_BACKGROUND_EXPAND : 0); + + /* Note: if need_expand is set and color_type is either RGB or RGB_ALPHA + * (in which case need_expand is superfluous anyway), the background color + * might actually be gray yet not be flagged as such. This is not a problem + * for the current code, which uses PNG_FLAG_BACKGROUND_IS_GRAY only to + * decide when to do the png_do_gray_to_rgb() transformation. + */ + if ((need_expand && !(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) || + (!need_expand && background_color->red == background_color->green && + background_color->red == background_color->blue)) + png_ptr->flags |= PNG_FLAG_BACKGROUND_IS_GRAY; } #endif @@ -238,11 +216,11 @@ png_set_dither(png_structp png_ptr, png_colorp palette, /* swap the palette around, and set up a table, if necessary */ if (full_dither) { - int j; + int j = num_palette; /* put all the useful colors within the max, but don't move the others */ - for (i = 0, j = num_palette; i < maximum_colors; i++) + for (i = 0; i < maximum_colors; i++) { if ((int)sort[i] >= maximum_colors) { @@ -255,11 +233,11 @@ png_set_dither(png_structp png_ptr, png_colorp palette, } else { - int j; + int j = num_palette; /* move all the used colors inside the max limit, and develop a translation table */ - for (i = 0, j = num_palette; i < maximum_colors; i++) + for (i = 0; i < maximum_colors; i++) { /* only move the colors we need to */ if ((int)sort[i] >= maximum_colors) @@ -315,8 +293,8 @@ png_set_dither(png_structp png_ptr, png_colorp palette, don't always behave themselves with only a few colors as input. So we will just find the closest two colors, and throw out one of them (chosen somewhat randomly). - [I don't understand this at all, so if someone wants to - work on improving it, be my guest - AED] + [We don't understand this at all, so if someone wants to + work on improving it, be our guest - AED, GRP] */ int i; int max_d; @@ -340,7 +318,7 @@ png_set_dither(png_structp png_ptr, png_colorp palette, palette_to_index[i] = (png_byte)i; } - hash = (png_dsortpp)png_malloc(png_ptr, (png_uint_32)(769 * + hash = (png_dsortpp)png_malloc(png_ptr, (png_uint_32)(769 * sizeof (png_dsortp))); for (i = 0; i < 769; i++) hash[i] = NULL; @@ -447,9 +425,7 @@ png_set_dither(png_structp png_ptr, png_colorp palette, { if (hash[i] != NULL) { - png_dsortp p; - - p = hash[i]; + png_dsortp p = hash[i]; while (p) { png_dsortp t; @@ -478,17 +454,13 @@ png_set_dither(png_structp png_ptr, png_colorp palette, if (full_dither) { int i; - int total_bits, num_red, num_green, num_blue; - png_size_t num_entries; png_bytep distance; - - total_bits = PNG_DITHER_RED_BITS + PNG_DITHER_GREEN_BITS + + int total_bits = PNG_DITHER_RED_BITS + PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS; - - num_red = (1 << PNG_DITHER_RED_BITS); - num_green = (1 << PNG_DITHER_GREEN_BITS); - num_blue = (1 << PNG_DITHER_BLUE_BITS); - num_entries = ((png_size_t)1 << total_bits); + int num_red = (1 << PNG_DITHER_RED_BITS); + int num_green = (1 << PNG_DITHER_GREEN_BITS); + int num_blue = (1 << PNG_DITHER_BLUE_BITS); + png_size_t num_entries = ((png_size_t)1 << total_bits); png_ptr->palette_lookup = (png_bytep )png_malloc(png_ptr, (png_uint_32)(num_entries * sizeof (png_byte))); @@ -502,34 +474,29 @@ png_set_dither(png_structp png_ptr, png_colorp palette, for (i = 0; i < num_palette; i++) { - int r, g, b, ir, ig, ib; - - r = (palette[i].red >> (8 - PNG_DITHER_RED_BITS)); - g = (palette[i].green >> (8 - PNG_DITHER_GREEN_BITS)); - b = (palette[i].blue >> (8 - PNG_DITHER_BLUE_BITS)); + int ir, ig, ib; + int r = (palette[i].red >> (8 - PNG_DITHER_RED_BITS)); + int g = (palette[i].green >> (8 - PNG_DITHER_GREEN_BITS)); + int b = (palette[i].blue >> (8 - PNG_DITHER_BLUE_BITS)); for (ir = 0; ir < num_red; ir++) { - int dr, index_r; + int dr = abs(ir - r); + int index_r = (ir << (PNG_DITHER_BLUE_BITS + PNG_DITHER_GREEN_BITS)); - dr = abs(ir - r); - index_r = (ir << (PNG_DITHER_BLUE_BITS + PNG_DITHER_GREEN_BITS)); for (ig = 0; ig < num_green; ig++) { - int dg, dt, dm, index_g; + int dg = abs(ig - g); + int dt = dr + dg; + int dm = ((dr > dg) ? dr : dg); + int index_g = index_r | (ig << PNG_DITHER_BLUE_BITS); - dg = abs(ig - g); - dt = dr + dg; - dm = ((dr > dg) ? dr : dg); - index_g = index_r | (ig << PNG_DITHER_BLUE_BITS); for (ib = 0; ib < num_blue; ib++) { - int d_index, db, dmax, d; - - d_index = index_g | ib; - db = abs(ib - b); - dmax = ((dm > db) ? dm : db); - d = dmax + dt + db; + int d_index = index_g | ib; + int db = abs(ib - b); + int dmax = ((dm > db) ? dm : db); + int d = dmax + dt + db; if (d < (int)distance[d_index]) { @@ -565,7 +532,7 @@ png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma) #if defined(PNG_READ_EXPAND_SUPPORTED) /* Expand paletted images to rgb, expand grayscale images of - * less then 8 bit depth to 8 bit depth, and expand tRNS chunks + * less than 8 bit depth to 8 bit depth, and expand tRNS chunks * to alpha channels. */ void @@ -586,17 +553,49 @@ png_set_gray_to_rgb(png_structp png_ptr) #endif #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) -/* Convert a RGB image to a grayscale of the given width. This would - * allow us, for example, to convert a 24 bpp RGB image into an 8 or - * 16 bpp grayscale image. (Not yet implemented.) +/* Convert a RGB image to a grayscale of the same width. This allows us, + * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image. */ void -png_set_rgb_to_gray(png_structp png_ptr, int gray_bits) +png_set_rgb_to_gray(png_structp png_ptr, int error_action, float red, + float green) { png_debug(1, "in png_set_rgb_to_gray\n"); - png_ptr->transformations |= PNG_RGB_TO_GRAY; - /* Need to do something with gray_bits here. */ - png_warning(png_ptr, "RGB to GRAY transformation is not yet implemented."); + switch(error_action) + { + case 1: png_ptr->transformations |= PNG_RGB_TO_GRAY; + break; + case 2: png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN; + break; + case 3: png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR; + } + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) +#if defined(PNG_READ_EXPAND_SUPPORTED) + png_ptr->transformations |= PNG_EXPAND; +#else + { + png_warning(png_ptr, "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED."); + png_ptr->transformations &= ~PNG_RGB_TO_GRAY; + } +#endif + { + png_byte red_byte = (png_byte)(red*255.0 + 0.5); + png_byte green_byte = (png_byte)(green*255.0 + 0.5); + if(red < 0.0 || green < 0.0) + { + red_byte = 54; + green_byte = 183; + } + else if(red_byte + green_byte > 255) + { + png_warning(png_ptr, "ignoring out of range rgb_to_gray coefficients"); + red_byte = 54; + green_byte = 183; + } + png_ptr->rgb_to_gray_red_coeff = red_byte; + png_ptr->rgb_to_gray_green_coeff = green_byte; + png_ptr->rgb_to_gray_blue_coeff = 255 - red_byte - green_byte; + } } #endif @@ -617,15 +616,20 @@ png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr void png_init_read_transformations(png_structp png_ptr) { - int color_type; - png_debug(1, "in png_init_read_transformations\n"); - color_type = png_ptr->color_type; +#if defined(PNG_USELESS_TESTS_SUPPORTED) + if(png_ptr != NULL) +#endif + { +#if defined(PNG_READ_BACKGROUND_SUPPORTED) || defined(PNG_READ_SHIFT_SUPPORTED) \ + || defined(PNG_READ_GAMMA_SUPPORTED) + int color_type = png_ptr->color_type; +#endif #if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED) if (png_ptr->transformations & PNG_BACKGROUND_EXPAND) { - if (color_type == PNG_COLOR_TYPE_GRAY) + if (!(color_type & PNG_COLOR_MASK_COLOR)) /* i.e., GRAY or GRAY_ALPHA */ { /* expand background chunk. */ switch (png_ptr->bit_depth) @@ -668,10 +672,11 @@ png_init_read_transformations(png_structp png_ptr) if (!(png_ptr->transformations & PNG_EXPAND)) #endif { - /* invert the alpha channel (in tRNS) unless the pixels are + /* invert the alpha channel (in tRNS) unless the pixels are going to be expanded, in which case leave it for later */ - int i; - for (i=0; i<(int)png_ptr->num_trans; i++) + int i,istop; + istop=(int)png_ptr->num_trans; + for (i=0; itrans[i] = 255 - png_ptr->trans[i]; } } @@ -685,7 +690,7 @@ png_init_read_transformations(png_structp png_ptr) png_ptr->background_1 = png_ptr->background; #endif #if defined(PNG_READ_GAMMA_SUPPORTED) - if (png_ptr->transformations & PNG_GAMMA) + if (png_ptr->transformations & (PNG_GAMMA | PNG_RGB_TO_GRAY)) { png_build_gamma_table(png_ptr); #if defined(PNG_READ_BACKGROUND_SUPPORTED) @@ -693,12 +698,10 @@ png_init_read_transformations(png_structp png_ptr) { if (color_type == PNG_COLOR_TYPE_PALETTE) { - int num_palette, i; png_color back, back_1; - png_colorp palette; - - palette = png_ptr->palette; - num_palette = png_ptr->num_palette; + png_colorp palette = png_ptr->palette; + int num_palette = png_ptr->num_palette; + int i; if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE) { @@ -795,11 +798,9 @@ png_init_read_transformations(png_structp png_ptr) else /* color_type != PNG_COLOR_TYPE_PALETTE */ { - double g, gs, m; - - m = (double)(((png_uint_32)1 << png_ptr->bit_depth) - 1); - g = 1.0; - gs = 1.0; + double m = (double)(((png_uint_32)1 << png_ptr->bit_depth) - 1); + double g = 1.0; + double gs = 1.0; switch (png_ptr->background_gamma_type) { @@ -849,11 +850,9 @@ png_init_read_transformations(png_structp png_ptr) #endif if (color_type == PNG_COLOR_TYPE_PALETTE) { - int num_palette, i; - png_colorp palette; - - palette = png_ptr->palette; - num_palette = png_ptr->num_palette; + png_colorp palette = png_ptr->palette; + int num_palette = png_ptr->num_palette; + int i; for (i = 0; i < num_palette; i++) { @@ -873,15 +872,15 @@ png_init_read_transformations(png_structp png_ptr) color_type == PNG_COLOR_TYPE_PALETTE) { int i; + int istop = (int)png_ptr->num_trans; png_color back; - png_colorp palette; + png_colorp palette = png_ptr->palette; - palette = png_ptr->palette; back.red = (png_byte)png_ptr->background.red; back.green = (png_byte)png_ptr->background.green; back.blue = (png_byte)png_ptr->background.blue; - for (i = 0; i < (int)png_ptr->num_trans; i++) + for (i = 0; i < istop; i++) { if (png_ptr->trans[i] == 0) { @@ -889,6 +888,7 @@ png_init_read_transformations(png_structp png_ptr) } else if (png_ptr->trans[i] != 0xff) { + /* The png_composite() macro is defined in png.h */ png_composite(palette[i].red, palette[i].red, png_ptr->trans[i], back.red); png_composite(palette[i].green, palette[i].green, @@ -905,18 +905,18 @@ png_init_read_transformations(png_structp png_ptr) color_type == PNG_COLOR_TYPE_PALETTE) { png_uint_16 i; - int sr, sg, sb; + png_uint_16 istop = png_ptr->num_palette; + int sr = 8 - png_ptr->sig_bit.red; + int sg = 8 - png_ptr->sig_bit.green; + int sb = 8 - png_ptr->sig_bit.blue; - sr = 8 - png_ptr->sig_bit.red; if (sr < 0 || sr > 8) sr = 0; - sg = 8 - png_ptr->sig_bit.green; if (sg < 0 || sg > 8) sg = 0; - sb = 8 - png_ptr->sig_bit.blue; if (sb < 0 || sb > 8) sb = 0; - for (i = 0; i < png_ptr->num_palette; i++) + for (i = 0; i < istop; i++) { png_ptr->palette[i].red >>= sr; png_ptr->palette[i].green >>= sg; @@ -924,6 +924,7 @@ png_init_read_transformations(png_structp png_ptr) } } #endif + } } /* Modify the info structure to reflect the transformations. The @@ -966,6 +967,11 @@ png_read_transform_info(png_structp png_ptr, png_infop info_ptr) } #endif +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (png_ptr->transformations & PNG_GAMMA) + info_ptr->gamma = png_ptr->gamma; +#endif + #if defined(PNG_READ_16_TO_8_SUPPORTED) if ((png_ptr->transformations & PNG_16_TO_8) && info_ptr->bit_depth == 16) info_ptr->bit_depth = 8; @@ -993,6 +999,11 @@ png_read_transform_info(png_structp png_ptr, png_infop info_ptr) info_ptr->color_type |= PNG_COLOR_MASK_COLOR; #endif +#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) + if (png_ptr->transformations & PNG_RGB_TO_GRAY) + info_ptr->color_type &= ~PNG_COLOR_MASK_COLOR; +#endif + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) info_ptr->channels = 1; else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) @@ -1005,20 +1016,19 @@ png_read_transform_info(png_structp png_ptr, png_infop info_ptr) info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA; #endif + if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) + info_ptr->channels++; + #if defined(PNG_READ_FILLER_SUPPORTED) - if ((png_ptr->transformations & PNG_FILLER) && - info_ptr->color_type & PNG_COLOR_TYPE_RGB && - info_ptr->channels == 3) - { - info_ptr->channels = 4; - } + /* STRIP_ALPHA and FILLER allowed: MASK_ALPHA bit stripped above */ + if (png_ptr->transformations & PNG_FILLER && + (info_ptr->color_type == PNG_COLOR_TYPE_RGB || + info_ptr->color_type == PNG_COLOR_TYPE_GRAY)) + ++info_ptr->channels; #endif - if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) - info_ptr->channels++; info_ptr->pixel_depth = (png_byte)(info_ptr->channels * info_ptr->bit_depth); - info_ptr->rowbytes = ((info_ptr->width * info_ptr->pixel_depth + 7) >> 3); } @@ -1053,7 +1063,7 @@ png_do_read_transformations(png_structp png_ptr) png_do_expand_palette(&(png_ptr->row_info), png_ptr->row_buf + 1, png_ptr->palette, png_ptr->trans, png_ptr->num_trans); } - else if (png_ptr->transformations & PNG_EXPAND) + else { if (png_ptr->num_trans) png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1, @@ -1071,6 +1081,60 @@ png_do_read_transformations(png_structp png_ptr) PNG_FLAG_FILLER_AFTER); #endif +#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) + if (png_ptr->transformations & PNG_RGB_TO_GRAY) + { + int rgb_error = + png_do_rgb_to_gray(png_ptr, &(png_ptr->row_info), png_ptr->row_buf + 1); + if(rgb_error) + { + png_ptr->rgb_to_gray_status=1; + if(png_ptr->transformations == PNG_RGB_TO_GRAY_WARN) + png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel"); + if(png_ptr->transformations == PNG_RGB_TO_GRAY_ERR) + png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel"); + } + } +#endif + +/* +From Andreas Dilger e-mail to png-implement, 26 March 1998: + + In most cases, the "simple transparency" should be done prior to doing + gray-to-RGB, or you will have to test 3x as many bytes to check if a + pixel is transparent. You would also need to make sure that the + transparency information is upgraded to RGB. + + To summarize, the current flow is: + - Gray + simple transparency -> compare 1 or 2 gray bytes and composite + with background "in place" if transparent, + convert to RGB if necessary + - Gray + alpha -> composite with gray background and remove alpha bytes, + convert to RGB if necessary + + To support RGB backgrounds for gray images we need: + - Gray + simple transparency -> convert to RGB + simple transparency, compare + 3 or 6 bytes and composite with background + "in place" if transparent (3x compare/pixel + compared to doing composite with gray bkgrnd) + - Gray + alpha -> convert to RGB + alpha, composite with background and + remove alpha bytes (3x float operations/pixel + compared with composite on gray background) + + Greg's change will do this. The reason it wasn't done before is for + performance, as this increases the per-pixel operations. If we would check + in advance if the background was gray or RGB, and position the gray-to-RGB + transform appropriately, then it would save a lot of work/time. + */ + +#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) + /* if gray -> RGB, do so now only if background is non-gray; else do later + * for performance reasons */ + if (png_ptr->transformations & PNG_GRAY_TO_RGB && + !(png_ptr->flags & PNG_FLAG_BACKGROUND_IS_GRAY)) + png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + #if defined(PNG_READ_BACKGROUND_SUPPORTED) if ((png_ptr->transformations & PNG_BACKGROUND) && ((png_ptr->num_trans != 0 ) || @@ -1086,18 +1150,17 @@ png_do_read_transformations(png_structp png_ptr) #if defined(PNG_READ_GAMMA_SUPPORTED) if ((png_ptr->transformations & PNG_GAMMA) && - !(png_ptr->transformations & PNG_BACKGROUND) && +#if defined(PNG_READ_BACKGROUND_SUPPORTED) + !((png_ptr->transformations & PNG_BACKGROUND) && + ((png_ptr->num_trans != 0) || + (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); #endif -#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) - if (png_ptr->transformations & PNG_RGB_TO_GRAY) - png_do_rgb_to_gray(&(png_ptr->row_info), png_ptr->row_buf + 1); -#endif - #if defined(PNG_READ_16_TO_8_SUPPORTED) if (png_ptr->transformations & PNG_16_TO_8) png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1); @@ -1140,7 +1203,9 @@ png_do_read_transformations(png_structp png_ptr) #endif #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) - if (png_ptr->transformations & PNG_GRAY_TO_RGB) + /* if gray -> RGB, do so now only if we did not do so above */ + if (png_ptr->transformations & PNG_GRAY_TO_RGB && + png_ptr->flags & PNG_FLAG_BACKGROUND_IS_GRAY) png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1); #endif @@ -1199,17 +1264,17 @@ png_do_unpack(png_row_infop row_info, png_bytep row) if (row_info->bit_depth < 8) #endif { - png_uint_32 shift, i; - png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width=row_info->width; switch (row_info->bit_depth) { case 1: { - sp = row + (png_size_t)((row_info->width - 1) >> 3); - dp = row + (png_size_t)row_info->width - 1; - shift = 7 - (int)((row_info->width + 7) & 7); - for (i = 0; i < row_info->width; i++) + png_bytep sp = row + (png_size_t)((row_width - 1) >> 3); + png_bytep dp = row + (png_size_t)row_width - 1; + png_uint_32 shift = 7 - (int)((row_width + 7) & 7); + for (i = 0; i < row_width; i++) { *dp = (png_byte)((*sp >> shift) & 0x1); if (shift == 7) @@ -1227,10 +1292,10 @@ png_do_unpack(png_row_infop row_info, png_bytep row) case 2: { - sp = row + (png_size_t)((row_info->width - 1) >> 2); - dp = row + (png_size_t)row_info->width - 1; - shift = (int)((3 - ((row_info->width + 3) & 3)) << 1); - for (i = 0; i < row_info->width; i++) + png_bytep sp = row + (png_size_t)((row_width - 1) >> 2); + png_bytep dp = row + (png_size_t)row_width - 1; + png_uint_32 shift = (int)((3 - ((row_width + 3) & 3)) << 1); + for (i = 0; i < row_width; i++) { *dp = (png_byte)((*sp >> shift) & 0x3); if (shift == 6) @@ -1247,10 +1312,10 @@ png_do_unpack(png_row_infop row_info, png_bytep row) } case 4: { - sp = row + (png_size_t)((row_info->width - 1) >> 1); - dp = row + (png_size_t)row_info->width - 1; - shift = (int)((1 - ((row_info->width + 1) & 1)) << 2); - for (i = 0; i < row_info->width; i++) + png_bytep sp = row + (png_size_t)((row_width - 1) >> 1); + png_bytep dp = row + (png_size_t)row_width - 1; + png_uint_32 shift = (int)((1 - ((row_width + 1) & 1)) << 2); + for (i = 0; i < row_width; i++) { *dp = (png_byte)((*sp >> shift) & 0xf); if (shift == 4) @@ -1268,7 +1333,7 @@ png_do_unpack(png_row_infop row_info, png_bytep row) } row_info->bit_depth = 8; row_info->pixel_depth = (png_byte)(8 * row_info->channels); - row_info->rowbytes = row_info->width * row_info->channels; + row_info->rowbytes = row_width * row_info->channels; } } #endif @@ -1290,10 +1355,11 @@ png_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits) row_info->color_type != PNG_COLOR_TYPE_PALETTE) { int shift[4]; - int channels, c; - png_uint_16 value; + int channels = 0; + int c; + png_uint_16 value = 0; + png_uint_32 row_width = row_info->width; - channels = 0; if (row_info->color_type & PNG_COLOR_MASK_COLOR) { shift[channels++] = row_info->bit_depth - sig_bits->red; @@ -1309,8 +1375,6 @@ png_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits) shift[channels++] = row_info->bit_depth - sig_bits->alpha; } - value = 0; - for (c = 0; c < channels; c++) { if (shift[c] <= 0) @@ -1328,57 +1392,54 @@ png_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits) { png_bytep bp; png_uint_32 i; + png_uint_32 istop = row_info->rowbytes; - for (bp = row, i = 0; i < row_info->rowbytes; i++, bp++) + for (bp = row, i = 0; i < istop; i++) { *bp >>= 1; - *bp &= 0x55; + *bp++ &= 0x55; } break; } case 4: { - png_bytep bp; - png_byte mask; + png_bytep bp = row; png_uint_32 i; - - mask = (png_byte)(((int)0xf0 >> shift[0]) & (int)0xf0) | + png_uint_32 istop = row_info->rowbytes; + png_byte mask = (png_byte)(((int)0xf0 >> shift[0]) & (int)0xf0) | (png_byte)((int)0xf >> shift[0]); - for (bp = row, i = 0; i < row_info->rowbytes; i++, bp++) + + for (i = 0; i < istop; i++) { *bp >>= shift[0]; - *bp &= mask; + *bp++ &= mask; } break; } case 8: { - png_bytep bp; + png_bytep bp = row; png_uint_32 i; + png_uint_32 istop = row_width * channels; - for (bp = row, i = 0; i < row_info->width; i++) + for (i = 0; i < istop; i++) { - for (c = 0; c < (int)row_info->channels; c++, bp++) - { - *bp >>= shift[c]; - } + *bp++ >>= shift[i%channels]; } break; } case 16: { - png_bytep bp; - png_size_t i; + png_bytep bp = row; + png_uint_32 i; + png_uint_32 istop = channels * row_width; - for (bp = row, i = 0; i < row_info->width; i++) + for (i = 0; i < istop; i++) { - for (c = 0; c < (int)row_info->channels; c++, bp += 2) - { - value = (png_uint_16)((*bp << 8) + *(bp + 1)); - value >>= shift[c]; - *bp = (png_byte)(value >> 8); - *(bp + 1) = (png_byte)(value & 0xff); - } + value = (png_uint_16)((*bp << 8) + *(bp + 1)); + value >>= shift[i%channels]; + *bp++ = (png_byte)(value >> 8); + *bp++ = (png_byte)(value & 0xff); } break; } @@ -1399,38 +1460,39 @@ png_do_chop(png_row_infop row_info, png_bytep row) if (row_info->bit_depth == 16) #endif { - png_bytep sp, dp; + png_bytep sp = row; + png_bytep dp = row; png_uint_32 i; + png_uint_32 istop = row_info->width * row_info->channels; - sp = row; - dp = row; - for (i = 0; i < row_info->width * row_info->channels; i++, sp += 2, dp++) + for (i = 0; i> 8)) >> 8; + * + * Approximate calculation with shift/add instead of multiply/divide: + * *dp = ((((png_uint_32)(*sp) << 8) | + * (png_uint_32)((int)(*(sp + 1)) - *sp)) + 128) >> 8; + * + * What we actually do to avoid extra shifting and conversion: + */ - - * GRR: no, I think this is what it really should be: - *dp = (((((png_uint_32)(*sp) << 8) | - (png_uint_32)(*(sp + 1))) + 128L) / (png_uint_32)257L; - - * GRR: here's the exact calculation with shifts: - temp = (((png_uint_32)(*sp) << 8) | (png_uint_32)(*(sp + 1))) + 128L; - *dp = (temp - (temp >> 8)) >> 8; - - - * Approximate calculation with shift/add instead of multiply/divide: - *dp = ((((png_uint_32)(*sp) << 8) | - (png_uint_32)((int)(*(sp + 1)) - *sp)) + 128) >> 8; - - * What we actually do to avoid extra shifting and conversion: */ *dp = *sp + ((((int)(*(sp + 1)) - *sp) > 128) ? 1 : 0); #else + /* Simply discard the low order byte */ *dp = *sp; #endif } @@ -1450,17 +1512,18 @@ png_do_read_swap_alpha(png_row_infop row_info, png_bytep row) if (row != NULL && row_info != NULL) #endif { + png_uint_32 row_width = row_info->width; if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) { /* This converts from RGBA to ARGB */ if (row_info->bit_depth == 8) { - png_bytep sp, dp; + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; png_byte save; png_uint_32 i; - for (i = 0, sp = dp = row + row_info->rowbytes; - i < row_info->width; i++) + for (i = 0; i < row_width; i++) { save = *(--sp); *(--dp) = *(--sp); @@ -1472,12 +1535,12 @@ png_do_read_swap_alpha(png_row_infop row_info, png_bytep row) /* This converts from RRGGBBAA to AARRGGBB */ else { - png_bytep sp, dp; + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; png_byte save[2]; png_uint_32 i; - for (i = 0, sp = dp = row + row_info->rowbytes; - i < row_info->width; i++) + for (i = 0; i < row_width; i++) { save[0] = *(--sp); save[1] = *(--sp); @@ -1497,12 +1560,12 @@ png_do_read_swap_alpha(png_row_infop row_info, png_bytep row) /* This converts from GA to AG */ if (row_info->bit_depth == 8) { - png_bytep sp, dp; + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; png_byte save; png_uint_32 i; - for (i = 0, sp = dp = row + row_info->rowbytes; - i < row_info->width; i++) + for (i = 0; i < row_width; i++) { save = *(--sp); *(--dp) = *(--sp); @@ -1512,12 +1575,12 @@ png_do_read_swap_alpha(png_row_infop row_info, png_bytep row) /* This converts from GGAA to AAGG */ else { - png_bytep sp, dp; + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; png_byte save[2]; png_uint_32 i; - for (i = 0, sp = dp = row + row_info->rowbytes; - i < row_info->width; i++) + for (i = 0; i < row_width; i++) { save[0] = *(--sp); save[1] = *(--sp); @@ -1541,16 +1604,17 @@ png_do_read_invert_alpha(png_row_infop row_info, png_bytep row) if (row != NULL && row_info != NULL) #endif { + png_uint_32 row_width = row_info->width; if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) { /* This inverts the alpha channel in RGBA */ if (row_info->bit_depth == 8) { - png_bytep sp, dp; + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; png_uint_32 i; - for (i = 0, sp = dp = row + row_info->rowbytes; - i < row_info->width; i++) + for (i = 0; i < row_width; i++) { *(--dp) = 255 - *(--sp); *(--dp) = *(--sp); @@ -1561,11 +1625,11 @@ png_do_read_invert_alpha(png_row_infop row_info, png_bytep row) /* This inverts the alpha channel in RRGGBBAA */ else { - png_bytep sp, dp; + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; png_uint_32 i; - for (i = 0, sp = dp = row + row_info->rowbytes; - i < row_info->width; i++) + for (i = 0; i < row_width; i++) { *(--dp) = 255 - *(--sp); *(--dp) = 255 - *(--sp); @@ -1583,11 +1647,11 @@ png_do_read_invert_alpha(png_row_infop row_info, png_bytep row) /* This inverts the alpha channel in GA */ if (row_info->bit_depth == 8) { - png_bytep sp, dp; + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; png_uint_32 i; - for (i = 0, sp = dp = row + row_info->rowbytes; - i < row_info->width; i++) + for (i = 0; i < row_width; i++) { *(--dp) = 255 - *(--sp); *(--dp) = *(--sp); @@ -1596,11 +1660,11 @@ png_do_read_invert_alpha(png_row_infop row_info, png_bytep row) /* This inverts the alpha channel in GGAA */ else { - png_bytep sp, dp; + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; png_uint_32 i; - for (i = 0, sp = dp = row + row_info->rowbytes; - i < row_info->width; i++) + for (i = 0; i < row_width; i++) { *(--dp) = 255 - *(--sp); *(--dp) = 255 - *(--sp); @@ -1619,52 +1683,173 @@ void png_do_read_filler(png_row_infop row_info, png_bytep row, png_uint_32 filler, png_uint_32 flags) { - png_bytep sp, dp; png_uint_32 i; + png_uint_32 row_width = row_info->width; + + png_byte hi_filler = (png_byte)((filler>>8) & 0xff); + png_byte lo_filler = (png_byte)(filler & 0xff); png_debug(1, "in png_do_read_filler\n"); if ( #if defined(PNG_USELESS_TESTS_SUPPORTED) row != NULL && row_info != NULL && #endif - row_info->color_type == PNG_COLOR_TYPE_RGB && row_info->bit_depth == 8) + row_info->color_type == PNG_COLOR_TYPE_GRAY) { - /* This changes the data from RGB to RGBX */ - if (flags & PNG_FLAG_FILLER_AFTER) + if(row_info->bit_depth == 8) { - for (i = 1, sp = row + (png_size_t)row_info->width * 3, - dp = row + (png_size_t)row_info->width * 4; - i < row_info->width; - i++) + /* This changes the data from G to GX */ + if (flags & PNG_FLAG_FILLER_AFTER) { - *(--dp) = (png_byte)filler; - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); + png_bytep sp = row + (png_size_t)row_width; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 1; i < row_width; i++) + { + *(--dp) = lo_filler; + *(--dp) = *(--sp); + } + *(--dp) = lo_filler; + row_info->channels = 2; + row_info->pixel_depth = 16; + row_info->rowbytes = row_width * 2; + } + /* This changes the data from G to XG */ + else + { + png_bytep sp = row + (png_size_t)row_width; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 0; i < row_width; i++) + { + *(--dp) = *(--sp); + *(--dp) = lo_filler; + } + row_info->channels = 2; + row_info->pixel_depth = 16; + row_info->rowbytes = row_width * 2; } - *(--dp) = (png_byte)filler; - row_info->channels = 4; - row_info->pixel_depth = 32; - row_info->rowbytes = row_info->width * 4; } + else if(row_info->bit_depth == 16) + { + /* This changes the data from GG to GGXX */ + if (flags & PNG_FLAG_FILLER_AFTER) + { + png_bytep sp = row + (png_size_t)row_width; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 1; i < row_width; i++) + { + *(--dp) = hi_filler; + *(--dp) = lo_filler; + *(--dp) = *(--sp); + *(--dp) = *(--sp); + } + *(--dp) = hi_filler; + *(--dp) = lo_filler; + row_info->channels = 2; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 2; + } + /* This changes the data from GG to XXGG */ + else + { + png_bytep sp = row + (png_size_t)row_width; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 0; i < row_width; i++) + { + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = hi_filler; + *(--dp) = lo_filler; + } + row_info->channels = 2; + row_info->pixel_depth = 16; + row_info->rowbytes = row_width * 2; + } + } + } /* COLOR_TYPE == GRAY */ + else if (row_info->color_type == PNG_COLOR_TYPE_RGB) + { + if(row_info->bit_depth == 8) + { + /* This changes the data from RGB to RGBX */ + if (flags & PNG_FLAG_FILLER_AFTER) + { + png_bytep sp = row + (png_size_t)row_width * 3; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 1; i < row_width; i++) + { + *(--dp) = lo_filler; + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + } + *(--dp) = lo_filler; + row_info->channels = 4; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + } /* This changes the data from RGB to XRGB */ - else + else + { + png_bytep sp = row + (png_size_t)row_width * 3; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 0; i < row_width; i++) + { + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = lo_filler; + } + row_info->channels = 4; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + } + } + else if(row_info->bit_depth == 16) { - for (i = 0, sp = row + (png_size_t)row_info->width * 3, - dp = row + (png_size_t)row_info->width * 4; - i < row_info->width; - i++) + /* This changes the data from RRGGBB to RRGGBBXX */ + if (flags & PNG_FLAG_FILLER_AFTER) { - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = (png_byte)filler; + png_bytep sp = row + (png_size_t)row_width * 3; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 1; i < row_width; i++) + { + *(--dp) = hi_filler; + *(--dp) = lo_filler; + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + } + *(--dp) = hi_filler; + *(--dp) = lo_filler; + row_info->channels = 4; + row_info->pixel_depth = 64; + row_info->rowbytes = row_width * 4; + } + /* This changes the data from RRGGBB to XXRRGGBB */ + else + { + png_bytep sp = row + (png_size_t)row_width * 3; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 0; i < row_width; i++) + { + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = hi_filler; + *(--dp) = lo_filler; + } + row_info->channels = 4; + row_info->pixel_depth = 64; + row_info->rowbytes = row_width * 4; } - row_info->channels = 4; - row_info->pixel_depth = 32; - row_info->rowbytes = row_info->width * 4; } - } + } /* COLOR_TYPE == RGB */ } #endif @@ -1673,8 +1858,8 @@ png_do_read_filler(png_row_infop row_info, png_bytep row, void png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) { - png_bytep sp, dp; png_uint_32 i; + png_uint_32 row_width = row_info->width; png_debug(1, "in png_do_gray_to_rgb\n"); if (row_info->bit_depth >= 8 && @@ -1687,10 +1872,9 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) { if (row_info->bit_depth == 8) { - for (i = 0, sp = row + (png_size_t)row_info->width - 1, - dp = row + (png_size_t)row_info->width * 3 - 1; - i < row_info->width; - i++) + png_bytep sp = row + (png_size_t)row_width - 1; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 0; i < row_width; i++) { *(dp--) = *sp; *(dp--) = *sp; @@ -1700,10 +1884,9 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) } else { - for (i = 0, sp = row + (png_size_t)row_info->width * 2 - 1, - dp = row + (png_size_t)row_info->width * 6 - 1; - i < row_info->width; - i++) + png_bytep sp = row + (png_size_t)row_width * 2 - 1; + png_bytep dp = sp + (png_size_t)row_width * 4; + for (i = 0; i < row_width; i++) { *(dp--) = *sp; *(dp--) = *(sp - 1); @@ -1720,10 +1903,9 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) { if (row_info->bit_depth == 8) { - for (i = 0, sp = row + (png_size_t)row_info->width * 2 - 1, - dp = row + (png_size_t)row_info->width * 4 - 1; - i < row_info->width; - i++) + png_bytep sp = row + (png_size_t)row_width * 2 - 1; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 0; i < row_width; i++) { *(dp--) = *(sp--); *(dp--) = *sp; @@ -1734,10 +1916,9 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) } else { - for (i = 0, sp = row + (png_size_t)row_info->width * 4 - 1, - dp = row + (png_size_t)row_info->width * 8 - 1; - i < row_info->width; - i++) + png_bytep sp = row + (png_size_t)row_width * 4 - 1; + png_bytep dp = sp + (png_size_t)row_width * 4; + for (i = 0; i < row_width; i++) { *(dp--) = *(sp--); *(dp--) = *(sp--); @@ -1756,12 +1937,267 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) row_info->color_type |= PNG_COLOR_MASK_COLOR; row_info->pixel_depth = (png_byte)(row_info->channels * row_info->bit_depth); - row_info->rowbytes = ((row_info->width * + row_info->rowbytes = ((row_width * row_info->pixel_depth + 7) >> 3); } } #endif +#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) +/* reduce RGB files to grayscale, with or without alpha + * using the equation given in Poynton's ColorFAQ at + * + * Copyright (c) 1998-01-04 Charles Poynton poynton@inforamp.net + * + * Y = 0.212671 * R + 0.715160 * G + 0.072169 * B + * + * We approximate this with + * + * Y = 0.211 * R + 0.715 * G + 0.074 * B + * + * which can be expressed with integers as + * + * Y = (54 * R + 183 * G + 19 * B)/256 + * + * The calculation is to be done in a linear colorspace. + * + * Other integer coefficents can be used via png_set_rgb_to_gray(). + */ +int +png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row) + +{ + png_uint_32 i; + + png_uint_32 row_width = row_info->width; + int rgb_error = 0; + + png_debug(1, "in png_do_rgb_to_gray\n"); + if ( +#if defined(PNG_USELESS_TESTS_SUPPORTED) + row != NULL && row_info != NULL && +#endif + (row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + png_byte rc = png_ptr->rgb_to_gray_red_coeff; + png_byte gc = png_ptr->rgb_to_gray_green_coeff; + png_byte bc = png_ptr->rgb_to_gray_blue_coeff; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + { + if (row_info->bit_depth == 8) + { +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL) + { + png_bytep sp = row; + png_bytep dp = row; + + for (i = 0; i < row_width; i++) + { + png_byte red = png_ptr->gamma_to_1[*(sp++)]; + png_byte green = png_ptr->gamma_to_1[*(sp++)]; + png_byte blue = png_ptr->gamma_to_1[*(sp++)]; + if(red != green || red != blue) + { + rgb_error |= 1; + *(dp++) = png_ptr->gamma_from_1[ + (rc*red+gc*green+bc*blue)>>8]; + } + else + *(dp++) = *(sp-1); + } + } + else +#endif + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_byte red = *(sp++); + png_byte green = *(sp++); + png_byte blue = *(sp++); + if(red != green || red != blue) + { + rgb_error |= 1; + *(dp++) = (rc*red+gc*green+bc*blue)>>8; + } + else + *(dp++) = *(sp-1); + } + } + } + + else /* RGB bit_depth == 16 */ + { +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->gamma_16_to_1 != NULL && + png_ptr->gamma_16_from_1 != NULL) + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 red, green, blue, w; + + red = ((*(sp))<<8) | *(sp+1); sp+=2; + green = ((*(sp))<<8) | *(sp+1); sp+=2; + blue = ((*(sp))<<8) | *(sp+1); sp+=2; + + if(red == green && red == blue) + w = red; + else + { + png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >> + png_ptr->gamma_shift][red>>8]; + png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >> + png_ptr->gamma_shift][green>>8]; + png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >> + png_ptr->gamma_shift][blue>>8]; + png_uint_16 gray16 = (rc * red_1 + gc * green_1 + + bc * blue_1)>>8; + w = png_ptr->gamma_16_from_1[(gray16&0xff) >> + png_ptr->gamma_shift][gray16 >> 8]; + rgb_error |= 1; + } + + *(dp++) = (w>>8) & 0xff; + *(dp++) = w & 0xff; + } + } + else +#endif + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 red, green, blue, gray16; + + red = ((*(sp))<<8) | *(sp+1); sp+=2; + green = ((*(sp))<<8) | *(sp+1); sp+=2; + blue = ((*(sp))<<8) | *(sp+1); sp+=2; + + if(red != green || red != blue) + rgb_error |= 1; + gray16 = (rc * red + gc * green + bc * blue)>>8; + *(dp++) = (gray16>>8) & 0xff; + *(dp++) = gray16 & 0xff; + } + } + } + } + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + if (row_info->bit_depth == 8) + { +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL) + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_byte red = png_ptr->gamma_to_1[*(sp++)]; + png_byte green = png_ptr->gamma_to_1[*(sp++)]; + png_byte blue = png_ptr->gamma_to_1[*(sp++)]; + if(red != green || red != blue) + rgb_error |= 1; + *(dp++) = png_ptr->gamma_from_1 + [(rc*red + gc*green + bc*blue)>>8]; + *(dp++) = *(sp++); /* alpha */ + } + } + else +#endif + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_byte red = *(sp++); + png_byte green = *(sp++); + png_byte blue = *(sp++); + if(red != green || red != blue) + rgb_error |= 1; + *(dp++) = (gc*red + gc*green + bc*blue)>>8; + *(dp++) = *(sp++); /* alpha */ + } + } + } + else /* RGBA bit_depth == 16 */ + { +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->gamma_16_to_1 != NULL && + png_ptr->gamma_16_from_1 != NULL) + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 red, green, blue, w; + + red = ((*(sp))<<8) | *(sp+1); sp+=2; + green = ((*(sp))<<8) | *(sp+1); sp+=2; + blue = ((*(sp))<<8) | *(sp+1); sp+=2; + + if(red == green && red == blue) + w = red; + else + { + png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >> + png_ptr->gamma_shift][red>>8]; + png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >> + png_ptr->gamma_shift][green>>8]; + png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >> + png_ptr->gamma_shift][blue>>8]; + png_uint_16 gray16 = (rc * red_1 + gc * green_1 + + bc * blue_1)>>8; + w = png_ptr->gamma_16_from_1[(gray16&0xff) >> + png_ptr->gamma_shift][gray16 >> 8]; + rgb_error |= 1; + } + + *(dp++) = (w>>8) & 0xff; + *(dp++) = w & 0xff; + *(dp++) = *(sp++); /* alpha */ + *(dp++) = *(sp++); + } + } + else +#endif + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 red, green, blue, gray16; + red = (*(sp)<<8) | *(sp+1); sp+=2; + green = (*(sp)<<8) | *(sp+1); sp+=2; + blue = (*(sp)<<8) | *(sp+1); sp+=2; + if(red != green || red != blue) + rgb_error |= 1; + gray16 = (rc * red + gc * green + bc * blue)>>8; + *(dp++) = (gray16>>8) & 0xff; + *(dp++) = gray16 & 0xff; + *(dp++) = *(sp++); /* alpha */ + *(dp++) = *(sp++); + } + } + } + } + row_info->channels -= (png_byte)2; + row_info->color_type &= ~PNG_COLOR_MASK_COLOR; + row_info->pixel_depth = (png_byte)(row_info->channels * + row_info->bit_depth); + row_info->rowbytes = ((row_width * + row_info->pixel_depth + 7) >> 3); + } + return rgb_error; +} +#endif + /* 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 @@ -1819,8 +2255,7 @@ png_correct_palette(png_structp png_ptr, png_colorp palette, { png_debug(1, "in png_correct_palette\n"); #if defined(PNG_READ_BACKGROUND_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED) - if ((png_ptr->transformations & (PNG_GAMMA)) && - (png_ptr->transformations & (PNG_BACKGROUND))) + if (png_ptr->transformations & (PNG_GAMMA | PNG_BACKGROUND)) { png_color back, back_1; @@ -2008,6 +2443,7 @@ png_do_background(png_row_infop row_info, png_bytep row, { png_bytep sp, dp; png_uint_32 i; + png_uint_32 row_width=row_info->width; int shift; png_debug(1, "in png_do_background\n"); @@ -2028,7 +2464,7 @@ png_do_background(png_row_infop row_info, png_bytep row, { sp = row; shift = 7; - for (i = 0; i < row_info->width; i++) + for (i = 0; i < row_width; i++) { if ((png_uint_16)((*sp >> shift) & 0x1) == trans_values->gray) @@ -2048,45 +2484,112 @@ png_do_background(png_row_infop row_info, png_bytep row, } case 2: { - sp = row; - shift = 6; - for (i = 0; i < row_info->width; i++) +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (gamma_table != NULL) { - if ((png_uint_16)((*sp >> shift) & 0x3) - == trans_values->gray) + sp = row; + shift = 6; + for (i = 0; i < row_width; i++) { - *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); - *sp |= (png_byte)(background->gray << shift); + if ((png_uint_16)((*sp >> shift) & 0x3) + == trans_values->gray) + { + *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); + *sp |= (png_byte)(background->gray << shift); + } + else + { + png_byte p = (*sp >> shift) & 0x3; + png_byte g = (gamma_table [p | (p << 2) | (p << 4) | + (p << 6)] >> 6) & 0x3; + *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); + *sp |= (png_byte)(g << shift); + } + if (!shift) + { + shift = 6; + sp++; + } + else + shift -= 2; } - if (!shift) + } + else +#endif + { + sp = row; + shift = 6; + for (i = 0; i < row_width; i++) { - shift = 6; - sp++; + if ((png_uint_16)((*sp >> shift) & 0x3) + == trans_values->gray) + { + *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); + *sp |= (png_byte)(background->gray << shift); + } + if (!shift) + { + shift = 6; + sp++; + } + else + shift -= 2; } - else - shift -= 2; } break; } case 4: { - sp = row; - shift = 4; - for (i = 0; i < row_info->width; i++) +#if defined(PNG_READ_GAMMA_SUPPORTED) + if (gamma_table != NULL) { - if ((png_uint_16)((*sp >> shift) & 0xf) - == trans_values->gray) + sp = row; + shift = 4; + for (i = 0; i < row_width; i++) { - *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); - *sp |= (png_byte)(background->gray << shift); + if ((png_uint_16)((*sp >> shift) & 0xf) + == trans_values->gray) + { + *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); + *sp |= (png_byte)(background->gray << shift); + } + else + { + png_byte p = (*sp >> shift) & 0xf; + png_byte g = (gamma_table[p | (p << 4)] >> 4) & 0xf; + *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); + *sp |= (png_byte)(g << shift); + } + if (!shift) + { + shift = 4; + sp++; + } + else + shift -= 4; } - if (!shift) + } + else +#endif + { + sp = row; + shift = 4; + for (i = 0; i < row_width; i++) { - shift = 4; - sp++; + if ((png_uint_16)((*sp >> shift) & 0xf) + == trans_values->gray) + { + *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); + *sp |= (png_byte)(background->gray << shift); + } + if (!shift) + { + shift = 4; + sp++; + } + else + shift -= 4; } - else - shift -= 4; } break; } @@ -2095,7 +2598,8 @@ png_do_background(png_row_infop row_info, png_bytep row, #if defined(PNG_READ_GAMMA_SUPPORTED) if (gamma_table != NULL) { - for (i = 0, sp = row; i < row_info->width; i++, sp++) + sp = row; + for (i = 0; i < row_width; i++, sp++) { if (*sp == trans_values->gray) { @@ -2110,7 +2614,8 @@ png_do_background(png_row_infop row_info, png_bytep row, else #endif { - for (i = 0, sp = row; i < row_info->width; i++, sp++) + sp = row; + for (i = 0; i < row_width; i++, sp++) { if (*sp == trans_values->gray) { @@ -2125,7 +2630,8 @@ png_do_background(png_row_infop row_info, png_bytep row, #if defined(PNG_READ_GAMMA_SUPPORTED) if (gamma_16 != NULL) { - for (i = 0, sp = row; i < row_info->width; i++, sp += 2) + sp = row; + for (i = 0; i < row_width; i++, sp += 2) { png_uint_16 v; @@ -2147,7 +2653,8 @@ png_do_background(png_row_infop row_info, png_bytep row, else #endif { - for (i = 0, sp = row; i < row_info->width; i++, sp += 2) + sp = row; + for (i = 0; i < row_width; i++, sp += 2) { png_uint_16 v; @@ -2171,7 +2678,8 @@ png_do_background(png_row_infop row_info, png_bytep row, #if defined(PNG_READ_GAMMA_SUPPORTED) if (gamma_table != NULL) { - for (i = 0, sp = row; i < row_info->width; i++, sp += 3) + sp = row; + for (i = 0; i < row_width; i++, sp += 3) { if (*sp == trans_values->red && *(sp + 1) == trans_values->green && @@ -2192,7 +2700,8 @@ png_do_background(png_row_infop row_info, png_bytep row, else #endif { - for (i = 0, sp = row; i < row_info->width; i++, sp += 3) + sp = row; + for (i = 0; i < row_width; i++, sp += 3) { if (*sp == trans_values->red && *(sp + 1) == trans_values->green && @@ -2210,13 +2719,12 @@ png_do_background(png_row_infop row_info, png_bytep row, #if defined(PNG_READ_GAMMA_SUPPORTED) if (gamma_16 != NULL) { - for (i = 0, sp = row; i < row_info->width; i++, sp += 6) + sp = row; + for (i = 0; i < row_width; i++, sp += 6) { - png_uint_16 r, g, b; - - r = ((png_uint_16)(*sp) << 8) + *(sp + 1); - g = ((png_uint_16)(*(sp + 2)) << 8) + *(sp + 3); - b = ((png_uint_16)(*(sp + 4)) << 8) + *(sp + 5); + png_uint_16 r = ((png_uint_16)(*sp) << 8) + *(sp + 1); + png_uint_16 g = ((png_uint_16)(*(sp + 2)) << 8) + *(sp + 3); + png_uint_16 b = ((png_uint_16)(*(sp + 4)) << 8) + *(sp + 5); if (r == trans_values->red && g == trans_values->green && b == trans_values->blue) { @@ -2230,8 +2738,7 @@ png_do_background(png_row_infop row_info, png_bytep row, } else { - png_uint_16 v; - v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; *sp = (png_byte)((v >> 8) & 0xff); *(sp + 1) = (png_byte)(v & 0xff); v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; @@ -2246,13 +2753,13 @@ png_do_background(png_row_infop row_info, png_bytep row, else #endif { - for (i = 0, sp = row; i < row_info->width; i++, sp += 6) + sp = row; + for (i = 0; i < row_width; i++, sp += 6) { - png_uint_16 r, g, b; + png_uint_16 r = ((png_uint_16)(*sp) << 8) + *(sp + 1); + png_uint_16 g = ((png_uint_16)(*(sp + 2)) << 8) + *(sp + 3); + png_uint_16 b = ((png_uint_16)(*(sp + 4)) << 8) + *(sp + 5); - r = ((png_uint_16)(*sp) << 8) + *(sp + 1); - g = ((png_uint_16)(*(sp + 2)) << 8) + *(sp + 3); - b = ((png_uint_16)(*(sp + 4)) << 8) + *(sp + 5); if (r == trans_values->red && g == trans_values->green && b == trans_values->blue) { @@ -2276,12 +2783,12 @@ png_do_background(png_row_infop row_info, png_bytep row, if (gamma_to_1 != NULL && gamma_from_1 != NULL && gamma_table != NULL) { - for (i = 0, sp = row, dp = row; - i < row_info->width; i++, sp += 2, dp++) + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 2, dp++) { - png_uint_16 a; + png_uint_16 a = *(sp + 1); - a = *(sp + 1); if (a == 0xff) { *dp = gamma_table[*sp]; @@ -2304,12 +2811,12 @@ png_do_background(png_row_infop row_info, png_bytep row, else #endif { - for (i = 0, sp = row, dp = row; - i < row_info->width; i++, sp += 2, dp++) + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 2, dp++) { - png_byte a; + png_byte a = *(sp + 1); - a = *(sp + 1); if (a == 0xff) { *dp = *sp; @@ -2331,12 +2838,12 @@ png_do_background(png_row_infop row_info, png_bytep row, if (gamma_16 != NULL && gamma_16_from_1 != NULL && gamma_16_to_1 != NULL) { - for (i = 0, sp = row, dp = row; - i < row_info->width; i++, sp += 4, dp += 2) + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 4, dp += 2) { - png_uint_16 a; + png_uint_16 a = ((png_uint_16)(*(sp + 2)) << 8) + *(sp + 3); - a = ((png_uint_16)(*(sp + 2)) << 8) + *(sp + 3); if (a == (png_uint_16)0xffff) { png_uint_16 v; @@ -2366,12 +2873,11 @@ png_do_background(png_row_infop row_info, png_bytep row, else #endif { - for (i = 0, sp = row, dp = row; - i < row_info->width; i++, sp += 4, dp += 2) + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 4, dp += 2) { - png_uint_16 a; - - a = ((png_uint_16)(*(sp + 2)) << 8) + *(sp + 3); + png_uint_16 a = ((png_uint_16)(*(sp + 2)) << 8) + *(sp + 3); if (a == (png_uint_16)0xffff) { png_memcpy(dp, sp, 2); @@ -2403,12 +2909,12 @@ png_do_background(png_row_infop row_info, png_bytep row, if (gamma_to_1 != NULL && gamma_from_1 != NULL && gamma_table != NULL) { - for (i = 0, sp = row, dp = row; - i < row_info->width; i++, sp += 4, dp += 3) + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 4, dp += 3) { - png_byte a; + png_byte a = *(sp + 3); - a = *(sp + 3); if (a == 0xff) { *dp = gamma_table[*sp]; @@ -2441,12 +2947,12 @@ png_do_background(png_row_infop row_info, png_bytep row, else #endif { - for (i = 0, sp = row, dp = row; - i < row_info->width; i++, sp += 4, dp += 3) + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 4, dp += 3) { - png_byte a; + png_byte a = *(sp + 3); - a = *(sp + 3); if (a == 0xff) { *dp = *sp; @@ -2476,13 +2982,12 @@ png_do_background(png_row_infop row_info, png_bytep row, if (gamma_16 != NULL && gamma_16_from_1 != NULL && gamma_16_to_1 != NULL) { - for (i = 0, sp = row, dp = row; - i < row_info->width; i++, sp += 8, dp += 6) + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 8, dp += 6) { - png_uint_16 a; - - a = (png_uint_16)(((png_uint_16)(*(sp + 6)) << 8) + - (png_uint_16)(*(sp + 7))); + png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) + << 8) + (png_uint_16)(*(sp + 7))); if (a == (png_uint_16)0xffff) { png_uint_16 v; @@ -2532,13 +3037,12 @@ png_do_background(png_row_infop row_info, png_bytep row, else #endif { - for (i = 0, sp = row, dp = row; - i < row_info->width; i++, sp += 8, dp += 6) + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 8, dp += 6) { - png_uint_16 a; - - a = (png_uint_16)(((png_uint_16)(*(sp + 6)) << 8) + - (png_uint_16)(*(sp + 7))); + png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) + << 8) + (png_uint_16)(*(sp + 7))); if (a == (png_uint_16)0xffff) { png_memcpy(dp, sp, 6); @@ -2554,11 +3058,13 @@ png_do_background(png_row_infop row_info, png_bytep row, } else { - png_uint_16 r, g, b, v; + png_uint_16 v; - r = ((png_uint_16)(*sp) << 8) + *(sp + 1); - g = ((png_uint_16)(*(sp + 2)) << 8) + *(sp + 3); - b = ((png_uint_16)(*(sp + 4)) << 8) + *(sp + 5); + png_uint_16 r = ((png_uint_16)(*sp) << 8) + *(sp + 1); + png_uint_16 g = ((png_uint_16)(*(sp + 2)) << 8) + + *(sp + 3); + png_uint_16 b = ((png_uint_16)(*(sp + 4)) << 8) + + *(sp + 5); png_composite_16(v, r, a, background->red); *dp = (png_byte)((v >> 8) & 0xff); @@ -2583,7 +3089,7 @@ png_do_background(png_row_infop row_info, png_bytep row, row_info->channels--; row_info->pixel_depth = (png_byte)(row_info->channels * row_info->bit_depth); - row_info->rowbytes = ((row_info->width * + row_info->rowbytes = ((row_width * row_info->pixel_depth + 7) >> 3); } } @@ -2592,7 +3098,7 @@ png_do_background(png_row_infop row_info, png_bytep row, #if defined(PNG_READ_GAMMA_SUPPORTED) /* Gamma correct the image, avoiding the alpha channel. Make sure - * you do this after you deal with the trasparency issue on grayscale + * you do this after you deal with the transparency issue on grayscale * or rgb images. If your bit depth is 8, use gamma_table, if it * is 16, use gamma_16_table and gamma_shift. Build these with * build_gamma_table(). @@ -2604,6 +3110,7 @@ png_do_gamma(png_row_infop row_info, png_bytep row, { png_bytep sp; png_uint_32 i; + png_uint_32 row_width=row_info->width; png_debug(1, "in png_do_gamma\n"); if ( @@ -2619,7 +3126,8 @@ png_do_gamma(png_row_infop row_info, png_bytep row, { if (row_info->bit_depth == 8) { - for (i = 0, sp = row; i < row_info->width; i++) + sp = row; + for (i = 0; i < row_width; i++) { *sp = gamma_table[*sp]; sp++; @@ -2631,7 +3139,8 @@ png_do_gamma(png_row_infop row_info, png_bytep row, } else /* if (row_info->bit_depth == 16) */ { - for (i = 0, sp = row; i < row_info->width; i++) + sp = row; + for (i = 0; i < row_width; i++) { png_uint_16 v; @@ -2655,8 +3164,8 @@ png_do_gamma(png_row_infop row_info, png_bytep row, { if (row_info->bit_depth == 8) { - for (i = 0, sp = row; - i < row_info->width; i++) + sp = row; + for (i = 0; i < row_width; i++) { *sp = gamma_table[*sp]; sp++; @@ -2669,12 +3178,10 @@ png_do_gamma(png_row_infop row_info, png_bytep row, } else /* if (row_info->bit_depth == 16) */ { - for (i = 0, sp = row; - i < row_info->width; i++) + sp = row; + for (i = 0; i < row_width; i++) { - png_uint_16 v; - - v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; *sp = (png_byte)((v >> 8) & 0xff); *(sp + 1) = (png_byte)(v & 0xff); sp += 2; @@ -2694,8 +3201,8 @@ png_do_gamma(png_row_infop row_info, png_bytep row, { if (row_info->bit_depth == 8) { - for (i = 0, sp = row; - i < row_info->width; i++) + sp = row; + for (i = 0; i < row_width; i++) { *sp = gamma_table[*sp]; sp += 2; @@ -2703,12 +3210,10 @@ png_do_gamma(png_row_infop row_info, png_bytep row, } else /* if (row_info->bit_depth == 16) */ { - for (i = 0, sp = row; - i < row_info->width; i++) + sp = row; + for (i = 0; i < row_width; i++) { - png_uint_16 v; - - v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; *sp = (png_byte)((v >> 8) & 0xff); *(sp + 1) = (png_byte)(v & 0xff); sp += 4; @@ -2720,7 +3225,8 @@ png_do_gamma(png_row_infop row_info, png_bytep row, { if (row_info->bit_depth == 2) { - for (i = 0, sp = row; i < row_info->width; i += 4) + sp = row; + for (i = 0; i < row_width; i += 4) { int a = *sp & 0xc0; int b = *sp & 0x30; @@ -2736,7 +3242,8 @@ png_do_gamma(png_row_infop row_info, png_bytep row, } if (row_info->bit_depth == 4) { - for (i = 0, sp = row; i < row_info->width; i += 2) + sp = row; + for (i = 0; i < row_width; i += 2) { int msb = *sp & 0xf0; int lsb = *sp & 0x0f; @@ -2748,7 +3255,8 @@ png_do_gamma(png_row_infop row_info, png_bytep row, } else if (row_info->bit_depth == 8) { - for (i = 0, sp = row; i < row_info->width; i++) + sp = row; + for (i = 0; i < row_width; i++) { *sp = gamma_table[*sp]; sp++; @@ -2756,11 +3264,10 @@ png_do_gamma(png_row_infop row_info, png_bytep row, } else if (row_info->bit_depth == 16) { - for (i = 0, sp = row; i < row_info->width; i++) + sp = row; + for (i = 0; i < row_width; i++) { - png_uint_16 v; - - v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; *sp = (png_byte)((v >> 8) & 0xff); *(sp + 1) = (png_byte)(v & 0xff); sp += 2; @@ -2784,6 +3291,7 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row, int shift, value; png_bytep sp, dp; png_uint_32 i; + png_uint_32 row_width=row_info->width; png_debug(1, "in png_do_expand_palette\n"); if ( @@ -2798,10 +3306,10 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row, { case 1: { - sp = row + (png_size_t)((row_info->width - 1) >> 3); - dp = row + (png_size_t)row_info->width - 1; - shift = 7 - (int)((row_info->width + 7) & 7); - for (i = 0; i < row_info->width; i++) + sp = row + (png_size_t)((row_width - 1) >> 3); + dp = row + (png_size_t)row_width - 1; + shift = 7 - (int)((row_width + 7) & 7); + for (i = 0; i < row_width; i++) { if ((*sp >> shift) & 0x1) *dp = 1; @@ -2821,10 +3329,10 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row, } case 2: { - sp = row + (png_size_t)((row_info->width - 1) >> 2); - dp = row + (png_size_t)row_info->width - 1; - shift = (int)((3 - ((row_info->width + 3) & 3)) << 1); - for (i = 0; i < row_info->width; i++) + sp = row + (png_size_t)((row_width - 1) >> 2); + dp = row + (png_size_t)row_width - 1; + shift = (int)((3 - ((row_width + 3) & 3)) << 1); + for (i = 0; i < row_width; i++) { value = (*sp >> shift) & 0x3; *dp = (png_byte)value; @@ -2842,10 +3350,10 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row, } case 4: { - sp = row + (png_size_t)((row_info->width - 1) >> 1); - dp = row + (png_size_t)row_info->width - 1; - shift = (int)((row_info->width & 1) << 2); - for (i = 0; i < row_info->width; i++) + sp = row + (png_size_t)((row_width - 1) >> 1); + dp = row + (png_size_t)row_width - 1; + shift = (int)((row_width & 1) << 2); + for (i = 0; i < row_width; i++) { value = (*sp >> shift) & 0xf; *dp = (png_byte)value; @@ -2864,7 +3372,7 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row, } row_info->bit_depth = 8; row_info->pixel_depth = 8; - row_info->rowbytes = row_info->width; + row_info->rowbytes = row_width; } switch (row_info->bit_depth) { @@ -2872,10 +3380,10 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row, { if (trans != NULL) { - sp = row + (png_size_t)row_info->width - 1; - dp = row + (png_size_t)(row_info->width << 2) - 1; + sp = row + (png_size_t)row_width - 1; + dp = row + (png_size_t)(row_width << 2) - 1; - for (i = 0; i < row_info->width; i++) + for (i = 0; i < row_width; i++) { if ((int)(*sp) >= num_trans) *dp-- = 0xff; @@ -2888,16 +3396,16 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row, } row_info->bit_depth = 8; row_info->pixel_depth = 32; - row_info->rowbytes = row_info->width * 4; + row_info->rowbytes = row_width * 4; row_info->color_type = 6; row_info->channels = 4; } else { - sp = row + (png_size_t)row_info->width - 1; - dp = row + (png_size_t)(row_info->width * 3) - 1; + sp = row + (png_size_t)row_width - 1; + dp = row + (png_size_t)(row_width * 3) - 1; - for (i = 0; i < row_info->width; i++) + for (i = 0; i < row_width; i++) { *dp-- = palette[*sp].blue; *dp-- = palette[*sp].green; @@ -2906,7 +3414,7 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row, } row_info->bit_depth = 8; row_info->pixel_depth = 24; - row_info->rowbytes = row_info->width * 3; + row_info->rowbytes = row_width * 3; row_info->color_type = 2; row_info->channels = 3; } @@ -2926,6 +3434,7 @@ png_do_expand(png_row_infop row_info, png_bytep row, int shift, value; png_bytep sp, dp; png_uint_32 i; + png_uint_32 row_width=row_info->width; png_debug(1, "in png_do_expand\n"); #if defined(PNG_USELESS_TESTS_SUPPORTED) @@ -2943,10 +3452,10 @@ png_do_expand(png_row_infop row_info, png_bytep row, case 1: { gray *= 0xff; - sp = row + (png_size_t)((row_info->width - 1) >> 3); - dp = row + (png_size_t)row_info->width - 1; - shift = 7 - (int)((row_info->width + 7) & 7); - for (i = 0; i < row_info->width; i++) + sp = row + (png_size_t)((row_width - 1) >> 3); + dp = row + (png_size_t)row_width - 1; + shift = 7 - (int)((row_width + 7) & 7); + for (i = 0; i < row_width; i++) { if ((*sp >> shift) & 0x1) *dp = 0xff; @@ -2967,10 +3476,10 @@ png_do_expand(png_row_infop row_info, png_bytep row, case 2: { gray *= 0x55; - sp = row + (png_size_t)((row_info->width - 1) >> 2); - dp = row + (png_size_t)row_info->width - 1; - shift = (int)((3 - ((row_info->width + 3) & 3)) << 1); - for (i = 0; i < row_info->width; i++) + sp = row + (png_size_t)((row_width - 1) >> 2); + dp = row + (png_size_t)row_width - 1; + shift = (int)((3 - ((row_width + 3) & 3)) << 1); + for (i = 0; i < row_width; i++) { value = (*sp >> shift) & 0x3; *dp = (png_byte)(value | (value << 2) | (value << 4) | @@ -2990,10 +3499,10 @@ png_do_expand(png_row_infop row_info, png_bytep row, case 4: { gray *= 0x11; - sp = row + (png_size_t)((row_info->width - 1) >> 1); - dp = row + (png_size_t)row_info->width - 1; - shift = (int)((1 - ((row_info->width + 1) & 1)) << 2); - for (i = 0; i < row_info->width; i++) + sp = row + (png_size_t)((row_width - 1) >> 1); + dp = row + (png_size_t)row_width - 1; + shift = (int)((1 - ((row_width + 1) & 1)) << 2); + for (i = 0; i < row_width; i++) { value = (*sp >> shift) & 0xf; *dp = (png_byte)(value | (value << 4)); @@ -3012,16 +3521,16 @@ png_do_expand(png_row_infop row_info, png_bytep row, } row_info->bit_depth = 8; row_info->pixel_depth = 8; - row_info->rowbytes = row_info->width; + row_info->rowbytes = row_width; } if (trans_value != NULL) { if (row_info->bit_depth == 8) { - sp = row + (png_size_t)row_info->width - 1; - dp = row + (png_size_t)(row_info->width << 1) - 1; - for (i = 0; i < row_info->width; i++) + sp = row + (png_size_t)row_width - 1; + dp = row + (png_size_t)(row_width << 1) - 1; + for (i = 0; i < row_width; i++) { if (*sp == gray) *dp-- = 0; @@ -3034,7 +3543,7 @@ png_do_expand(png_row_infop row_info, png_bytep row, { sp = row + row_info->rowbytes - 1; dp = row + (row_info->rowbytes << 1) - 1; - for (i = 0; i < row_info->width; i++) + for (i = 0; i < row_width; i++) { if (((png_uint_16)*(sp) | ((png_uint_16)*(sp - 1) << 8)) == gray) @@ -3055,7 +3564,7 @@ png_do_expand(png_row_infop row_info, png_bytep row, row_info->channels = 2; row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1); row_info->rowbytes = - ((row_info->width * row_info->pixel_depth) >> 3); + ((row_width * row_info->pixel_depth) >> 3); } } else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_value) @@ -3063,8 +3572,8 @@ png_do_expand(png_row_infop row_info, png_bytep row, if (row_info->bit_depth == 8) { sp = row + (png_size_t)row_info->rowbytes - 1; - dp = row + (png_size_t)(row_info->width << 2) - 1; - for (i = 0; i < row_info->width; i++) + dp = row + (png_size_t)(row_width << 2) - 1; + for (i = 0; i < row_width; i++) { if (*(sp - 2) == trans_value->red && *(sp - 1) == trans_value->green && @@ -3080,8 +3589,8 @@ png_do_expand(png_row_infop row_info, png_bytep row, else if (row_info->bit_depth == 16) { sp = row + row_info->rowbytes - 1; - dp = row + (png_size_t)(row_info->width << 3) - 1; - for (i = 0; i < row_info->width; i++) + dp = row + (png_size_t)(row_width << 3) - 1; + for (i = 0; i < row_width; i++) { if ((((png_uint_16)*(sp - 4) | ((png_uint_16)*(sp - 5) << 8)) == trans_value->red) && @@ -3110,7 +3619,7 @@ png_do_expand(png_row_infop row_info, png_bytep row, row_info->channels = 4; row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2); row_info->rowbytes = - ((row_info->width * row_info->pixel_depth) >> 3); + ((row_width * row_info->pixel_depth) >> 3); } } } @@ -3123,6 +3632,7 @@ png_do_dither(png_row_infop row_info, png_bytep row, { png_bytep sp, dp; png_uint_32 i; + png_uint_32 row_width=row_info->width; png_debug(1, "in png_do_dither\n"); #if defined(PNG_USELESS_TESTS_SUPPORTED) @@ -3135,7 +3645,7 @@ png_do_dither(png_row_infop row_info, png_bytep row, int r, g, b, p; sp = row; dp = row; - for (i = 0; i < row_info->width; i++) + for (i = 0; i < row_width; i++) { r = *sp++; g = *sp++; @@ -3163,7 +3673,7 @@ png_do_dither(png_row_infop row_info, png_bytep row, row_info->channels = 1; row_info->pixel_depth = row_info->bit_depth; row_info->rowbytes = - ((row_info->width * row_info->pixel_depth + 7) >> 3); + ((row_width * row_info->pixel_depth + 7) >> 3); } else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA && palette_lookup != NULL && row_info->bit_depth == 8) @@ -3171,7 +3681,7 @@ png_do_dither(png_row_infop row_info, png_bytep row, int r, g, b, p; sp = row; dp = row; - for (i = 0; i < row_info->width; i++) + for (i = 0; i < row_width; i++) { r = *sp++; g = *sp++; @@ -3193,13 +3703,13 @@ png_do_dither(png_row_infop row_info, png_bytep row, row_info->channels = 1; row_info->pixel_depth = row_info->bit_depth; row_info->rowbytes = - ((row_info->width * row_info->pixel_depth + 7) >> 3); + ((row_width * row_info->pixel_depth + 7) >> 3); } else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE && dither_lookup && row_info->bit_depth == 8) { sp = row; - for (i = 0; i < row_info->width; i++, sp++) + for (i = 0; i < row_width; i++, sp++) { *sp = dither_lookup[*sp]; } @@ -3220,13 +3730,18 @@ static int png_gamma_shift[] = void png_build_gamma_table(png_structp png_ptr) { - png_debug(1, "in png_build_gamma_table\n"); + png_debug(1, "in png_build_gamma_table\n"); + if(png_ptr->gamma != 0.0) + { if (png_ptr->bit_depth <= 8) { int i; double g; - g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); + if (png_ptr->screen_gamma > .000001) + g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); + else + g = 1.0; png_ptr->gamma_table = (png_bytep)png_malloc(png_ptr, (png_uint_32)256); @@ -3237,9 +3752,11 @@ png_build_gamma_table(png_structp png_ptr) g) * 255.0 + .5); } -#if defined(PNG_READ_BACKGROUND_SUPPORTED) - if (png_ptr->transformations & PNG_BACKGROUND) +#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ + defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) + if (png_ptr->transformations & (PNG_BACKGROUND | PNG_RGB_TO_GRAY)) { + g = 1.0 / (png_ptr->gamma); png_ptr->gamma_to_1 = (png_bytep)png_malloc(png_ptr, @@ -3251,18 +3768,23 @@ png_build_gamma_table(png_structp png_ptr) g) * 255.0 + .5); } - g = 1.0 / (png_ptr->screen_gamma); - + png_ptr->gamma_from_1 = (png_bytep)png_malloc(png_ptr, (png_uint_32)256); + if(png_ptr->screen_gamma > 0.000001) + g = 1.0 / png_ptr->screen_gamma; + else + g = png_ptr->gamma; /* probably doing rgb_to_gray */ + for (i = 0; i < 256; i++) { png_ptr->gamma_from_1[i] = (png_byte)(pow((double)i / 255.0, g) * 255.0 + .5); + } } -#endif /* PNG_BACKGROUND_SUPPORTED */ +#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */ } else { @@ -3304,13 +3826,15 @@ png_build_gamma_table(png_structp png_ptr) num = (1 << (8 - shift)); - g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); + if (png_ptr->screen_gamma > .000001) + g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); + else + g = 1.0; png_ptr->gamma_16_table = (png_uint_16pp)png_malloc(png_ptr, (png_uint_32)(num * sizeof (png_uint_16p))); - if ((png_ptr->transformations & PNG_16_TO_8) && - !(png_ptr->transformations & PNG_BACKGROUND)) + if (png_ptr->transformations & (PNG_16_TO_8 | PNG_BACKGROUND)) { double fin, fout; png_uint_32 last, max; @@ -3360,9 +3884,11 @@ png_build_gamma_table(png_structp png_ptr) } } -#if defined(PNG_READ_BACKGROUND_SUPPORTED) - if (png_ptr->transformations & PNG_BACKGROUND) +#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ + defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) + if (png_ptr->transformations & (PNG_BACKGROUND | PNG_RGB_TO_GRAY)) { + g = 1.0 / (png_ptr->gamma); png_ptr->gamma_16_to_1 = (png_uint_16pp)png_malloc(png_ptr, @@ -3382,7 +3908,11 @@ png_build_gamma_table(png_structp png_ptr) 65535.0, g) * 65535.0 + .5); } } - g = 1.0 / (png_ptr->screen_gamma); + + if(png_ptr->screen_gamma > 0.000001) + g = 1.0 / png_ptr->screen_gamma; + else + g = png_ptr->gamma; /* probably doing rgb_to_gray */ png_ptr->gamma_16_from_1 = (png_uint_16pp)png_malloc(png_ptr, (png_uint_32)(num * sizeof (png_uint_16p))); @@ -3402,8 +3932,9 @@ png_build_gamma_table(png_structp png_ptr) } } } -#endif /* PNG_BACKGROUND_SUPPORTED */ +#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */ } + } } #endif