/* pngread.c - read a PNG file
*
- * Last changed in libpng 1.6.17 [March 26, 2015]
- * Copyright (c) 1998-2002,2004,2006-2015 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.)
+ * Copyright (c) 2018-2019 Cosmin Truta
+ * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
{
#ifndef PNG_USER_MEM_SUPPORTED
png_structp png_ptr = png_create_png_struct(user_png_ver, error_ptr,
- error_fn, warn_fn, NULL, NULL, NULL);
+ error_fn, warn_fn, NULL, NULL, NULL);
#else
return png_create_read_struct_2(user_png_ver, error_ptr, error_fn,
- warn_fn, NULL, NULL, NULL);
+ warn_fn, NULL, NULL, NULL);
}
/* Alternate create PNG structure for reading, and allocate any memory
png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED)
{
png_structp png_ptr = png_create_png_struct(user_png_ver, error_ptr,
- error_fn, warn_fn, mem_ptr, malloc_fn, free_fn);
+ error_fn, warn_fn, mem_ptr, malloc_fn, free_fn);
#endif /* USER_MEM */
if (png_ptr != NULL)
}
else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
+ {
+ png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT;
png_ptr->mode |= PNG_AFTER_IDAT;
+ }
/* This should be a binary subdivision search or a hash for
* matching the chunk name rather than a linear search.
png_handle_cHRM(png_ptr, info_ptr, length);
#endif
+#ifdef PNG_READ_eXIf_SUPPORTED
+ else if (chunk_name == png_eXIf)
+ png_handle_eXIf(png_ptr, info_ptr, length);
+#endif
+
#ifdef PNG_READ_gAMA_SUPPORTED
else if (chunk_name == png_gAMA)
png_handle_gAMA(png_ptr, info_ptr, length);
else
png_handle_unknown(png_ptr, info_ptr, length,
- PNG_HANDLE_CHUNK_AS_DEFAULT);
+ PNG_HANDLE_CHUNK_AS_DEFAULT);
}
}
#endif /* SEQUENTIAL_READ */
/* New in 1.6.0 this avoids the bug of doing the initializations twice */
else
png_app_error(png_ptr,
- "png_read_update_info/png_start_read_image: duplicate call");
+ "png_read_update_info/png_start_read_image: duplicate call");
}
}
/* New in 1.6.0 this avoids the bug of doing the initializations twice */
else
png_app_error(png_ptr,
- "png_start_read_image/png_read_update_info: duplicate call");
+ "png_start_read_image/png_read_update_info: duplicate call");
}
}
#endif /* SEQUENTIAL_READ */
for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
{
- png_uint_32 s0 = (*(rp ) << 8) | *(rp + 1);
- png_uint_32 s1 = (*(rp + 2) << 8) | *(rp + 3);
- png_uint_32 s2 = (*(rp + 4) << 8) | *(rp + 5);
+ png_uint_32 s0 = (png_uint_32)(*(rp ) << 8) | *(rp + 1);
+ png_uint_32 s1 = (png_uint_32)(*(rp + 2) << 8) | *(rp + 3);
+ png_uint_32 s2 = (png_uint_32)(*(rp + 4) << 8) | *(rp + 5);
png_uint_32 red = (s0 + s1 + 65536) & 0xffff;
png_uint_32 blue = (s2 + s1 + 65536) & 0xffff;
*(rp ) = (png_byte)((red >> 8) & 0xff);
png_error(png_ptr, "Invalid attempt to read row data");
/* Fill the row with IDAT data: */
+ png_ptr->row_buf[0]=255; /* to force error if no data was found */
png_read_IDAT_data(png_ptr, png_ptr->row_buf, row_info.rowbytes + 1);
if (png_ptr->row_buf[0] > PNG_FILTER_VALUE_NONE)
{
if (png_ptr->row_buf[0] < PNG_FILTER_VALUE_LAST)
png_read_filter_row(png_ptr, &row_info, png_ptr->row_buf + 1,
- png_ptr->prev_row + 1, png_ptr->row_buf[0]);
+ png_ptr->prev_row + 1, png_ptr->row_buf[0]);
else
png_error(png_ptr, "bad adaptive filter value");
}
{
if (png_ptr->pass < 6)
png_do_read_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass,
- png_ptr->transformations);
+ png_ptr->transformations);
if (dsp_row != NULL)
png_combine_row(png_ptr, dsp_row, 1/*display*/);
* but the caller should do it!
*/
png_warning(png_ptr, "Interlace handling should be turned on when "
+ "using png_read_image");
+ /* Make sure this is set correctly */
+ png_ptr->num_rows = png_ptr->height;
+ }
+
+ /* Obtain the pass number, which also turns on the PNG_INTERLACE flag in
+ * the above error case.
+ */
+ pass = png_set_interlace_handling(png_ptr);
+ }
+#else
+ if (png_ptr->interlaced)
+ png_error(png_ptr,
+ "Cannot read interlaced image -- interlace handler disabled");
+
+ pass = 1;
+#endif
+
+ image_height=png_ptr->height;
+
+ for (j = 0; j < pass; j++)
+ {
+ rp = image;
+ for (i = 0; i < image_height; i++)
+ {
+ png_read_row(png_ptr, *rp, NULL);
+ rp++;
+ }
+ }
+}
+
+#ifdef __TIZEN__
+void PNGAPI
+png_read_image_with_pick_color(png_structp png_ptr, png_bytepp image, PngPickColor *pickcolor)
+{
+ png_uint_32 i, image_height;
+ int pass, j;
+ png_uint_32 /*k = 0,*/ image_bpp = 0, image_width;
+ png_bytepp rp;
+ //png_bytep rc;
+ unsigned int npixels;
+ int perc_enable_y1, perc_enable_y2;
+ png_debug(1, "in png_read_image");
+
+ if (png_ptr == NULL || pickcolor == NULL)
+ return;
+
+#ifdef PNG_READ_INTERLACING_SUPPORTED
+ if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
+ {
+ pass = png_set_interlace_handling(png_ptr);
+ /* And make sure transforms are initialized. */
+ png_start_read_image(png_ptr);
+ }
+ else
+ {
+ if (png_ptr->interlaced && !(png_ptr->transformations & PNG_INTERLACE))
+ {
+ /* Caller called png_start_read_image or png_read_update_info without
+ * first turning on the PNG_INTERLACE transform. We can fix this here,
+ * but the caller should do it!
+ */
+ png_warning(png_ptr, "Interlace handling should be turned on when "
"using png_read_image");
/* Make sure this is set correctly */
png_ptr->num_rows = png_ptr->height;
#endif
image_height=png_ptr->height;
+ image_bpp=png_ptr->rowbytes;
+ image_width=png_ptr->width;
+ png_ptr->user_chunk_ptr = pickcolor;
+
+ if(pickcolor->perc < 0)
+ {
+ png_error(png_ptr, "ColorPick percentage is negative");
+ return;
+ }
+ if( (pickcolor->region < PNG_COLORPICK_TOP) || (pickcolor->region > PNG_COLORPICK_BOTTOM))
+ {
+ png_error(png_ptr, "ColorPick Region is out of bound");
+ return;
+ }
+ if(pickcolor->region == PNG_COLORPICK_TOP)
+ {
+ perc_enable_y1 = 0;
+ perc_enable_y2 = (pickcolor->perc*image_height/100) - 1;
+ }
+ else if(pickcolor->region == PNG_COLORPICK_MIDDLE)
+ {
+ perc_enable_y1 = (image_height/2) - (((pickcolor->perc/2)*image_height)/100);
+ perc_enable_y2 = perc_enable_y1 + ((pickcolor->perc*image_height)/100) - 1;
+ }
+ else
+ {
+ perc_enable_y1 = (image_height) - ( pickcolor->perc * image_height / 100 );
+ perc_enable_y2 = image_height - 1;
+ }
for (j = 0; j < pass; j++)
{
rp = image;
for (i = 0; i < image_height; i++)
{
+ pickcolor->enable = 0;
+ if( pickcolor->perc > 0 )
+ {
+ if( (int)i >= perc_enable_y1 && (int)i <= perc_enable_y2)
+ {
+ pickcolor->enable = 1;
+ }
+ }
+ else
+ {
+ if( ((int)i >= pickcolor->y1) && ((int)i <= pickcolor->y2) )
+ {
+ pickcolor->enable = 1;
+ }
+ }
png_read_row(png_ptr, *rp, NULL);
rp++;
}
}
+
+
+ if(pickcolor->perc > 0)
+ {
+ npixels = (pickcolor->perc*image_height*image_width)/100;
+ }
+ else
+ {
+ npixels = (pickcolor->x2-pickcolor->x1+1)*(pickcolor->y2-pickcolor->y1+1);
+ }
+ if(npixels > 0)
+ {
+ pickcolor->sumR = pickcolor->sumR/npixels;
+ pickcolor->sumG = pickcolor->sumG/npixels;
+ pickcolor->sumB = pickcolor->sumB/npixels;
+ }
}
+#endif /* __TIZEN__ */
#endif /* SEQUENTIAL_READ */
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
#ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED
/* Report invalid palette index; added at libng-1.5.10 */
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
- png_ptr->num_palette_max > png_ptr->num_palette)
- png_benign_error(png_ptr, "Read palette index exceeding num_palette");
+ png_ptr->num_palette_max > png_ptr->num_palette)
+ png_benign_error(png_ptr, "Read palette index exceeding num_palette");
#endif
do
png_uint_32 length = png_read_chunk_header(png_ptr);
png_uint_32 chunk_name = png_ptr->chunk_name;
+ if (chunk_name != png_IDAT)
+ png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT;
+
if (chunk_name == png_IEND)
png_handle_IEND(png_ptr, info_ptr, length);
{
if (chunk_name == png_IDAT)
{
- if ((length > 0) ||
- (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) != 0)
- png_benign_error(png_ptr, "Too many IDATs found");
+ if ((length > 0 && !(png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED))
+ || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) != 0)
+ png_benign_error(png_ptr, ".Too many IDATs found");
}
png_handle_unknown(png_ptr, info_ptr, length, keep);
if (chunk_name == png_PLTE)
else if (chunk_name == png_IDAT)
{
/* Zero length IDATs are legal after the last IDAT has been
- * read, but not after other chunks have been read.
+ * read, but not after other chunks have been read. 1.6 does not
+ * always read all the deflate data; specifically it cannot be relied
+ * upon to read the Adler32 at the end. If it doesn't ignore IDAT
+ * chunks which are longer than zero as well:
*/
- if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) != 0)
- png_benign_error(png_ptr, "Too many IDATs found");
+ if ((length > 0 && !(png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED))
+ || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) != 0)
+ png_benign_error(png_ptr, "..Too many IDATs found");
png_crc_finish(png_ptr, length);
}
png_handle_cHRM(png_ptr, info_ptr, length);
#endif
+#ifdef PNG_READ_eXIf_SUPPORTED
+ else if (chunk_name == png_eXIf)
+ png_handle_eXIf(png_ptr, info_ptr, length);
+#endif
+
#ifdef PNG_READ_gAMA_SUPPORTED
else if (chunk_name == png_gAMA)
png_handle_gAMA(png_ptr, info_ptr, length);
else
png_handle_unknown(png_ptr, info_ptr, length,
- PNG_HANDLE_CHUNK_AS_DEFAULT);
+ PNG_HANDLE_CHUNK_AS_DEFAULT);
} while ((png_ptr->mode & PNG_HAVE_IEND) == 0);
}
#endif /* SEQUENTIAL_READ */
png_ptr->chunk_list = NULL;
#endif
+#if defined(PNG_READ_EXPAND_SUPPORTED) && \
+ defined(PNG_ARM_NEON_IMPLEMENTATION)
+ png_free(png_ptr, png_ptr->riffled_palette);
+ png_ptr->riffled_palette = NULL;
+#endif
+
/* NOTE: the 'setjmp' buffer may still be allocated and the memory and error
* callbacks are still set at this point. They are required to complete the
* destruction of the png_struct itself.
#ifdef PNG_INFO_IMAGE_SUPPORTED
void PNGAPI
png_read_png(png_structrp png_ptr, png_inforp info_ptr,
- int transforms,
- voidp params)
+ int transforms, voidp params)
{
if (png_ptr == NULL || info_ptr == NULL)
return;
if (info_ptr != NULL)
{
png_controlp control = png_voidcast(png_controlp,
- png_malloc_warn(png_ptr, (sizeof *control)));
+ png_malloc_warn(png_ptr, (sizeof *control)));
if (control != NULL)
{
png_structrp png_ptr = image->opaque->png_ptr;
png_inforp info_ptr = image->opaque->info_ptr;
+#ifdef PNG_BENIGN_ERRORS_SUPPORTED
png_set_benign_errors(png_ptr, 1/*warn*/);
+#endif
png_read_info(png_ptr, info_ptr);
/* Do this the fast way; just read directly out of png_struct. */
break;
case PNG_COLOR_TYPE_PALETTE:
- cmap_entries = png_ptr->num_palette;
+ cmap_entries = (png_uint_32)png_ptr->num_palette;
break;
default:
else
return png_image_error(image,
- "png_image_begin_read_from_stdio: invalid argument");
+ "png_image_begin_read_from_stdio: invalid argument");
}
else if (image != NULL)
return png_image_error(image,
- "png_image_begin_read_from_stdio: incorrect PNG_IMAGE_VERSION");
+ "png_image_begin_read_from_stdio: incorrect PNG_IMAGE_VERSION");
return 0;
}
else
return png_image_error(image,
- "png_image_begin_read_from_file: invalid argument");
+ "png_image_begin_read_from_file: invalid argument");
}
else if (image != NULL)
return png_image_error(image,
- "png_image_begin_read_from_file: incorrect PNG_IMAGE_VERSION");
+ "png_image_begin_read_from_file: incorrect PNG_IMAGE_VERSION");
return 0;
}
#endif /* STDIO */
static void PNGCBAPI
-png_image_memory_read(png_structp png_ptr, png_bytep out, png_size_t need)
+png_image_memory_read(png_structp png_ptr, png_bytep out, size_t need)
{
if (png_ptr != NULL)
{
if (cp != NULL)
{
png_const_bytep memory = cp->memory;
- png_size_t size = cp->size;
+ size_t size = cp->size;
if (memory != NULL && size >= need)
{
}
int PNGAPI png_image_begin_read_from_memory(png_imagep image,
- png_const_voidp memory, png_size_t size)
+ png_const_voidp memory, size_t size)
{
if (image != NULL && image->version == PNG_IMAGE_VERSION)
{
else
return png_image_error(image,
- "png_image_begin_read_from_memory: invalid argument");
+ "png_image_begin_read_from_memory: invalid argument");
}
else if (image != NULL)
return png_image_error(image,
- "png_image_begin_read_from_memory: incorrect PNG_IMAGE_VERSION");
+ "png_image_begin_read_from_memory: incorrect PNG_IMAGE_VERSION");
return 0;
}
* errors (which are unfortunately quite common.)
*/
{
- static PNG_CONST png_byte chunks_to_process[] = {
+ static const png_byte chunks_to_process[] = {
98, 75, 71, 68, '\0', /* bKGD */
99, 72, 82, 77, '\0', /* cHRM */
103, 65, 77, 65, '\0', /* gAMA */
* IHDR, PLTE, tRNS, IDAT, and IEND chunks.
*/
png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_NEVER,
- NULL, -1);
+ NULL, -1);
/* But do not ignore image data handling chunks */
png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_AS_DEFAULT,
- chunks_to_process, (int)/*SAFE*/(sizeof chunks_to_process)/5);
- }
+ chunks_to_process, (int)/*SAFE*/(sizeof chunks_to_process)/5);
+ }
}
# define PNG_SKIP_CHUNKS(p) png_image_skip_unused_chunks(p)
#ifdef __GNUC__
default:
png_error(display->image->opaque->png_ptr,
- "unexpected encoding (internal error)");
+ "unexpected encoding (internal error)");
#endif
}
static png_uint_32
png_colormap_compose(png_image_read_control *display,
- png_uint_32 foreground, int foreground_encoding, png_uint_32 alpha,
- png_uint_32 background, int encoding)
+ png_uint_32 foreground, int foreground_encoding, png_uint_32 alpha,
+ png_uint_32 background, int encoding)
{
/* The file value is composed on the background, the background has the given
* encoding and so does the result, the file is encoded with P_FILE and the
*/
static void
png_create_colormap_entry(png_image_read_control *display,
- png_uint_32 ip, png_uint_32 red, png_uint_32 green, png_uint_32 blue,
- png_uint_32 alpha, int encoding)
+ png_uint_32 ip, png_uint_32 red, png_uint_32 green, png_uint_32 blue,
+ png_uint_32 alpha, int encoding)
{
png_imagep image = display->image;
- const int output_encoding = (image->format & PNG_FORMAT_FLAG_LINEAR) != 0 ?
- P_LINEAR : P_sRGB;
- const int convert_to_Y = (image->format & PNG_FORMAT_FLAG_COLOR) == 0 &&
- (red != green || green != blue);
+ int output_encoding = (image->format & PNG_FORMAT_FLAG_LINEAR) != 0 ?
+ P_LINEAR : P_sRGB;
+ int convert_to_Y = (image->format & PNG_FORMAT_FLAG_COLOR) == 0 &&
+ (red != green || green != blue);
if (ip > 255)
png_error(image->opaque->png_ptr, "color-map index out of range");
/* Store the value. */
{
# ifdef PNG_FORMAT_AFIRST_SUPPORTED
- const int afirst = (image->format & PNG_FORMAT_FLAG_AFIRST) != 0 &&
+ int afirst = (image->format & PNG_FORMAT_FLAG_AFIRST) != 0 &&
(image->format & PNG_FORMAT_FLAG_ALPHA) != 0;
# else
# define afirst 0
# endif
# ifdef PNG_FORMAT_BGR_SUPPORTED
- const int bgr = (image->format & PNG_FORMAT_FLAG_BGR) != 0 ? 2 : 0;
+ int bgr = (image->format & PNG_FORMAT_FLAG_BGR) != 0 ? 2 : 0;
# else
# define bgr 0
# endif
{
case 4:
entry[afirst ? 0 : 3] = (png_uint_16)alpha;
- /* FALL THROUGH */
+ /* FALLTHROUGH */
case 3:
if (alpha < 65535)
case 2:
entry[1 ^ afirst] = (png_uint_16)alpha;
- /* FALL THROUGH */
+ /* FALLTHROUGH */
case 1:
if (alpha < 65535)
{
case 4:
entry[afirst ? 0 : 3] = (png_byte)alpha;
+ /* FALLTHROUGH */
case 3:
entry[afirst + (2 ^ bgr)] = (png_byte)blue;
entry[afirst + 1] = (png_byte)green;
case 2:
entry[1 ^ afirst] = (png_byte)alpha;
+ /* FALLTHROUGH */
case 1:
entry[afirst] = (png_byte)green;
break;
for (i=0; i<256; ++i)
png_create_colormap_entry(display, i, i, i, i, 255, P_FILE);
- return i;
+ return (int)i;
}
static int
for (i=0; i<256; ++i)
png_create_colormap_entry(display, i, i, i, i, 255, P_sRGB);
- return i;
+ return (int)i;
}
#define PNG_GRAY_COLORMAP_ENTRIES 256
for (g=0; g<6; ++g)
png_create_colormap_entry(display, i++, g*51, g*51, g*51, a*51,
- P_sRGB);
+ P_sRGB);
}
- return i;
+ return (int)i;
}
#define PNG_GA_COLORMAP_ENTRIES 256
for (b=0; b<6; ++b)
png_create_colormap_entry(display, i++, r*51, g*51, b*51, 255,
- P_sRGB);
+ P_sRGB);
}
}
- return i;
+ return (int)i;
}
#define PNG_RGB_COLORMAP_ENTRIES 216
{
png_image_read_control *display =
png_voidcast(png_image_read_control*, argument);
- const png_imagep image = display->image;
+ png_imagep image = display->image;
- const png_structrp png_ptr = image->opaque->png_ptr;
- const png_uint_32 output_format = image->format;
- const int output_encoding = (output_format & PNG_FORMAT_FLAG_LINEAR) != 0 ?
+ png_structrp png_ptr = image->opaque->png_ptr;
+ png_uint_32 output_format = image->format;
+ int output_encoding = (output_format & PNG_FORMAT_FLAG_LINEAR) != 0 ?
P_LINEAR : P_sRGB;
unsigned int cmap_entries;
else if (display->background == NULL /* no way to remove it */)
png_error(png_ptr,
- "a background color must be supplied to remove alpha/transparency");
+ "background color must be supplied to remove alpha/transparency");
/* Get a copy of the background color (this avoids repeating the checks
* below.) The encoding is 8-bit sRGB or 16-bit linear, depending on the
*/
if (i != trans)
png_create_colormap_entry(display, i, val, val, val, 255,
- P_FILE/*8-bit with file gamma*/);
+ P_FILE/*8-bit with file gamma*/);
/* Else this entry is transparent. The colors don't matter if
* there is an alpha channel (back_alpha == 0), but it does no
*/
else
png_create_colormap_entry(display, i, back_r, back_g, back_b,
- back_alpha, output_encoding);
+ back_alpha, output_encoding);
}
/* We need libpng to preserve the original encoding. */
if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries)
png_error(png_ptr, "gray[16] color-map: too few entries");
- cmap_entries = make_gray_colormap(display);
+ cmap_entries = (unsigned int)make_gray_colormap(display);
if (png_ptr->num_trans > 0)
{
* matches.
*/
png_create_colormap_entry(display, gray, back_g, back_g,
- back_g, 65535, P_LINEAR);
+ back_g, 65535, P_LINEAR);
}
/* The background passed to libpng, however, must be the
* doesn't.
*/
png_set_background_fixed(png_ptr, &c,
- PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/,
- 0/*gamma: not used*/);
+ PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/,
+ 0/*gamma: not used*/);
output_processing = PNG_CMAP_NONE;
break;
* background color at full precision.
*/
png_create_colormap_entry(display, 254, back_r, back_g, back_b,
- back_alpha, output_encoding);
+ back_alpha, output_encoding);
}
else
if (PNG_GA_COLORMAP_ENTRIES > image->colormap_entries)
png_error(png_ptr, "gray+alpha color-map: too few entries");
- cmap_entries = make_ga_colormap(display);
+ cmap_entries = (unsigned int)make_ga_colormap(display);
background_index = PNG_CMAP_GA_BACKGROUND;
output_processing = PNG_CMAP_GA;
if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries)
png_error(png_ptr, "gray-alpha color-map: too few entries");
- cmap_entries = make_gray_colormap(display);
+ cmap_entries = (unsigned int)make_gray_colormap(display);
if (output_encoding == P_LINEAR)
{
/* And make sure the corresponding palette entry matches. */
png_create_colormap_entry(display, gray, back_g, back_g,
- back_g, 65535, P_LINEAR);
+ back_g, 65535, P_LINEAR);
}
/* The background passed to libpng, however, must be the sRGB
c.gray = c.red = c.green = c.blue = (png_uint_16)gray;
png_set_background_fixed(png_ptr, &c,
- PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/,
- 0/*gamma: not used*/);
+ PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/,
+ 0/*gamma: not used*/);
output_processing = PNG_CMAP_NONE;
}
{
png_uint_32 gray = (i * 256 + 115) / 231;
png_create_colormap_entry(display, i++, gray, gray, gray,
- 255, P_sRGB);
+ 255, P_sRGB);
}
/* NOTE: this preserves the full precision of the application
background_index = i;
png_create_colormap_entry(display, i++, back_r, back_g, back_b,
#ifdef __COVERITY__
- /* Coverity claims that output_encoding cannot be 2 (P_LINEAR)
- * here.
- */ 255U,
+ /* Coverity claims that output_encoding
+ * cannot be 2 (P_LINEAR) here.
+ */ 255U,
#else
- output_encoding == P_LINEAR ? 65535U : 255U,
+ output_encoding == P_LINEAR ? 65535U : 255U,
#endif
- output_encoding);
+ output_encoding);
/* For non-opaque input composite on the sRGB background - this
* requires inverting the encoding for each component. The input
png_uint_32 gray = png_sRGB_table[g*51] * alpha;
png_create_colormap_entry(display, i++,
- PNG_sRGB_FROM_LINEAR(gray + back_rx),
- PNG_sRGB_FROM_LINEAR(gray + back_gx),
- PNG_sRGB_FROM_LINEAR(gray + back_bx), 255, P_sRGB);
+ PNG_sRGB_FROM_LINEAR(gray + back_rx),
+ PNG_sRGB_FROM_LINEAR(gray + back_gx),
+ PNG_sRGB_FROM_LINEAR(gray + back_bx), 255, P_sRGB);
}
}
* png_set_tRNS_to_alpha before png_set_background_fixed.
*/
png_set_rgb_to_gray_fixed(png_ptr, PNG_ERROR_ACTION_NONE, -1,
- -1);
+ -1);
data_encoding = P_sRGB;
/* The output will now be one or two 8-bit gray or gray+alpha
if (PNG_GA_COLORMAP_ENTRIES > image->colormap_entries)
png_error(png_ptr, "rgb[ga] color-map: too few entries");
- cmap_entries = make_ga_colormap(display);
+ cmap_entries = (unsigned int)make_ga_colormap(display);
background_index = PNG_CMAP_GA_BACKGROUND;
output_processing = PNG_CMAP_GA;
}
png_ptr->num_trans > 0) &&
png_gamma_not_sRGB(png_ptr->colorspace.gamma) != 0)
{
- cmap_entries = make_gray_file_colormap(display);
+ cmap_entries = (unsigned int)make_gray_file_colormap(display);
data_encoding = P_FILE;
}
else
- cmap_entries = make_gray_colormap(display);
+ cmap_entries = (unsigned int)make_gray_colormap(display);
/* But if the input has alpha or transparency it must be removed
*/
gray = png_sRGB_table[gray]; /* now P_LINEAR */
gray = PNG_DIV257(png_gamma_16bit_correct(gray,
- png_ptr->colorspace.gamma)); /* now P_FILE */
+ png_ptr->colorspace.gamma)); /* now P_FILE */
/* And make sure the corresponding palette entry contains
* exactly the required sRGB value.
*/
png_create_colormap_entry(display, gray, back_g, back_g,
- back_g, 0/*unused*/, output_encoding);
+ back_g, 0/*unused*/, output_encoding);
}
else if (output_encoding == P_LINEAR)
*/
expand_tRNS = 1;
png_set_background_fixed(png_ptr, &c,
- PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/,
- 0/*gamma: not used*/);
+ PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/,
+ 0/*gamma: not used*/);
}
output_processing = PNG_CMAP_NONE;
if (PNG_RGB_COLORMAP_ENTRIES+1+27 > image->colormap_entries)
png_error(png_ptr, "rgb+alpha color-map: too few entries");
- cmap_entries = make_rgb_colormap(display);
+ cmap_entries = (unsigned int)make_rgb_colormap(display);
/* Add a transparent entry. */
png_create_colormap_entry(display, cmap_entries, 255, 255,
- 255, 0, P_sRGB);
+ 255, 0, P_sRGB);
/* This is stored as the background index for the processing
* algorithm.
*/
for (b=0; b<256; b = (b << 1) | 0x7f)
png_create_colormap_entry(display, cmap_entries++,
- r, g, b, 128, P_sRGB);
+ r, g, b, 128, P_sRGB);
}
}
if (PNG_RGB_COLORMAP_ENTRIES+1+27 > image->colormap_entries)
png_error(png_ptr, "rgb-alpha color-map: too few entries");
- cmap_entries = make_rgb_colormap(display);
+ cmap_entries = (unsigned int)make_rgb_colormap(display);
png_create_colormap_entry(display, cmap_entries, back_r,
- back_g, back_b, 0/*unused*/, output_encoding);
+ back_g, back_b, 0/*unused*/, output_encoding);
if (output_encoding == P_LINEAR)
{
* index.
*/
if (memcmp((png_const_bytep)display->colormap +
- sample_size * cmap_entries,
- (png_const_bytep)display->colormap +
- sample_size * PNG_RGB_INDEX(r,g,b),
+ sample_size * cmap_entries,
+ (png_const_bytep)display->colormap +
+ sample_size * PNG_RGB_INDEX(r,g,b),
sample_size) != 0)
{
/* The background color must be added. */
*/
for (b=0; b<256; b = (b << 1) | 0x7f)
png_create_colormap_entry(display, cmap_entries++,
- png_colormap_compose(display, r, P_sRGB, 128,
- back_r, output_encoding),
- png_colormap_compose(display, g, P_sRGB, 128,
- back_g, output_encoding),
- png_colormap_compose(display, b, P_sRGB, 128,
- back_b, output_encoding),
- 0/*unused*/, output_encoding);
+ png_colormap_compose(display, r, P_sRGB, 128,
+ back_r, output_encoding),
+ png_colormap_compose(display, g, P_sRGB, 128,
+ back_g, output_encoding),
+ png_colormap_compose(display, b, P_sRGB, 128,
+ back_b, output_encoding),
+ 0/*unused*/, output_encoding);
}
}
c.blue = (png_uint_16)back_b;
png_set_background_fixed(png_ptr, &c,
- PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/,
- 0/*gamma: not used*/);
+ PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/,
+ 0/*gamma: not used*/);
output_processing = PNG_CMAP_RGB;
}
if (PNG_RGB_COLORMAP_ENTRIES > image->colormap_entries)
png_error(png_ptr, "rgb color-map: too few entries");
- cmap_entries = make_rgb_colormap(display);
+ cmap_entries = (unsigned int)make_rgb_colormap(display);
output_processing = PNG_CMAP_RGB;
}
}
unsigned int num_trans = png_ptr->num_trans;
png_const_bytep trans = num_trans > 0 ? png_ptr->trans_alpha : NULL;
png_const_colorp colormap = png_ptr->palette;
- const int do_background = trans != NULL &&
+ int do_background = trans != NULL &&
(output_format & PNG_FORMAT_FLAG_ALPHA) == 0;
unsigned int i;
output_processing = PNG_CMAP_NONE;
data_encoding = P_FILE; /* Don't change from color-map indices */
- cmap_entries = png_ptr->num_palette;
+ cmap_entries = (unsigned int)png_ptr->num_palette;
if (cmap_entries > 256)
cmap_entries = 256;
- if (cmap_entries > image->colormap_entries)
+ if (cmap_entries > (unsigned int)image->colormap_entries)
png_error(png_ptr, "palette color-map: too few entries");
for (i=0; i < cmap_entries; ++i)
{
if (trans[i] == 0)
png_create_colormap_entry(display, i, back_r, back_g,
- back_b, 0, output_encoding);
+ back_b, 0, output_encoding);
else
{
* on the sRGB color in 'back'.
*/
png_create_colormap_entry(display, i,
- png_colormap_compose(display, colormap[i].red, P_FILE,
- trans[i], back_r, output_encoding),
- png_colormap_compose(display, colormap[i].green, P_FILE,
- trans[i], back_g, output_encoding),
- png_colormap_compose(display, colormap[i].blue, P_FILE,
- trans[i], back_b, output_encoding),
- output_encoding == P_LINEAR ? trans[i] * 257U :
- trans[i],
- output_encoding);
+ png_colormap_compose(display, colormap[i].red,
+ P_FILE, trans[i], back_r, output_encoding),
+ png_colormap_compose(display, colormap[i].green,
+ P_FILE, trans[i], back_g, output_encoding),
+ png_colormap_compose(display, colormap[i].blue,
+ P_FILE, trans[i], back_b, output_encoding),
+ output_encoding == P_LINEAR ? trans[i] * 257U :
+ trans[i],
+ output_encoding);
}
}
else
png_create_colormap_entry(display, i, colormap[i].red,
- colormap[i].green, colormap[i].blue,
- i < num_trans ? trans[i] : 255U, P_FILE/*8-bit*/);
+ colormap[i].green, colormap[i].blue,
+ i < num_trans ? trans[i] : 255U, P_FILE/*8-bit*/);
}
/* The PNG data may have indices packed in fewer than 8 bits, it
case P_sRGB:
/* Change to 8-bit sRGB */
png_set_alpha_mode_fixed(png_ptr, PNG_ALPHA_PNG, PNG_GAMMA_sRGB);
- /* FALL THROUGH */
+ /* FALLTHROUGH */
case P_FILE:
if (png_ptr->bit_depth > 8)
png_error(png_ptr, "bad background index (internal error)");
}
- display->colormap_processing = output_processing;
+ display->colormap_processing = (int)output_processing;
return 1/*ok*/;
}
png_image_read_and_map(png_voidp argument)
{
png_image_read_control *display = png_voidcast(png_image_read_control*,
- argument);
+ argument);
png_imagep image = display->image;
png_structrp png_ptr = image->opaque->png_ptr;
int passes;
if (alpha >= 196)
*outrow = PNG_RGB_INDEX(inrow[0], inrow[1],
- inrow[2]);
+ inrow[2]);
else if (alpha < 64)
*outrow = PNG_CMAP_RGB_ALPHA_BACKGROUND;
png_image_read_colormapped(png_voidp argument)
{
png_image_read_control *display = png_voidcast(png_image_read_control*,
- argument);
+ argument);
png_imagep image = display->image;
png_controlp control = image->opaque;
png_structrp png_ptr = control->png_ptr;
image->colormap_entries == 244 /* 216 + 1 + 27 */)
break;
- /* goto bad_output; */
- /* FALL THROUGH */
+ goto bad_output;
default:
bad_output:
else
{
- png_alloc_size_t row_bytes = display->row_bytes;
+ png_alloc_size_t row_bytes = (png_alloc_size_t)display->row_bytes;
while (--passes >= 0)
{
png_uint_32 y = image->height;
png_bytep row = png_voidcast(png_bytep, display->first_row);
- while (y-- > 0)
+ for (; y > 0; --y)
{
png_read_row(png_ptr, row, NULL);
row += row_bytes;
png_image_read_composite(png_voidp argument)
{
png_image_read_control *display = png_voidcast(png_image_read_control*,
- argument);
+ argument);
png_imagep image = display->image;
png_structrp png_ptr = image->opaque->png_ptr;
int passes;
png_image_read_background(png_voidp argument)
{
png_image_read_control *display = png_voidcast(png_image_read_control*,
- argument);
+ argument);
png_imagep image = display->image;
png_structrp png_ptr = image->opaque->png_ptr;
png_inforp info_ptr = image->opaque->info_ptr;
for (pass = 0; pass < passes; ++pass)
{
- png_bytep row = png_voidcast(png_bytep,
- display->first_row);
+ png_bytep row = png_voidcast(png_bytep, display->first_row);
unsigned int startx, stepx, stepy;
png_uint_32 y;
for (; y<height; y += stepy)
{
png_bytep inrow = png_voidcast(png_bytep,
- display->local_row);
+ display->local_row);
png_bytep outrow = first_row + y * step_row;
png_const_bytep end_row = outrow + width;
for (; y<height; y += stepy)
{
png_bytep inrow = png_voidcast(png_bytep,
- display->local_row);
+ display->local_row);
png_bytep outrow = first_row + y * step_row;
png_const_bytep end_row = outrow + width;
*/
{
png_uint_16p first_row = png_voidcast(png_uint_16p,
- display->first_row);
+ display->first_row);
/* The division by two is safe because the caller passed in a
* stride which was multiplied by 2 (below) to get row_bytes.
*/
ptrdiff_t step_row = display->row_bytes / 2;
- int preserve_alpha = (image->format & PNG_FORMAT_FLAG_ALPHA) != 0;
- unsigned int outchannels = 1+preserve_alpha;
+ unsigned int preserve_alpha = (image->format &
+ PNG_FORMAT_FLAG_ALPHA) != 0;
+ unsigned int outchannels = 1U+preserve_alpha;
int swap_alpha = 0;
# ifdef PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED
/* Read the row, which is packed: */
png_read_row(png_ptr, png_voidcast(png_bytep,
- display->local_row), NULL);
+ display->local_row), NULL);
inrow = png_voidcast(png_const_uint_16p, display->local_row);
/* Now do the pre-multiplication on each pixel in this row.
png_image_read_direct(png_voidp argument)
{
png_image_read_control *display = png_voidcast(png_image_read_control*,
- argument);
+ argument);
png_imagep image = display->image;
png_structrp png_ptr = image->opaque->png_ptr;
png_inforp info_ptr = image->opaque->info_ptr;
do_local_background = 1/*maybe*/;
png_set_rgb_to_gray_fixed(png_ptr, PNG_ERROR_ACTION_NONE,
- PNG_RGB_TO_GRAY_DEFAULT, PNG_RGB_TO_GRAY_DEFAULT);
+ PNG_RGB_TO_GRAY_DEFAULT, PNG_RGB_TO_GRAY_DEFAULT);
}
change &= ~PNG_FORMAT_FLAG_COLOR;
output_gamma = PNG_DEFAULT_sRGB;
}
+ if ((change & PNG_FORMAT_FLAG_ASSOCIATED_ALPHA) != 0)
+ {
+ mode = PNG_ALPHA_OPTIMIZED;
+ change &= ~PNG_FORMAT_FLAG_ASSOCIATED_ALPHA;
+ }
+
/* If 'do_local_background' is set check for the presence of gamma
* correction; this is part of the work-round for the libpng bug
* described above.
* final value.
*/
if (png_muldiv(>est, output_gamma, png_ptr->colorspace.gamma,
- PNG_FP_1) != 0 && png_gamma_significant(gtest) == 0)
+ PNG_FP_1) != 0 && png_gamma_significant(gtest) == 0)
do_local_background = 0;
else if (mode == PNG_ALPHA_STANDARD)
* pixels.
*/
png_set_background_fixed(png_ptr, &c,
- PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/,
- 0/*gamma: not used*/);
+ PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/,
+ 0/*gamma: not used*/);
}
else /* compose on row: implemented below. */
else
filler = 255;
-# ifdef PNG_FORMAT_AFIRST_SUPPORTED
- if ((format & PNG_FORMAT_FLAG_AFIRST) != 0)
- {
- where = PNG_FILLER_BEFORE;
- change &= ~PNG_FORMAT_FLAG_AFIRST;
- }
+#ifdef PNG_FORMAT_AFIRST_SUPPORTED
+ if ((format & PNG_FORMAT_FLAG_AFIRST) != 0)
+ {
+ where = PNG_FILLER_BEFORE;
+ change &= ~PNG_FORMAT_FLAG_AFIRST;
+ }
- else
-# endif
- where = PNG_FILLER_AFTER;
+ else
+#endif
+ where = PNG_FILLER_AFTER;
png_set_add_alpha(png_ptr, filler, where);
}
*/
if (linear != 0)
{
- PNG_CONST png_uint_16 le = 0x0001;
+ png_uint_16 le = 0x0001;
if ((*(png_const_bytep) & le) != 0)
png_set_swap(png_ptr);
else if (do_local_compose != 0) /* internal error */
png_error(png_ptr, "png_image_read: alpha channel lost");
+ if ((format & PNG_FORMAT_FLAG_ASSOCIATED_ALPHA) != 0) {
+ info_format |= PNG_FORMAT_FLAG_ASSOCIATED_ALPHA;
+ }
+
if (info_ptr->bit_depth == 16)
info_format |= PNG_FORMAT_FLAG_LINEAR;
-# ifdef PNG_FORMAT_BGR_SUPPORTED
- if ((png_ptr->transformations & PNG_BGR) != 0)
- info_format |= PNG_FORMAT_FLAG_BGR;
-# endif
+#ifdef PNG_FORMAT_BGR_SUPPORTED
+ if ((png_ptr->transformations & PNG_BGR) != 0)
+ info_format |= PNG_FORMAT_FLAG_BGR;
+#endif
-# ifdef PNG_FORMAT_AFIRST_SUPPORTED
+#ifdef PNG_FORMAT_AFIRST_SUPPORTED
if (do_local_background == 2)
{
if ((format & PNG_FORMAT_FLAG_AFIRST) != 0)
else
{
- png_alloc_size_t row_bytes = display->row_bytes;
+ png_alloc_size_t row_bytes = (png_alloc_size_t)display->row_bytes;
while (--passes >= 0)
{
png_uint_32 y = image->height;
png_bytep row = png_voidcast(png_bytep, display->first_row);
- while (y-- > 0)
+ for (; y > 0; --y)
{
png_read_row(png_ptr, row, NULL);
row += row_bytes;
int PNGAPI
png_image_finish_read(png_imagep image, png_const_colorp background,
- void *buffer, png_int_32 row_stride, void *colormap)
+ void *buffer, png_int_32 row_stride, void *colormap)
{
if (image != NULL && image->version == PNG_IMAGE_VERSION)
{
- png_uint_32 check;
+ /* Check for row_stride overflow. This check is not performed on the
+ * original PNG format because it may not occur in the output PNG format
+ * and libpng deals with the issues of reading the original.
+ */
+ unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format);
- if (row_stride == 0)
- row_stride = PNG_IMAGE_ROW_STRIDE(*image);
+ /* The following checks just the 'row_stride' calculation to ensure it
+ * fits in a signed 32-bit value. Because channels/components can be
+ * either 1 or 2 bytes in size the length of a row can still overflow 32
+ * bits; this is just to verify that the 'row_stride' argument can be
+ * represented.
+ */
+ if (image->width <= 0x7fffffffU/channels) /* no overflow */
+ {
+ png_uint_32 check;
+ png_uint_32 png_row_stride = image->width * channels;
- if (row_stride < 0)
- check = -row_stride;
+ if (row_stride == 0)
+ row_stride = (png_int_32)/*SAFE*/png_row_stride;
- else
- check = row_stride;
+ if (row_stride < 0)
+ check = (png_uint_32)(-row_stride);
- if (image->opaque != NULL && buffer != NULL &&
- check >= PNG_IMAGE_ROW_STRIDE(*image))
- {
- if ((image->format & PNG_FORMAT_FLAG_COLORMAP) == 0 ||
- (image->colormap_entries > 0 && colormap != NULL))
+ else
+ check = (png_uint_32)row_stride;
+
+ /* This verifies 'check', the absolute value of the actual stride
+ * passed in and detects overflow in the application calculation (i.e.
+ * if the app did actually pass in a non-zero 'row_stride'.
+ */
+ if (image->opaque != NULL && buffer != NULL && check >= png_row_stride)
{
- int result;
- png_image_read_control display;
-
- memset(&display, 0, (sizeof display));
- display.image = image;
- display.buffer = buffer;
- display.row_stride = row_stride;
- display.colormap = colormap;
- display.background = background;
- display.local_row = NULL;
-
- /* Choose the correct 'end' routine; for the color-map case all the
- * setup has already been done.
+ /* Now check for overflow of the image buffer calculation; this
+ * limits the whole image size to 32 bits for API compatibility with
+ * the current, 32-bit, PNG_IMAGE_BUFFER_SIZE macro.
+ *
+ * The PNG_IMAGE_BUFFER_SIZE macro is:
+ *
+ * (PNG_IMAGE_PIXEL_COMPONENT_SIZE(fmt)*height*(row_stride))
+ *
+ * And the component size is always 1 or 2, so make sure that the
+ * number of *bytes* that the application is saying are available
+ * does actually fit into a 32-bit number.
+ *
+ * NOTE: this will be changed in 1.7 because PNG_IMAGE_BUFFER_SIZE
+ * will be changed to use png_alloc_size_t; bigger images can be
+ * accommodated on 64-bit systems.
*/
- if ((image->format & PNG_FORMAT_FLAG_COLORMAP) != 0)
- result =
- png_safe_execute(image, png_image_read_colormap, &display) &&
- png_safe_execute(image, png_image_read_colormapped, &display);
+ if (image->height <=
+ 0xffffffffU/PNG_IMAGE_PIXEL_COMPONENT_SIZE(image->format)/check)
+ {
+ if ((image->format & PNG_FORMAT_FLAG_COLORMAP) == 0 ||
+ (image->colormap_entries > 0 && colormap != NULL))
+ {
+ int result;
+ png_image_read_control display;
+
+ memset(&display, 0, (sizeof display));
+ display.image = image;
+ display.buffer = buffer;
+ display.row_stride = row_stride;
+ display.colormap = colormap;
+ display.background = background;
+ display.local_row = NULL;
+
+ /* Choose the correct 'end' routine; for the color-map case
+ * all the setup has already been done.
+ */
+ if ((image->format & PNG_FORMAT_FLAG_COLORMAP) != 0)
+ result =
+ png_safe_execute(image,
+ png_image_read_colormap, &display) &&
+ png_safe_execute(image,
+ png_image_read_colormapped, &display);
- else
- result =
- png_safe_execute(image, png_image_read_direct, &display);
+ else
+ result =
+ png_safe_execute(image,
+ png_image_read_direct, &display);
+
+ png_image_free(image);
+ return result;
+ }
- png_image_free(image);
- return result;
+ else
+ return png_image_error(image,
+ "png_image_finish_read[color-map]: no color-map");
+ }
+
+ else
+ return png_image_error(image,
+ "png_image_finish_read: image too large");
}
else
return png_image_error(image,
- "png_image_finish_read[color-map]: no color-map");
+ "png_image_finish_read: invalid argument");
}
else
return png_image_error(image,
- "png_image_finish_read: invalid argument");
+ "png_image_finish_read: row_stride too large");
}
else if (image != NULL)
return png_image_error(image,
- "png_image_finish_read: damaged PNG_IMAGE_VERSION");
+ "png_image_finish_read: damaged PNG_IMAGE_VERSION");
return 0;
}