X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/9c0d9ce3285864062f74951871971fec1debeafb..06a32e049c1bad9249079ad2e91659303424a774:/src/png/pngrutil.c diff --git a/src/png/pngrutil.c b/src/png/pngrutil.c index 72b662338c..52a73cfc39 100644 --- a/src/png/pngrutil.c +++ b/src/png/pngrutil.c @@ -1,7 +1,7 @@ /* pngrutil.c - utilities to read a PNG file * - * Last changed in libpng 1.5.6 [November 3, 2011] + * Last changed in libpng 1.5.7 [December 15, 2011] * Copyright (c) 1998-2011 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) @@ -490,7 +490,7 @@ png_decompress_chunk(png_structp png_ptr, int comp_type, { PNG_WARNING_PARAMETERS(p) png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_d, comp_type); - png_formatted_warning(png_ptr, p, "Unknown zTXt compression type @1"); + png_formatted_warning(png_ptr, p, "Unknown compression type @1"); /* The recovery is to simply drop the data. */ } @@ -2540,6 +2540,14 @@ png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) comp_type = *lang++; } + if (comp_type || (comp_flag && comp_flag != PNG_TEXT_COMPRESSION_zTXt)) + { + png_warning(png_ptr, "Unknown iTXt compression type or method"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + for (lang_key = lang; *lang_key; lang_key++) /* Empty loop */ ; @@ -2767,18 +2775,13 @@ png_check_chunk_name(png_structp png_ptr, png_uint_32 chunk_name) } } -/* Combines the row recently read in with the existing pixels in the - * row. This routine takes care of alpha and transparency if requested. - * This routine also handles the two methods of progressive display - * of interlaced images, depending on the mask value. - * The mask value describes which pixels are to be combined with - * the row. The pattern always repeats every 8 pixels, so just 8 - * bits are needed. A one indicates the pixel is to be combined, - * a zero indicates the pixel is to be skipped. This is in addition - * to any alpha or transparency value associated with the pixel. If - * you want all pixels to be combined, pass 0xff (255) in mask. +/* Combines the row recently read in with the existing pixels in the row. This + * routine takes care of alpha and transparency if requested. This routine also + * handles the two methods of progressive display of interlaced images, + * depending on the 'display' value; if 'display' is true then the whole row + * (dp) is filled from the start by replicating the available pixels. If + * 'display' is false only those pixels present in the pass are filled in. */ - void /* PRIVATE */ png_combine_row(png_structp png_ptr, png_bytep dp, int display) { @@ -2850,7 +2853,7 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display) if (pixel_depth < 8) { - /* For pixel depths up to 4-bpp the 8-pixel mask can be expanded to fit + /* For pixel depths up to 4 bpp the 8-pixel mask can be expanded to fit * into 32 bits, then a single loop over the bytes using the four byte * values in the 32-bit mask can be used. For the 'display' option the * expanded mask may also not require any masking within a byte. To @@ -2859,7 +2862,7 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display) * * The 'regular' case requires a mask for each of the first 6 passes, * the 'display' case does a copy for the even passes in the range - * 0..6. This has already been handled in the tst above. + * 0..6. This has already been handled in the test above. * * The masks are arranged as four bytes with the first byte to use in * the lowest bits (little-endian) regardless of the order (PACKSWAP or @@ -2867,7 +2870,7 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display) * * NOTE: the whole of this logic depends on the caller of this function * only calling it on rows appropriate to the pass. This function only - * understands the 'x' logic, the 'y' logic is handled by the caller. + * understands the 'x' logic; the 'y' logic is handled by the caller. * * The following defines allow generation of compile time constant bit * masks for each pixel depth and each possibility of swapped or not @@ -2885,7 +2888,7 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display) * the compiler even though it isn't used. Microsoft Visual C (various * versions) and the Intel C compiler are known to do this. To avoid * this the following macros are used in 1.5.6. This is a temporary - * solution to avoid destablizing the code during the release process. + * solution to avoid destabilizing the code during the release process. */ # if PNG_USE_COMPILE_TIME_MASKS # define PNG_LSR(x,s) ((x)>>((s) & 0x1f)) @@ -2930,7 +2933,7 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display) #if PNG_USE_COMPILE_TIME_MASKS /* Utility macros to construct all the masks for a depth/swap * combination. The 's' parameter says whether the format is PNG - * (big endian bytes) or not. Only the three odd numbered passes are + * (big endian bytes) or not. Only the three odd-numbered passes are * required for the display/block algorithm. */ # define S_MASKS(d,s) { S_MASK(0,d,s), S_MASK(1,d,s), S_MASK(2,d,s),\ @@ -2943,7 +2946,8 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display) /* Hence the pre-compiled masks indexed by PACKSWAP (or not), depth and * then pass: */ - static PNG_CONST png_uint_32 row_mask[2/*PACKSWAP*/][3/*depth*/][6] = { + static PNG_CONST png_uint_32 row_mask[2/*PACKSWAP*/][3/*depth*/][6] = + { /* Little-endian byte masks for PACKSWAP */ { S_MASKS(1,0), S_MASKS(2,0), S_MASKS(4,0) }, /* Normal (big-endian byte) masks - PNG format */ @@ -2953,7 +2957,8 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display) /* display_mask has only three entries for the odd passes, so index by * pass>>1. */ - static PNG_CONST png_uint_32 display_mask[2][3][3] = { + static PNG_CONST png_uint_32 display_mask[2][3][3] = + { /* Little-endian byte masks for PACKSWAP */ { B_MASKS(1,0), B_MASKS(2,0), B_MASKS(4,0) }, /* Normal (big-endian byte) masks - PNG format */ @@ -3129,7 +3134,7 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display) /* Check for double byte alignment and, if possible, use a * 16-bit copy. Don't attempt this for narrow images - ones that * are less than an interlace panel wide. Don't attempt it for - * wide bytes-to-copy either - use the png_memcpy there. + * wide bytes_to_copy either - use the png_memcpy there. */ if (bytes_to_copy < 16 /*else use png_memcpy*/ && png_isaligned(dp, png_uint_16) && @@ -3498,132 +3503,252 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, } #endif /* PNG_READ_INTERLACING_SUPPORTED */ -/* 1.5.6: Changed to just take a png_row_info (not png_ptr) and to ignore bad - * adaptive filter bytes. - */ -void /* PRIVATE */ -png_read_filter_row(png_row_infop row_info, png_bytep row, - png_const_bytep prev_row, int filter) +static void +png_read_filter_row_sub(png_row_infop row_info, png_bytep row, + png_const_bytep prev_row) { - switch (filter) + png_size_t i; + png_size_t istop = row_info->rowbytes; + unsigned int bpp = (row_info->pixel_depth + 7) >> 3; + png_bytep rp = row + bpp; + + PNG_UNUSED(prev_row) + + for (i = bpp; i < istop; i++) { - case PNG_FILTER_VALUE_NONE: - break; + *rp = (png_byte)(((int)(*rp) + (int)(*(rp-bpp))) & 0xff); + rp++; + } +} - case PNG_FILTER_VALUE_SUB: - { - png_size_t i; - png_size_t istop = row_info->rowbytes; - unsigned int bpp = (row_info->pixel_depth + 7) >> 3; - png_bytep rp = row + bpp; - png_bytep lp = row; +static void +png_read_filter_row_up(png_row_infop row_info, png_bytep row, + png_const_bytep prev_row) +{ + png_size_t i; + png_size_t istop = row_info->rowbytes; + png_bytep rp = row; + png_const_bytep pp = prev_row; - for (i = bpp; i < istop; i++) - { - *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff); - rp++; - } - break; - } - case PNG_FILTER_VALUE_UP: - { - png_size_t i; - png_size_t istop = row_info->rowbytes; - png_bytep rp = row; - png_const_bytep pp = prev_row; + for (i = 0; i < istop; i++) + { + *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff); + rp++; + } +} - for (i = 0; i < istop; i++) - { - *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff); - rp++; - } - break; - } - case PNG_FILTER_VALUE_AVG: - { - png_size_t i; - png_bytep rp = row; - png_const_bytep pp = prev_row; - png_bytep lp = row; - unsigned int bpp = (row_info->pixel_depth + 7) >> 3; - png_size_t istop = row_info->rowbytes - bpp; - - for (i = 0; i < bpp; i++) - { - *rp = (png_byte)(((int)(*rp) + - ((int)(*pp++) / 2 )) & 0xff); +static void +png_read_filter_row_avg(png_row_infop row_info, png_bytep row, + png_const_bytep prev_row) +{ + png_size_t i; + png_bytep rp = row; + png_const_bytep pp = prev_row; + unsigned int bpp = (row_info->pixel_depth + 7) >> 3; + png_size_t istop = row_info->rowbytes - bpp; - rp++; - } + for (i = 0; i < bpp; i++) + { + *rp = (png_byte)(((int)(*rp) + + ((int)(*pp++) / 2 )) & 0xff); - for (i = 0; i < istop; i++) - { - *rp = (png_byte)(((int)(*rp) + - (int)(*pp++ + *lp++) / 2 ) & 0xff); + rp++; + } - rp++; - } - break; - } - case PNG_FILTER_VALUE_PAETH: - { - png_size_t i; - png_bytep rp = row; - png_const_bytep pp = prev_row; - png_bytep lp = row; - png_const_bytep cp = prev_row; - unsigned int bpp = (row_info->pixel_depth + 7) >> 3; - png_size_t istop=row_info->rowbytes - bpp; - - for (i = 0; i < bpp; i++) - { - *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff); - rp++; - } + for (i = 0; i < istop; i++) + { + *rp = (png_byte)(((int)(*rp) + + (int)(*pp++ + *(rp-bpp)) / 2 ) & 0xff); - for (i = 0; i < istop; i++) /* Use leftover rp,pp */ - { - int a, b, c, pa, pb, pc, p; + rp++; + } +} - a = *lp++; - b = *pp++; - c = *cp++; +static void +png_read_filter_row_paeth_1byte_pixel(png_row_infop row_info, png_bytep row, + png_const_bytep prev_row) +{ + png_bytep rp_end = row + row_info->rowbytes; + int a, c; - p = b - c; - pc = a - c; + /* First pixel/byte */ + c = *prev_row++; + a = *row + c; + *row++ = (png_byte)a; -#ifdef PNG_USE_ABS - pa = abs(p); - pb = abs(pc); - pc = abs(p + pc); -#else - pa = p < 0 ? -p : p; - pb = pc < 0 ? -pc : pc; - pc = (p + pc) < 0 ? -(p + pc) : p + pc; -#endif + /* Remainder */ + while (row < rp_end) + { + int b, pa, pb, pc, p; - /* - if (pa <= pb && pa <= pc) - p = a; + a &= 0xff; /* From previous iteration or start */ + b = *prev_row++; - else if (pb <= pc) - p = b; + p = b - c; + pc = a - c; - else - p = c; - */ +# ifdef PNG_USE_ABS + pa = abs(p); + pb = abs(pc); + pc = abs(p + pc); +# else + pa = p < 0 ? -p : p; + pb = pc < 0 ? -pc : pc; + pc = (p + pc) < 0 ? -(p + pc) : p + pc; +# endif - p = (pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c; + /* Find the best predictor, the least of pa, pb, pc favoring the earlier + * ones in the case of a tie. + */ + if (pb < pa) pa = pb, a = b; + if (pc < pa) a = c; - *rp = (png_byte)(((int)(*rp) + p) & 0xff); - rp++; - } + /* Calculate the current pixel in a, and move the previous row pixel to c + * for the next time round the loop + */ + c = b; + a += *row; + *row++ = (png_byte)a; + } +} + +static void +png_read_filter_row_paeth_multibyte_pixel(png_row_infop row_info, png_bytep row, + png_const_bytep prev_row) +{ + int bpp = (row_info->pixel_depth + 7) >> 3; + png_bytep rp_end = row + bpp; + + /* Process the first pixel in the row completely (this is the same as 'up' + * because there is only one candidate predictor for the first row). + */ + while (row < rp_end) + { + int a = *row + *prev_row++; + *row++ = (png_byte)a; + } + + /* Remainder */ + rp_end += row_info->rowbytes - bpp; + + while (row < rp_end) + { + int a, b, c, pa, pb, pc, p; + + c = *(prev_row - bpp); + a = *(row - bpp); + b = *prev_row++; + + p = b - c; + pc = a - c; + +# ifdef PNG_USE_ABS + pa = abs(p); + pb = abs(pc); + pc = abs(p + pc); +# else + pa = p < 0 ? -p : p; + pb = pc < 0 ? -pc : pc; + pc = (p + pc) < 0 ? -(p + pc) : p + pc; +# endif + + if (pb < pa) pa = pb, a = b; + if (pc < pa) a = c; + + c = b; + a += *row; + *row++ = (png_byte)a; + } +} + +#ifdef PNG_ARM_NEON + +#ifdef __linux__ +#include +#include +#include + +static int png_have_hwcap(unsigned cap) +{ + FILE *f = fopen("/proc/self/auxv", "r"); + Elf32_auxv_t aux; + int have_cap = 0; + + if (!f) + return 0; + + while (fread(&aux, sizeof(aux), 1, f) > 0) + { + if (aux.a_type == AT_HWCAP && + aux.a_un.a_val & cap) + { + have_cap = 1; break; } - default: - /* NOT REACHED */ - break; } + + fclose(f); + + return have_cap; +} +#endif /* __linux__ */ + +static void +png_init_filter_functions_neon(png_structp pp, unsigned int bpp) +{ +#ifdef __linux__ + if (!png_have_hwcap(HWCAP_NEON)) + return; +#endif + + pp->read_filter[PNG_FILTER_VALUE_UP-1] = png_read_filter_row_up_neon; + + if (bpp == 3) + { + pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub3_neon; + pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg3_neon; + pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = + png_read_filter_row_paeth3_neon; + } + + else if (bpp == 4) + { + pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub4_neon; + pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg4_neon; + pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = + png_read_filter_row_paeth4_neon; + } +} +#endif /* PNG_ARM_NEON */ + +static void +png_init_filter_functions(png_structp pp) +{ + unsigned int bpp = (pp->pixel_depth + 7) >> 3; + + pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub; + pp->read_filter[PNG_FILTER_VALUE_UP-1] = png_read_filter_row_up; + pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg; + if (bpp == 1) + pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = + png_read_filter_row_paeth_1byte_pixel; + else + pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = + png_read_filter_row_paeth_multibyte_pixel; + +#ifdef PNG_ARM_NEON + png_init_filter_functions_neon(pp, bpp); +#endif +} + +void /* PRIVATE */ +png_read_filter_row(png_structp pp, png_row_infop row_info, png_bytep row, + png_const_bytep prev_row, int filter) +{ + if (pp->read_filter[0] == NULL) + png_init_filter_functions(pp); + if (filter > PNG_FILTER_VALUE_NONE && filter < PNG_FILTER_VALUE_LAST) + pp->read_filter[filter-1](row_info, row, prev_row); } #ifdef PNG_SEQUENTIAL_READ_SUPPORTED @@ -3811,6 +3936,16 @@ png_read_start_row(png_structp png_ptr) max_pixel_depth = png_ptr->pixel_depth; + /* WARNING: * png_read_transform_info (pngrtran.c) performs a simpliar set of + * calculations to calculate the final pixel depth, then + * png_do_read_transforms actually does the transforms. This means that the + * code which effectively calculates this value is actually repeated in three + * separate places. They must all match. Innocent changes to the order of + * transformations can and will break libpng in a way that causes memory + * overwrites. + * + * TODO: fix this. + */ #ifdef PNG_READ_PACK_SUPPORTED if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8) max_pixel_depth = 8; @@ -3869,10 +4004,7 @@ png_read_start_row(png_structp png_ptr) #ifdef PNG_READ_FILLER_SUPPORTED if (png_ptr->transformations & (PNG_FILLER)) { - if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - max_pixel_depth = 32; - - else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) + if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) { if (max_pixel_depth <= 8) max_pixel_depth = 16; @@ -3881,7 +4013,8 @@ png_read_start_row(png_structp png_ptr) max_pixel_depth = 32; } - else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB || + png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) { if (max_pixel_depth <= 32) max_pixel_depth = 32;