gd_png.c (libgd-2.2.4) | : | gd_png.c (libgd-2.2.5) | ||
---|---|---|---|---|
skipping to change at line 71 | skipping to change at line 71 | |||
/* This function, aside from the extra step of retrieving the "error | /* This function, aside from the extra step of retrieving the "error | |||
* pointer" (below) and the fact that it exists within the application | * pointer" (below) and the fact that it exists within the application | |||
* rather than within libpng, is essentially identical to libpng's | * rather than within libpng, is essentially identical to libpng's | |||
* default error handler. The second point is critical: since both | * default error handler. The second point is critical: since both | |||
* setjmp() and longjmp() are called from the same code, they are | * setjmp() and longjmp() are called from the same code, they are | |||
* guaranteed to have compatible notions of how big a jmp_buf is, | * guaranteed to have compatible notions of how big a jmp_buf is, | |||
* regardless of whether _BSD_SOURCE or anything else has (or has not) | * regardless of whether _BSD_SOURCE or anything else has (or has not) | |||
* been defined. */ | * been defined. */ | |||
gd_error_ex(GD_ERROR, "gd-png: fatal libpng error: %s\n", msg); | gd_error_ex(GD_WARNING, "gd-png: fatal libpng error: %s\n", msg); | |||
jmpbuf_ptr = png_get_error_ptr (png_ptr); | jmpbuf_ptr = png_get_error_ptr (png_ptr); | |||
if (jmpbuf_ptr == NULL) { /* we are complet ely hosed now */ | if (jmpbuf_ptr == NULL) { /* we are complet ely hosed now */ | |||
gd_error_ex(GD_ERROR, "gd-png: EXTREMELY fatal error: jmpbuf unre coverable; terminating.\n"); | gd_error_ex(GD_ERROR, "gd-png: EXTREMELY fatal error: jmpbuf unre coverable; terminating.\n"); | |||
exit (99); | exit (99); | |||
} | } | |||
longjmp (jmpbuf_ptr->jmpbuf, 1); | longjmp (jmpbuf_ptr->jmpbuf, 1); | |||
} | } | |||
#endif | #endif | |||
skipping to change at line 634 | skipping to change at line 634 | |||
Nothing. | Nothing. | |||
*/ | */ | |||
BGD_DECLARE(void) gdImagePng (gdImagePtr im, FILE * outFile) | BGD_DECLARE(void) gdImagePng (gdImagePtr im, FILE * outFile) | |||
{ | { | |||
gdIOCtx *out = gdNewFileCtx (outFile); | gdIOCtx *out = gdNewFileCtx (outFile); | |||
if (out == NULL) return; | if (out == NULL) return; | |||
gdImagePngCtxEx (im, out, -1); | gdImagePngCtxEx (im, out, -1); | |||
out->gd_free (out); | out->gd_free (out); | |||
} | } | |||
static int _gdImagePngCtxEx(gdImagePtr im, gdIOCtx * outfile, int level); | ||||
/* | /* | |||
Function: gdImagePngPtr | Function: gdImagePngPtr | |||
Equivalent to calling <gdImagePngPtrEx> with compression of -1. | Equivalent to calling <gdImagePngPtrEx> with compression of -1. | |||
See <gdImagePngEx> for more information. | See <gdImagePngEx> for more information. | |||
Parameters: | Parameters: | |||
im - the image to save. | im - the image to save. | |||
skipping to change at line 656 | skipping to change at line 658 | |||
Returns: | Returns: | |||
A pointer to memory containing the image data or NULL on error. | A pointer to memory containing the image data or NULL on error. | |||
*/ | */ | |||
BGD_DECLARE(void *) gdImagePngPtr (gdImagePtr im, int *size) | BGD_DECLARE(void *) gdImagePngPtr (gdImagePtr im, int *size) | |||
{ | { | |||
void *rv; | void *rv; | |||
gdIOCtx *out = gdNewDynamicCtx (2048, NULL); | gdIOCtx *out = gdNewDynamicCtx (2048, NULL); | |||
if (out == NULL) return NULL; | if (out == NULL) return NULL; | |||
gdImagePngCtxEx (im, out, -1); | if (!_gdImagePngCtxEx (im, out, -1)) { | |||
rv = gdDPExtractData (out, size); | rv = gdDPExtractData (out, size); | |||
} else { | ||||
rv = NULL; | ||||
} | ||||
out->gd_free (out); | out->gd_free (out); | |||
return rv; | return rv; | |||
} | } | |||
/* | /* | |||
Function: gdImagePngPtrEx | Function: gdImagePngPtrEx | |||
Identical to <gdImagePngEx> except that it returns a pointer to a | Identical to <gdImagePngEx> except that it returns a pointer to a | |||
memory area with the PNG data. This memory must be freed by the | memory area with the PNG data. This memory must be freed by the | |||
caller when it is no longer needed. **The caller must invoke | caller when it is no longer needed. **The caller must invoke | |||
skipping to change at line 691 | skipping to change at line 696 | |||
Returns: | Returns: | |||
A pointer to memory containing the image data or NULL on error. | A pointer to memory containing the image data or NULL on error. | |||
*/ | */ | |||
BGD_DECLARE(void *) gdImagePngPtrEx (gdImagePtr im, int *size, int level) | BGD_DECLARE(void *) gdImagePngPtrEx (gdImagePtr im, int *size, int level) | |||
{ | { | |||
void *rv; | void *rv; | |||
gdIOCtx *out = gdNewDynamicCtx (2048, NULL); | gdIOCtx *out = gdNewDynamicCtx (2048, NULL); | |||
if (out == NULL) return NULL; | if (out == NULL) return NULL; | |||
gdImagePngCtxEx (im, out, level); | if (!_gdImagePngCtxEx (im, out, level)) { | |||
rv = gdDPExtractData (out, size); | rv = gdDPExtractData (out, size); | |||
} else { | ||||
rv = NULL; | ||||
} | ||||
out->gd_free (out); | out->gd_free (out); | |||
return rv; | return rv; | |||
} | } | |||
/* | /* | |||
Function: gdImagePngCtx | Function: gdImagePngCtx | |||
Equivalent to calling <gdImagePngCtxEx> with compression of -1. | Equivalent to calling <gdImagePngCtxEx> with compression of -1. | |||
See <gdImagePngEx> for more information. | See <gdImagePngEx> for more information. | |||
skipping to change at line 736 | skipping to change at line 744 | |||
im - the image to save. | im - the image to save. | |||
outfile - the <gdIOCtx> to write to. | outfile - the <gdIOCtx> to write to. | |||
level - compression level: 0 -> none, 1-9 -> level, -1 -> default | level - compression level: 0 -> none, 1-9 -> level, -1 -> default | |||
Returns: | Returns: | |||
Nothing. | Nothing. | |||
*/ | */ | |||
BGD_DECLARE(void) gdImagePngCtxEx (gdImagePtr im, gdIOCtx * outfile, int level) | ||||
{ | ||||
_gdImagePngCtxEx(im, outfile, level); | ||||
} | ||||
/* This routine is based in part on code from Dale Lutz (Safe Software Inc.) | /* This routine is based in part on code from Dale Lutz (Safe Software Inc.) | |||
* and in part on demo code from Chapter 15 of "PNG: The Definitive Guide" | * and in part on demo code from Chapter 15 of "PNG: The Definitive Guide" | |||
* (http://www.libpng.org/pub/png/book/). | * (http://www.libpng.org/pub/png/book/). | |||
*/ | */ | |||
BGD_DECLARE(void) gdImagePngCtxEx (gdImagePtr im, gdIOCtx * outfile, int level) | /* returns 0 on success, 1 on failure */ | |||
static int _gdImagePngCtxEx(gdImagePtr im, gdIOCtx * outfile, int level) | ||||
{ | { | |||
int i, j, bit_depth = 0, interlace_type; | int i, j, bit_depth = 0, interlace_type; | |||
int width = im->sx; | int width = im->sx; | |||
int height = im->sy; | int height = im->sy; | |||
int colors = im->colorsTotal; | int colors = im->colorsTotal; | |||
int *open = im->open; | int *open = im->open; | |||
int mapping[gdMaxColors]; /* mapping[gd_index] == png_index */ | int mapping[gdMaxColors]; /* mapping[gd_index] == png_index */ | |||
png_byte trans_values[256]; | png_byte trans_values[256]; | |||
png_color_16 trans_rgb_value; | png_color_16 trans_rgb_value; | |||
png_color palette[gdMaxColors]; | png_color palette[gdMaxColors]; | |||
png_structp png_ptr; | png_structp png_ptr; | |||
png_infop info_ptr; | png_infop info_ptr; | |||
volatile int transparent = im->transparent; | volatile int transparent = im->transparent; | |||
volatile int remap = FALSE; | volatile int remap = FALSE; | |||
#ifdef PNG_SETJMP_SUPPORTED | #ifdef PNG_SETJMP_SUPPORTED | |||
jmpbuf_wrapper jbw; | jmpbuf_wrapper jbw; | |||
#endif | #endif | |||
int ret = 0; | ||||
/* width or height of value 0 is invalid in IHDR; | /* width or height of value 0 is invalid in IHDR; | |||
see http://www.w3.org/TR/PNG-Chunks.html */ | see http://www.w3.org/TR/PNG-Chunks.html */ | |||
if (width == 0 || height ==0) return; | if (width == 0 || height ==0) return 1; | |||
#ifdef PNG_SETJMP_SUPPORTED | #ifdef PNG_SETJMP_SUPPORTED | |||
png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, | png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, | |||
&jbw, gdPngErrorHandler, | &jbw, gdPngErrorHandler, | |||
NULL); | NULL); | |||
#else | #else | |||
png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NUL L); | png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NUL L); | |||
#endif | #endif | |||
if (png_ptr == NULL) { | if (png_ptr == NULL) { | |||
gd_error("gd-png error: cannot allocate libpng main struct\n"); | gd_error("gd-png error: cannot allocate libpng main struct\n"); | |||
return; | return 1; | |||
} | } | |||
info_ptr = png_create_info_struct (png_ptr); | info_ptr = png_create_info_struct (png_ptr); | |||
if (info_ptr == NULL) { | if (info_ptr == NULL) { | |||
gd_error("gd-png error: cannot allocate libpng info struct\n"); | gd_error("gd-png error: cannot allocate libpng info struct\n"); | |||
png_destroy_write_struct (&png_ptr, (png_infopp) NULL); | png_destroy_write_struct (&png_ptr, (png_infopp) NULL); | |||
return; | return 1; | |||
} | } | |||
#ifdef PNG_SETJMP_SUPPORTED | #ifdef PNG_SETJMP_SUPPORTED | |||
if (setjmp(jbw.jmpbuf)) { | if (setjmp(jbw.jmpbuf)) { | |||
gd_error("gd-png error: setjmp returns error condition\n"); | gd_error("gd-png error: setjmp returns error condition\n"); | |||
png_destroy_write_struct (&png_ptr, &info_ptr); | png_destroy_write_struct (&png_ptr, &info_ptr); | |||
return; | return 1; | |||
} | } | |||
#endif | #endif | |||
png_set_write_fn (png_ptr, (void *) outfile, gdPngWriteData, | png_set_write_fn (png_ptr, (void *) outfile, gdPngWriteData, | |||
gdPngFlushData); | gdPngFlushData); | |||
/* This is best for palette images, and libpng defaults to it for | /* This is best for palette images, and libpng defaults to it for | |||
palette images anyway, so we don't need to do it explicitly. | palette images anyway, so we don't need to do it explicitly. | |||
What to ideally do for truecolor images depends, alas, on the image. | What to ideally do for truecolor images depends, alas, on the image. | |||
gd is intentionally imperfect and doesn't spend a lot of time | gd is intentionally imperfect and doesn't spend a lot of time | |||
skipping to change at line 839 | skipping to change at line 853 | |||
/* count actual number of colors used (colorsTotal == high-water mark) */ | /* count actual number of colors used (colorsTotal == high-water mark) */ | |||
colors = 0; | colors = 0; | |||
for (i = 0; i < im->colorsTotal; ++i) { | for (i = 0; i < im->colorsTotal; ++i) { | |||
if (!open[i]) { | if (!open[i]) { | |||
mapping[i] = colors; | mapping[i] = colors; | |||
++colors; | ++colors; | |||
} | } | |||
} | } | |||
if (colors == 0) { | if (colors == 0) { | |||
gd_error("gd-png error: no colors in palette\n"); | gd_error("gd-png error: no colors in palette\n"); | |||
ret = 1; | ||||
goto bail; | goto bail; | |||
} | } | |||
if (colors < im->colorsTotal) { | if (colors < im->colorsTotal) { | |||
remap = TRUE; | remap = TRUE; | |||
} | } | |||
if (colors <= 2) | if (colors <= 2) | |||
bit_depth = 1; | bit_depth = 1; | |||
else if (colors <= 4) | else if (colors <= 4) | |||
bit_depth = 2; | bit_depth = 2; | |||
else if (colors <= 16) | else if (colors <= 16) | |||
skipping to change at line 970 | skipping to change at line 985 | |||
/* Our little 7-bit alpha channel trick costs us a bit here. */ | /* Our little 7-bit alpha channel trick costs us a bit here. */ | |||
png_bytep *row_pointers; | png_bytep *row_pointers; | |||
unsigned char *pOutputRow; | unsigned char *pOutputRow; | |||
int **ptpixels = im->tpixels; | int **ptpixels = im->tpixels; | |||
int *pThisRow; | int *pThisRow; | |||
unsigned char a; | unsigned char a; | |||
int thisPixel; | int thisPixel; | |||
png_bytep *prow_pointers; | png_bytep *prow_pointers; | |||
int saveAlphaFlag = im->saveAlphaFlag; | int saveAlphaFlag = im->saveAlphaFlag; | |||
if (overflow2(sizeof (png_bytep), height)) { | if (overflow2(sizeof (png_bytep), height)) { | |||
ret = 1; | ||||
goto bail; | goto bail; | |||
} | } | |||
row_pointers = gdMalloc (sizeof (png_bytep) * height); | row_pointers = gdMalloc (sizeof (png_bytep) * height); | |||
if (row_pointers == NULL) { | if (row_pointers == NULL) { | |||
gd_error("gd-png error: unable to allocate row_pointers\n "); | gd_error("gd-png error: unable to allocate row_pointers\n "); | |||
ret = 1; | ||||
goto bail; | goto bail; | |||
} | } | |||
prow_pointers = row_pointers; | prow_pointers = row_pointers; | |||
for (j = 0; j < height; ++j) { | for (j = 0; j < height; ++j) { | |||
if (overflow2(width, channels) || ((*prow_pointers = | if (overflow2(width, channels) || ((*prow_pointers = | |||
(png_bytep) gdMal loc (width * channels)) == NULL)) { | (png_bytep) gdMal loc (width * channels)) == NULL)) { | |||
gd_error("gd-png error: unable to allocate rows\n "); | gd_error("gd-png error: unable to allocate rows\n "); | |||
for (i = 0; i < j; ++i) | for (i = 0; i < j; ++i) | |||
gdFree (row_pointers[i]); | gdFree (row_pointers[i]); | |||
/* 2.0.29: memory leak TBB */ | /* 2.0.29: memory leak TBB */ | |||
gdFree(row_pointers); | gdFree(row_pointers); | |||
ret = 1; | ||||
goto bail; | goto bail; | |||
} | } | |||
pOutputRow = *prow_pointers++; | pOutputRow = *prow_pointers++; | |||
pThisRow = *ptpixels++; | pThisRow = *ptpixels++; | |||
for (i = 0; i < width; ++i) { | for (i = 0; i < width; ++i) { | |||
thisPixel = *pThisRow++; | thisPixel = *pThisRow++; | |||
*pOutputRow++ = gdTrueColorGetRed (thisPixel); | *pOutputRow++ = gdTrueColorGetRed (thisPixel); | |||
*pOutputRow++ = gdTrueColorGetGreen (thisPixel); | *pOutputRow++ = gdTrueColorGetGreen (thisPixel); | |||
*pOutputRow++ = gdTrueColorGetBlue (thisPixel); | *pOutputRow++ = gdTrueColorGetBlue (thisPixel); | |||
skipping to change at line 1019 | skipping to change at line 1037 | |||
png_write_image (png_ptr, row_pointers); | png_write_image (png_ptr, row_pointers); | |||
png_write_end (png_ptr, info_ptr); | png_write_end (png_ptr, info_ptr); | |||
for (j = 0; j < height; ++j) | for (j = 0; j < height; ++j) | |||
gdFree (row_pointers[j]); | gdFree (row_pointers[j]); | |||
gdFree (row_pointers); | gdFree (row_pointers); | |||
} else { | } else { | |||
if (remap) { | if (remap) { | |||
png_bytep *row_pointers; | png_bytep *row_pointers; | |||
if (overflow2(sizeof (png_bytep), height)) { | if (overflow2(sizeof (png_bytep), height)) { | |||
ret = 1; | ||||
goto bail; | goto bail; | |||
} | } | |||
row_pointers = gdMalloc (sizeof (png_bytep) * height); | row_pointers = gdMalloc (sizeof (png_bytep) * height); | |||
if (row_pointers == NULL) { | if (row_pointers == NULL) { | |||
gd_error("gd-png error: unable to allocate row_po inters\n"); | gd_error("gd-png error: unable to allocate row_po inters\n"); | |||
ret = 1; | ||||
goto bail; | goto bail; | |||
} | } | |||
for (j = 0; j < height; ++j) { | for (j = 0; j < height; ++j) { | |||
if ((row_pointers[j] = (png_bytep) gdMalloc (widt h)) == NULL) { | if ((row_pointers[j] = (png_bytep) gdMalloc (widt h)) == NULL) { | |||
gd_error("gd-png error: unable to allocat e rows\n"); | gd_error("gd-png error: unable to allocat e rows\n"); | |||
for (i = 0; i < j; ++i) | for (i = 0; i < j; ++i) | |||
gdFree (row_pointers[i]); | gdFree (row_pointers[i]); | |||
/* TBB: memory leak */ | /* TBB: memory leak */ | |||
gdFree (row_pointers); | gdFree (row_pointers); | |||
ret = 1; | ||||
goto bail; | goto bail; | |||
} | } | |||
for (i = 0; i < width; ++i) | for (i = 0; i < width; ++i) | |||
row_pointers[j][i] = mapping[im->pixels[j ][i]]; | row_pointers[j][i] = mapping[im->pixels[j ][i]]; | |||
} | } | |||
png_write_image (png_ptr, row_pointers); | png_write_image (png_ptr, row_pointers); | |||
png_write_end (png_ptr, info_ptr); | png_write_end (png_ptr, info_ptr); | |||
for (j = 0; j < height; ++j) | for (j = 0; j < height; ++j) | |||
gdFree (row_pointers[j]); | gdFree (row_pointers[j]); | |||
gdFree (row_pointers); | gdFree (row_pointers); | |||
} else { | } else { | |||
png_write_image (png_ptr, im->pixels); | png_write_image (png_ptr, im->pixels); | |||
png_write_end (png_ptr, info_ptr); | png_write_end (png_ptr, info_ptr); | |||
} | } | |||
} | } | |||
/* 1.6.3: maybe we should give that memory BACK! TBB */ | /* 1.6.3: maybe we should give that memory BACK! TBB */ | |||
bail: | bail: | |||
png_destroy_write_struct (&png_ptr, &info_ptr); | png_destroy_write_struct (&png_ptr, &info_ptr); | |||
return ret; | ||||
} | } | |||
#endif /* HAVE_LIBPNG */ | #endif /* HAVE_LIBPNG */ | |||
End of changes. 19 change blocks. | ||||
10 lines changed or deleted | 32 lines changed or added |