+/* $Id$ */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
fflush (stderr);
jmpbuf_ptr = png_get_error_ptr (png_ptr);
- if (jmpbuf_ptr == NULL)
- { /* we are completely hosed now */
- fprintf (stderr,
- "gd-png: EXTREMELY fatal error: jmpbuf unrecoverable; terminating.\n");
+ if (jmpbuf_ptr == NULL) { /* we are completely hosed now */
+ fprintf (stderr, "gd-png: EXTREMELY fatal error: jmpbuf unrecoverable; terminating.\n");
fflush (stderr);
exit (99);
}
static void
gdPngReadData (png_structp png_ptr, png_bytep data, png_size_t length)
{
- gdGetBuf (data, length, (gdIOCtx *) png_get_io_ptr (png_ptr));
+ int check;
+ check = gdGetBuf (data, length, (gdIOCtx *) png_get_io_ptr (png_ptr));
+ if (check != length) {
+ png_error(png_ptr, "Read Error: truncated data");
+ }
}
static void
png_byte sig[8];
png_structp png_ptr;
png_infop info_ptr;
- png_uint_32 width, height, rowbytes;
+ png_uint_32 width, height, rowbytes, w, h;
int bit_depth, color_type, interlace_type;
int num_palette, num_trans;
png_colorp palette;
/* Make sure the signature can't match by dumb luck -- TBB */
/* GRR: isn't sizeof(infile) equal to the size of the pointer? */
- memset (infile, 0, sizeof (infile));
+ memset (sig, 0, sizeof (sig));
/* first do a quick check that the file really is a PNG image; could
* have used slightly more general png_sig_cmp() function instead */
- gdGetBuf (sig, 8, infile);
- if (!png_check_sig (sig, 8))
- return NULL; /* bad signature */
+ if (gdGetBuf (sig, 8, infile) < 8) {
+ return NULL;
+ }
+
+ if (!png_check_sig (sig, 8)) { /* bad signature */
+ return NULL; /* bad signature */
+ }
#ifndef PNG_SETJMP_NOT_SUPPORTED
- png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, &gdPngJmpbufStruct,
- gdPngErrorHandler, NULL);
+ png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, &gdPngJmpbufStruct, gdPngErrorHandler, NULL);
#else
png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
#endif
- if (png_ptr == NULL)
- {
+ if (png_ptr == NULL) {
fprintf (stderr, "gd-png error: cannot allocate libpng main struct\n");
return NULL;
}
info_ptr = png_create_info_struct (png_ptr);
- if (info_ptr == NULL)
- {
+ if (info_ptr == NULL) {
fprintf (stderr, "gd-png error: cannot allocate libpng info struct\n");
png_destroy_read_struct (&png_ptr, NULL, NULL);
+
return NULL;
}
/* we could create a second info struct here (end_info), but it's only
* useful if we want to keep pre- and post-IDAT chunk info separated
- * (mainly for PNG-aware image editors and converters) */
+ * (mainly for PNG-aware image editors and converters)
+ */
/* setjmp() must be called in every non-callback function that calls a
* PNG-reading libpng function */
#ifndef PNG_SETJMP_NOT_SUPPORTED
- if (setjmp (gdPngJmpbufStruct.jmpbuf))
- {
- fprintf (stderr, "gd-png error: setjmp returns error condition\n");
+ if (setjmp (gdPngJmpbufStruct.jmpbuf)) {
+ fprintf (stderr, "gd-png error: setjmp returns error condition 1\n");
png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
+
return NULL;
}
#endif
png_set_read_fn (png_ptr, (void *) infile, gdPngReadData);
png_read_info (png_ptr, info_ptr); /* read all PNG info up to image data */
- png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
- &interlace_type, NULL, NULL);
- if ((color_type == PNG_COLOR_TYPE_RGB) ||
- (color_type == PNG_COLOR_TYPE_RGB_ALPHA))
- {
+ png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL);
+ if ((color_type == PNG_COLOR_TYPE_RGB) || (color_type == PNG_COLOR_TYPE_RGB_ALPHA)) {
im = gdImageCreateTrueColor ((int) width, (int) height);
- }
- else
- {
+ } else {
im = gdImageCreate ((int) width, (int) height);
}
- if (im == NULL)
- {
+ if (im == NULL) {
fprintf (stderr, "gd-png error: cannot allocate gdImage struct\n");
png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
gdFree (image_data);
gdFree (row_pointers);
+
return NULL;
}
- if (bit_depth == 16)
+ if (bit_depth == 16) {
png_set_strip_16 (png_ptr);
- else if (bit_depth < 8)
+ } else if (bit_depth < 8) {
png_set_packing (png_ptr); /* expand to 1 byte per pixel */
- switch (color_type)
- {
+ }
+
+ /* setjmp() must be called in every non-callback function that calls a
+ * PNG-reading libpng function
+ */
+#ifndef PNG_SETJMP_NOT_SUPPORTED
+ if (setjmp(gdPngJmpbufStruct.jmpbuf)) {
+ fprintf(stderr, "gd-png error: setjmp returns error condition 2");
+ png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+ gdFree(image_data);
+ gdFree(row_pointers);
+ if (im) {
+ gdImageDestroy(im);
+ }
+ return NULL;
+ }
+#endif
+
+ switch (color_type) {
case PNG_COLOR_TYPE_PALETTE:
png_get_PLTE (png_ptr, info_ptr, &palette, &num_palette);
#ifdef DEBUG
- fprintf (stderr, "gd-png color_type is palette, colors: %d\n",
- num_palette);
+ fprintf (stderr, "gd-png color_type is palette, colors: %d\n", num_palette);
#endif /* DEBUG */
- if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
- {
- /* gd 2.0: we support this rather thoroughly now. Grab the
- first fully transparent entry, if any, as the value of
- the simple-transparency index, mostly for backwards
- binary compatibility. The alpha channel is where it's
- really at these days. */
+ if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS)) {
+ /* gd 2.0: we support this rather thoroughly now. Grab the
+ * first fully transparent entry, if any, as the value of
+ * the simple-transparency index, mostly for backwards
+ * binary compatibility. The alpha channel is where it's
+ * really at these days.
+ */
int firstZero = 1;
png_get_tRNS (png_ptr, info_ptr, &trans, &num_trans, NULL);
- for (i = 0; i < num_trans; ++i)
- {
+ for (i = 0; i < num_trans; ++i) {
im->alpha[i] = gdAlphaMax - (trans[i] >> 1);
- if ((trans[i] == 0) && (firstZero))
- {
+ if ((trans[i] == 0) && (firstZero)) {
/* 2.0.5: long-forgotten patch from Wez Furlong */
transparent = i;
firstZero = 0;
case PNG_COLOR_TYPE_GRAY:
case PNG_COLOR_TYPE_GRAY_ALPHA:
/* create a fake palette and check for single-shade transparency */
- if ((palette =
- (png_colorp) gdMalloc (256 * sizeof (png_color))) == NULL)
- {
+ if ((palette = (png_colorp) gdMalloc (256 * sizeof (png_color))) == NULL) {
fprintf (stderr, "gd-png error: cannot allocate gray palette\n");
png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
return NULL;
}
palette_allocated = TRUE;
- if (bit_depth < 8)
- {
+ if (bit_depth < 8) {
num_palette = 1 << bit_depth;
- for (i = 0; i < 256; ++i)
- {
+ for (i = 0; i < 256; ++i) {
j = (255 * i) / (num_palette - 1);
palette[i].red = palette[i].green = palette[i].blue = j;
}
- }
- else
- {
+ } else {
num_palette = 256;
- for (i = 0; i < 256; ++i)
- {
+ for (i = 0; i < 256; ++i) {
palette[i].red = palette[i].green = palette[i].blue = i;
}
}
- if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
- {
+ if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS)) {
png_get_tRNS (png_ptr, info_ptr, NULL, NULL, &trans_gray_rgb);
- if (bit_depth == 16) /* png_set_strip_16() not yet in effect */
+ if (bit_depth == 16) { /* png_set_strip_16() not yet in effect */
transparent = trans_gray_rgb->gray >> 8;
- else
+ } else {
transparent = trans_gray_rgb->gray;
+ }
/* Note slight error in 16-bit case: up to 256 16-bit shades
* may get mapped to a single 8-bit shade, and only one of them
* is supposed to be transparent. IOW, both opaque pixels and
/* gd 2.0: we now support truecolor. See the comment above
for a rare situation in which the transparent pixel may not
work properly with 16-bit channels. */
- if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
- {
+ if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS)) {
png_get_tRNS (png_ptr, info_ptr, NULL, NULL, &trans_color_rgb);
- if (bit_depth == 16) /* png_set_strip_16() not yet in effect */
+ if (bit_depth == 16) { /* png_set_strip_16() not yet in effect */
transparent = gdTrueColor (trans_color_rgb->red >> 8,
trans_color_rgb->green >> 8,
trans_color_rgb->blue >> 8);
- else
+ } else {
transparent = gdTrueColor (trans_color_rgb->red,
trans_color_rgb->green,
trans_color_rgb->blue);
}
+ }
break;
}
if (overflow2(rowbytes, height)) {
png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
return NULL;
- }
- if ((image_data = (png_bytep) gdMalloc (rowbytes * height)) == NULL)
- {
+ }
+ image_data = (png_bytep) gdMalloc (rowbytes * height);
+ if (!image_data) {
fprintf (stderr, "gd-png error: cannot allocate image data\n");
png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
+ if (im) {
+ gdImageDestroy(im);
+ }
return NULL;
}
if (overflow2(height, sizeof (png_bytep))) {
png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
gdFree (image_data);
+ if (im) {
+ gdImageDestroy(im);
+ }
return NULL;
- }
- if ((row_pointers =
- (png_bytepp) gdMalloc (height * sizeof (png_bytep))) == NULL)
- {
+ }
+
+ row_pointers = (png_bytepp) gdMalloc (height * sizeof (png_bytep));
+ if (!row_pointers) {
fprintf (stderr, "gd-png error: cannot allocate row pointers\n");
png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
+ if (im) {
+ gdImageDestroy(im);
+ }
gdFree (image_data);
return NULL;
}
/* set the individual row_pointers to point at the correct offsets */
- for (j = 0; j < height; ++j)
- {
- row_pointers[j] = image_data + j * rowbytes;
+ for (h = 0; h < height; ++h) {
+ row_pointers[h] = image_data + h * rowbytes;
}
png_read_image (png_ptr, row_pointers); /* read whole image... */
png_read_end (png_ptr, NULL); /* ...done! */
- if (!im->trueColor)
- {
+ if (!im->trueColor) {
im->colorsTotal = num_palette;
/* load the palette and mark all entries "open" (unused) for now */
open = im->open;
- for (i = 0; i < num_palette; ++i)
- {
+ for (i = 0; i < num_palette; ++i) {
im->red[i] = palette[i].red;
im->green[i] = palette[i].green;
im->blue[i] = palette[i].blue;
open[i] = 1;
}
- for (i = num_palette; i < gdMaxColors; ++i)
- {
+ for (i = num_palette; i < gdMaxColors; ++i) {
open[i] = 1;
- }
+ }
}
/* 2.0.12: Slaven Rezic: palette images are not the only images
with a simple transparent color setting */
/* can't nuke structs until done with palette */
png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
- switch (color_type)
- {
+ switch (color_type) {
case PNG_COLOR_TYPE_RGB:
- for (j = 0; j < height; j++)
- {
+ for (h = 0; h < height; h++) {
int boffset = 0;
- for (i = 0; i < width; i++)
- {
- register png_byte r = row_pointers[j][boffset++];
- register png_byte g = row_pointers[j][boffset++];
- register png_byte b = row_pointers[j][boffset++];
- im->tpixels[j][i] = gdTrueColor (r, g, b);
+ for (w = 0; w < width; w++) {
+ register png_byte r = row_pointers[h][boffset++];
+ register png_byte g = row_pointers[h][boffset++];
+ register png_byte b = row_pointers[h][boffset++];
+ im->tpixels[h][w] = gdTrueColor (r, g, b);
}
}
break;
case PNG_COLOR_TYPE_RGB_ALPHA:
- for (j = 0; j < height; j++)
- {
+ for (h = 0; h < height; h++) {
int boffset = 0;
- for (i = 0; i < width; i++)
- {
- register png_byte r = row_pointers[j][boffset++];
- register png_byte g = row_pointers[j][boffset++];
- register png_byte b = row_pointers[j][boffset++];
- /* gd has only 7 bits of alpha channel resolution, and
- 127 is transparent, 0 opaque. A moment of convenience,
- a lifetime of compatibility. */
- register png_byte a = gdAlphaMax -
- (row_pointers[j][boffset++] >> 1);
- im->tpixels[j][i] = gdTrueColorAlpha (r, g, b, a);
+ for (w = 0; w < width; w++) {
+ register png_byte r = row_pointers[h][boffset++];
+ register png_byte g = row_pointers[h][boffset++];
+ register png_byte b = row_pointers[h][boffset++];
+
+ /* gd has only 7 bits of alpha channel resolution, and
+ * 127 is transparent, 0 opaque. A moment of convenience,
+ * a lifetime of compatibility.
+ */
+
+ register png_byte a = gdAlphaMax - (row_pointers[h][boffset++] >> 1);
+ im->tpixels[h][w] = gdTrueColorAlpha(r, g, b, a);
}
}
break;
default:
/* Palette image, or something coerced to be one */
- for (j = 0; j < height; ++j)
- {
- for (i = 0; i < width; ++i)
- {
- register png_byte idx = row_pointers[j][i];
- im->pixels[j][i] = idx;
+ for (h = 0; h < height; ++h) {
+ for (w = 0; w < width; ++w) {
+ register png_byte idx = row_pointers[h][w];
+ im->pixels[h][w] = idx;
open[idx] = 0;
}
}
}
#ifdef DEBUG
- if (!im->trueColor)
- {
- for (i = num_palette; i < gdMaxColors; ++i)
- {
- if (!open[i])
- {
+ if (!im->trueColor) {
+ for (i = num_palette; i < gdMaxColors; ++i) {
+ if (!open[i]) {
fprintf (stderr,
"gd-png warning: image data references out-of-range"
" color index (%d)\n", i);
}
#endif
- if (palette_allocated)
+ if (palette_allocated) {
gdFree (palette);
+ }
gdFree (image_data);
gdFree (row_pointers);
for (i = 0; i < j; ++i)
gdFree (row_pointers[i]);
/* 2.0.29: memory leak TBB */
- free(row_pointers);
+ gdFree(row_pointers);
return;
}
pOutputRow = *prow_pointers++;