42 return PNG_LIBPNG_VER_STRING;
45#ifdef PNG_SETJMP_SUPPORTED
46typedef struct _jmpbuf_wrapper
51static void gdPngErrorHandler (png_structp png_ptr, png_const_charp
msg)
53 jmpbuf_wrapper *jmpbuf_ptr;
67 jmpbuf_ptr = png_get_error_ptr (png_ptr);
68 if (jmpbuf_ptr ==
NULL) {
72 longjmp (jmpbuf_ptr->jmpbuf, 1);
75static void gdPngWarningHandler (png_structp png_ptr, png_const_charp
msg)
81static void gdPngReadData (png_structp png_ptr, png_bytep
data, png_size_t length)
85 if (check != length) {
86 png_error(png_ptr,
"Read Error: truncated data");
90static void gdPngWriteData (png_structp png_ptr, png_bytep
data, png_size_t length)
95static void gdPngFlushData (png_structp png_ptr)
124#ifdef PNG_SETJMP_SUPPORTED
129 png_uint_32 width, height, rowbytes, w, h, res_x, res_y;
130 int bit_depth, color_type, interlace_type, unit_type;
131 int num_palette, num_trans;
133 png_color_16p trans_gray_rgb;
134 png_color_16p trans_color_rgb;
136 volatile png_bytep image_data =
NULL;
137 volatile png_bytepp row_pointers =
NULL;
139 int i,
j, *open =
NULL;
140 volatile int transparent = -1;
141 volatile int palette_allocated =
FALSE;
146 memset (sig, 0,
sizeof(sig));
155 if (png_sig_cmp(sig, 0, 8) != 0) {
159#ifdef PNG_SETJMP_SUPPORTED
160 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, &jbw, gdPngErrorHandler, gdPngWarningHandler);
162 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
NULL,
NULL,
NULL);
164 if (png_ptr ==
NULL) {
165 gd_error(
"gd-png error: cannot allocate libpng main struct");
169 info_ptr = png_create_info_struct(png_ptr);
170 if (info_ptr ==
NULL) {
171 gd_error(
"gd-png error: cannot allocate libpng info struct");
172 png_destroy_read_struct (&png_ptr,
NULL,
NULL);
185#ifdef PNG_SETJMP_SUPPORTED
186 if (setjmp(jbw.jmpbuf)) {
187 gd_error(
"gd-png error: setjmp returns error condition");
188 png_destroy_read_struct(&png_ptr, &info_ptr,
NULL);
194 png_set_sig_bytes(png_ptr, 8);
196 png_set_read_fn(png_ptr, (
void *) infile, gdPngReadData);
197 png_read_info(png_ptr, info_ptr);
199 png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type,
NULL,
NULL);
200 if ((color_type == PNG_COLOR_TYPE_RGB) || (color_type == PNG_COLOR_TYPE_RGB_ALPHA)
201 || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
207 gd_error(
"gd-png error: cannot allocate gdImage struct");
208 png_destroy_read_struct(&png_ptr, &info_ptr,
NULL);
213 if (bit_depth == 16) {
214 png_set_strip_16(png_ptr);
215 }
else if (bit_depth < 8) {
216 png_set_packing (png_ptr);
222#ifdef PNG_SETJMP_SUPPORTED
223 if (setjmp(jbw.jmpbuf)) {
224 gd_error(
"gd-png error: setjmp returns error condition");
225 png_destroy_read_struct(&png_ptr, &info_ptr,
NULL);
235#ifdef PNG_pHYs_SUPPORTED
237 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_pHYs)) {
238 if (png_get_pHYs(png_ptr, info_ptr, &res_x, &res_y, &unit_type)) {
240 case PNG_RESOLUTION_METER:
249 switch (color_type) {
250 case PNG_COLOR_TYPE_PALETTE:
251 png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette);
253 gd_error(
"gd-png color_type is palette, colors: %d", num_palette);
255 if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS)) {
263 png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans,
NULL);
264 for (i = 0; i < num_trans; ++i) {
266 if ((trans[i] == 0) && (firstZero)) {
273 case PNG_COLOR_TYPE_GRAY:
275 if ((palette = (png_colorp)
gdMalloc (256 *
sizeof (png_color))) ==
NULL) {
276 gd_error(
"gd-png error: cannot allocate gray palette");
277 png_destroy_read_struct(&png_ptr, &info_ptr,
NULL);
281 palette_allocated =
TRUE;
283 num_palette = 1 << bit_depth;
284 for (i = 0; i < 256; ++i) {
285 j = (255 * i) / (num_palette - 1);
286 palette[i].red = palette[i].green = palette[i].blue =
j;
290 for (i = 0; i < 256; ++i) {
291 palette[i].red = palette[i].green = palette[i].blue = i;
294 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
295 png_get_tRNS(png_ptr, info_ptr,
NULL,
NULL, &trans_gray_rgb);
296 if (bit_depth == 16) {
297 transparent = trans_gray_rgb->gray >> 8;
299 transparent = trans_gray_rgb->gray;
315 case PNG_COLOR_TYPE_GRAY_ALPHA:
316 png_set_gray_to_rgb(png_ptr);
318 case PNG_COLOR_TYPE_RGB:
319 case PNG_COLOR_TYPE_RGB_ALPHA:
324 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
325 png_get_tRNS(png_ptr, info_ptr,
NULL,
NULL, &trans_color_rgb);
326 if (bit_depth == 16) {
327 transparent =
gdTrueColor(trans_color_rgb->red >> 8,
328 trans_color_rgb->green >> 8,
329 trans_color_rgb->blue >> 8);
332 trans_color_rgb->green,
333 trans_color_rgb->blue);
340#ifdef PNG_READ_INTERLACING_SUPPORTED
341 (
void)png_set_interlace_handling(png_ptr);
344 png_read_update_info(png_ptr, info_ptr);
347 rowbytes = png_get_rowbytes(png_ptr, info_ptr);
348 image_data = (png_bytep)
safe_emalloc(rowbytes, height, 0);
350 row_pointers = (png_bytepp)
safe_emalloc(height,
sizeof(png_bytep), 0);
353 for (h = 0; h < height; ++h) {
354 row_pointers[h] = image_data + h * rowbytes;
357 png_read_image(png_ptr, row_pointers);
358 png_read_end(png_ptr,
NULL);
364 for (i = 0; i < num_palette; ++i) {
365 im->
red[i] = palette[i].red;
366 im->
green[i] = palette[i].green;
367 im->
blue[i] = palette[i].blue;
379 im->
interlace = (interlace_type == PNG_INTERLACE_ADAM7);
382 png_destroy_read_struct(&png_ptr, &info_ptr,
NULL);
383 switch (color_type) {
384 case PNG_COLOR_TYPE_RGB:
385 for (h = 0; h < height; h++) {
387 for (w = 0; w < width; w++) {
388 register png_byte r = row_pointers[h][boffset++];
389 register png_byte g = row_pointers[h][boffset++];
390 register png_byte b = row_pointers[h][boffset++];
396 case PNG_COLOR_TYPE_GRAY_ALPHA:
397 case PNG_COLOR_TYPE_RGB_ALPHA:
398 for (h = 0; h < height; h++) {
400 for (w = 0; w < width; w++) {
401 register png_byte r = row_pointers[h][boffset++];
402 register png_byte g = row_pointers[h][boffset++];
403 register png_byte b = row_pointers[h][boffset++];
410 register png_byte
a =
gdAlphaMax - (row_pointers[h][boffset++] >> 1);
418 for (h = 0; h < height; ++h) {
419 for (w = 0; w < width; ++w) {
420 register png_byte idx = row_pointers[h][w];
430 gd_error(
"gd-png warning: image data references out-of-range color index (%d)", i);
436 if (palette_allocated) {
491 int i,
j, bit_depth = 0, interlace_type;
495 int *open = im->
open;
497 png_byte trans_values[256];
498 png_color_16 trans_rgb_value;
503 volatile int remap =
FALSE;
504#ifdef PNG_SETJMP_SUPPORTED
507 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, &jbw, gdPngErrorHandler, gdPngWarningHandler);
509 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
NULL,
NULL,
NULL);
511 if (png_ptr ==
NULL) {
512 gd_error(
"gd-png error: cannot allocate libpng main struct");
516 info_ptr = png_create_info_struct(png_ptr);
517 if (info_ptr ==
NULL) {
518 gd_error(
"gd-png error: cannot allocate libpng info struct");
519 png_destroy_write_struct (&png_ptr, (png_infopp)
NULL);
524#ifdef PNG_SETJMP_SUPPORTED
525 if (setjmp(jbw.jmpbuf)) {
526 gd_error(
"gd-png error: setjmp returns error condition");
527 png_destroy_write_struct (&png_ptr, &info_ptr);
533 png_set_write_fn(png_ptr, (
void *) outfile, gdPngWriteData, gdPngFlushData);
545 if (level != -1 && (level < 0 || level > 9)) {
546 gd_error(
"gd-png error: compression level must be 0 through 9");
549 png_set_compression_level(png_ptr, level);
550 if (basefilter >= 0) {
551 png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, basefilter);
554#ifdef PNG_pHYs_SUPPORTED
557 PNG_RESOLUTION_METER);
567 if (transparent >= im->
colorsTotal || (transparent >= 0 && open[transparent])) {
584 gd_error(
"gd-png error: no colors in palette");
594 }
else if (
colors <= 16) {
601 interlace_type = im->
interlace ? PNG_INTERLACE_ADAM7 : PNG_INTERLACE_NONE;
605 png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB_ALPHA, interlace_type,
606 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
608 png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB, interlace_type,
609 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
612 png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, PNG_COLOR_TYPE_PALETTE, interlace_type,
613 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
621 png_set_tRNS(png_ptr, info_ptr, 0, 0, &trans_rgb_value);
643 trans_values[i] = 255 - ((im->
alpha[i] << 1) + (im->
alpha[i] >> 6));
645 png_set_tRNS (png_ptr, info_ptr, trans_values, 256,
NULL);
661 trans_values[
j] = 255 - ((im->
alpha[i] << 1) + (im->
alpha[i] >> 6));
668 png_set_tRNS(png_ptr, info_ptr, trans_values, tc,
NULL);
676 if (mapping[i] < 0) {
680 palette[mapping[i]].red = im->
red[i];
681 palette[mapping[i]].green = im->
green[i];
682 palette[mapping[i]].blue = im->
blue[i];
685 for (i = 0; i <
colors; ++i) {
686 palette[i].red = im->
red[i];
687 palette[i].green = im->
green[i];
688 palette[i].blue = im->
blue[i];
691 png_set_PLTE(png_ptr, info_ptr, palette,
colors);
695 png_write_info(png_ptr, info_ptr);
698 png_set_packing(png_ptr);
712 png_bytep *row_pointers;
713 unsigned char* pOutputRow;
718 png_bytep *prow_pointers;
721 row_pointers =
safe_emalloc(
sizeof(png_bytep), height, 0);
722 prow_pointers = row_pointers;
723 for (
j = 0;
j < height; ++
j) {
724 *prow_pointers = (png_bytep)
safe_emalloc(width, channels, 0);
725 pOutputRow = *prow_pointers++;
726 pThisRow = *ptpixels++;
727 for (i = 0; i < width; ++i) {
728 thisPixel = *pThisRow++;
741 *pOutputRow++ = 255 - ((
a << 1) + (
a >> 6));
746 png_write_image(png_ptr, row_pointers);
747 png_write_end(png_ptr, info_ptr);
749 for (
j = 0;
j < height; ++
j) {
756 png_bytep *row_pointers;
757 row_pointers =
safe_emalloc(height,
sizeof(png_bytep), 0);
758 for (
j = 0;
j < height; ++
j) {
759 row_pointers[
j] = (png_bytep)
gdMalloc(width);
760 for (i = 0; i < width; ++i) {
761 row_pointers[
j][i] = mapping[im->
pixels[
j][i]];
765 png_write_image(png_ptr, row_pointers);
766 png_write_end(png_ptr, info_ptr);
768 for (
j = 0;
j < height; ++
j) {
774 png_write_image(png_ptr, im->
pixels);
775 png_write_end(png_ptr, info_ptr);
780 png_destroy_write_struct(&png_ptr, &info_ptr);
memset(ptr, 0, type->size)
#define gdTrueColorGetBlue(c)
void * gdDPExtractData(struct gdIOCtx *ctx, int *size)
void * gdImagePngPtr(gdImagePtr im, int *size)
gdImagePtr gdImageCreateFromPngCtx(gdIOCtxPtr in)
#define gdTrueColorGetGreen(c)
void * gdImagePngPtrEx(gdImagePtr im, int *size, int level, int basefilter)
void gdImagePngEx(gdImagePtr im, FILE *out, int level, int basefilter)
#define gdTrueColorGetAlpha(c)
void gdImagePng(gdImagePtr im, FILE *out)
#define gdTrueColorGetRed(c)
void gdImagePngCtxEx(gdImagePtr im, gdIOCtx *out, int level, int basefilter)
void gdImagePngCtx(gdImagePtr im, gdIOCtx *out)
gdIOCtx * gdNewFileCtx(FILE *)
#define gdTrueColorAlpha(r, g, b, a)
gdIOCtx * gdNewDynamicCtx(int, void *)
const char * gdPngGetVersionString(void)
#define gdTrueColor(r, g, b)
gdIOCtx * gdNewDynamicCtxEx(int size, void *data, int freeFlag)
gdImagePtr gdImageCreateFromPng(FILE *fd)
int gdGetBuf(void *buf, int size, gdIOCtx *ctx)
int gdPutBuf(const void *buf, int size, gdIOCtx *ctx)
gdImagePtr gdImageCreate(int sx, int sy)
void gdImageDestroy(gdImagePtr im)
void gd_error(const char *format,...)
void gd_error_ex(int priority, const char *format,...)
gdImagePtr gdImageCreateTrueColor(int sx, int sy)
const phpdbg_color_t * colors[PHPDBG_COLORS]
void(* gd_free)(struct gdIOCtx *)
#define safe_emalloc(nmemb, size, offset)
ZEND_API void(ZEND_FASTCALL *zend_touch_vm_stack_data)(void *vm_stack_data)