diff options
-rw-r--r-- | ext/gd/libgd/gd_gd.c | 332 | ||||
-rw-r--r-- | ext/gd/libgd/gd_gd2.c | 3 | ||||
-rw-r--r-- | ext/gd/libgd/gd_png.c | 1124 | ||||
-rw-r--r-- | ext/gd/libgd/gd_ss.c | 34 | ||||
-rw-r--r-- | ext/gd/libgd/gd_wbmp.c | 175 |
5 files changed, 762 insertions, 906 deletions
diff --git a/ext/gd/libgd/gd_gd.c b/ext/gd/libgd/gd_gd.c index 53b1c71f99..bbad474cd1 100644 --- a/ext/gd/libgd/gd_gd.c +++ b/ext/gd/libgd/gd_gd.c @@ -1,4 +1,3 @@ - #include <stdio.h> #include <math.h> #include <string.h> @@ -20,252 +19,199 @@ extern void gdImageGd (gdImagePtr im, FILE * out); /* */ /* Shared code to read color tables from gd file. */ /* */ -int -_gdGetColors (gdIOCtx * in, gdImagePtr im, int gd2xFlag) +int _gdGetColors (gdIOCtx * in, gdImagePtr im, int gd2xFlag) { - int i; - if (gd2xFlag) - { - if (!gdGetByte (&im->trueColor, in)) - { - goto fail1; - } - /* This should have been a word all along */ - if (!im->trueColor) - { - if (!gdGetWord (&im->colorsTotal, in)) - { - goto fail1; - } - } - /* Int to accommodate truecolor single-color transparency */ - if (!gdGetInt (&im->transparent, in)) - { - goto fail1; - } - } - else - { - if (!gdGetByte (&im->colorsTotal, in)) - { - goto fail1; - } - if (!gdGetWord (&im->transparent, in)) - { - goto fail1; + int i; + if (gd2xFlag) { + if (!gdGetByte (&im->trueColor, in)) { + goto fail1; + } + /* This should have been a word all along */ + if (!im->trueColor && !gdGetWord(&im->colorsTotal, in)) { + goto fail1; + } + /* Int to accommodate truecolor single-color transparency */ + if (!gdGetInt(&im->transparent, in)) { + goto fail1; + } + } else { + if (!gdGetByte(&im->colorsTotal, in)) { + goto fail1; + } + if (!gdGetWord (&im->transparent, in)) { + goto fail1; + } + if (im->transparent == 257) { + im->transparent = (-1); + } } - if (im->transparent == 257) - { - im->transparent = (-1); + GD2_DBG (php_gd_error("Pallette had %d colours (T=%d)\n", im->colorsTotal, im->transparent)); + + for (i = 0; i < gdMaxColors; i++) { + if (!gdGetByte(&im->red[i], in)) { + goto fail1; + } + if (!gdGetByte(&im->green[i], in)) { + goto fail1; + } + if (!gdGetByte(&im->blue[i], in)) { + goto fail1; + } + if (gd2xFlag && !gdGetByte (&im->alpha[i], in)) { + goto fail1; + } } - } - GD2_DBG (printf ("Pallette had %d colours (T=%d)\n", im->colorsTotal, im->transparent)); - for (i = 0; (i < gdMaxColors); i++) - { - if (!gdGetByte (&im->red[i], in)) - { - goto fail1; + for (i = 0; (i < im->colorsTotal); i++) { + im->open[i] = 0; } - if (!gdGetByte (&im->green[i], in)) - { - goto fail1; - } - if (!gdGetByte (&im->blue[i], in)) - { - goto fail1; - } - if (gd2xFlag) - { - if (!gdGetByte (&im->alpha[i], in)) - { - goto fail1; - } - } - } - - for (i = 0; (i < im->colorsTotal); i++) - { - im->open[i] = 0; - }; - return TRUE; + return TRUE; fail1: - return FALSE; + return FALSE; } /* */ /* Use the common basic header info to make the image object. */ /* This is also called from _gd2CreateFromFile */ /* */ -static - gdImagePtr -_gdCreateFromFile (gdIOCtx * in, int *sx, int *sy) +static gdImagePtr _gdCreateFromFile (gdIOCtx * in, int *sx, int *sy) { - gdImagePtr im; - int gd2xFlag = 0; - if (!gdGetWord (sx, in)) - { - goto fail1; - } - if (*sx == 65535) - { - /* This is a gd 2.0 .gd file */ - gd2xFlag = 1; - if (!gdGetWord (sx, in)) - { - goto fail1; + gdImagePtr im; + int gd2xFlag = 0; + if (!gdGetWord(sx, in)) { + goto fail1; + } + if (*sx == 65535) { + /* This is a gd 2.0 .gd file */ + gd2xFlag = 1; + if (!gdGetWord(sx, in)) { + goto fail1; + } + } + if (!gdGetWord(sy, in)) { + goto fail1; } - } - if (!gdGetWord (sy, in)) - { - goto fail1; - } - GD2_DBG (printf ("Image is %dx%d\n", *sx, *sy)); + GD2_DBG(php_gd_error("Image is %dx%d\n", *sx, *sy)); - im = gdImageCreate (*sx, *sy); + im = gdImageCreate (*sx, *sy); - if (!_gdGetColors (in, im, gd2xFlag)) - { - goto fail2; - } + if (!_gdGetColors(in, im, gd2xFlag)) { + goto fail2; + } - return im; + return im; fail2: - gdImageDestroy (im); + gdImageDestroy(im); fail1: - return 0; + return 0; } -gdImagePtr -gdImageCreateFromGd (FILE * inFile) +gdImagePtr gdImageCreateFromGd (FILE * inFile) { - gdImagePtr im; - gdIOCtx *in; + gdImagePtr im; + gdIOCtx *in; - in = gdNewFileCtx (inFile); - im = gdImageCreateFromGdCtx (in); + in = gdNewFileCtx (inFile); + im = gdImageCreateFromGdCtx (in); - in->gd_free (in); + in->gd_free(in); - return im; + return im; } -gdImagePtr -gdImageCreateFromGdCtx (gdIOCtxPtr in) +gdImagePtr gdImageCreateFromGdCtx (gdIOCtxPtr in) { - int sx, sy; - int x, y; - gdImagePtr im; + int sx, sy; + int x, y; + gdImagePtr im; - /* Read the header */ - im = _gdCreateFromFile (in, &sx, &sy); - - if (im == NULL) - { - goto fail1; - }; + /* Read the header */ + if ((im = _gdCreateFromFile (in, &sx, &sy)) == NULL) { + goto fail1; + } - /* Then the data... */ - for (y = 0; (y < sy); y++) - { - for (x = 0; (x < sx); x++) - { - int ch; - ch = gdGetC (in); - if (ch == EOF) - { - goto fail2; - } - /* ROW-MAJOR IN GD 1.3 */ - im->pixels[y][x] = ch; + /* Then the data... */ + for (y = 0; y < sy; y++) { + for (x = 0; x < sx; x++) { + int ch; + if ((ch = gdGetC(in)) == EOF) { + goto fail2; + } + /* ROW-MAJOR IN GD 1.3 */ + im->pixels[y][x] = ch; + } } - } - return im; + return im; fail2: - gdImageDestroy (im); + gdImageDestroy (im); fail1: - return 0; + return 0; } -void -_gdPutColors (gdImagePtr im, gdIOCtx * out) +void _gdPutColors (gdImagePtr im, gdIOCtx * out) { - int i; + int i; - gdPutC (im->trueColor, out); - if (!im->trueColor) - { - gdPutWord (im->colorsTotal, out); - } - gdPutInt (im->transparent, out); - if (!im->trueColor) - { - for (i = 0; (i < gdMaxColors); i++) - { - gdPutC ((unsigned char) im->red[i], out); - gdPutC ((unsigned char) im->green[i], out); - gdPutC ((unsigned char) im->blue[i], out); - gdPutC ((unsigned char) im->alpha[i], out); + gdPutC(im->trueColor, out); + if (!im->trueColor) { + gdPutWord (im->colorsTotal, out); + } + gdPutInt (im->transparent, out); + if (!im->trueColor) { + for (i = 0; (i < gdMaxColors); i++) { + gdPutC((unsigned char) im->red[i], out); + gdPutC((unsigned char) im->green[i], out); + gdPutC((unsigned char) im->blue[i], out); + gdPutC((unsigned char) im->alpha[i], out); + } } - } } -static -void -_gdPutHeader (gdImagePtr im, gdIOCtx * out) +static void _gdPutHeader (gdImagePtr im, gdIOCtx * out) { - /* 65535 indicates this is a gd 2.x .gd file. */ - gdPutWord (65535, out); - gdPutWord (im->sx, out); - gdPutWord (im->sy, out); - - _gdPutColors (im, out); + /* 65535 indicates this is a gd 2.x .gd file. */ + gdPutWord(65535, out); + gdPutWord(im->sx, out); + gdPutWord(im->sy, out); + _gdPutColors (im, out); } -static void -_gdImageGd (gdImagePtr im, gdIOCtx * out) +static void _gdImageGd (gdImagePtr im, gdIOCtx * out) { - int x, y; - - _gdPutHeader (im, out); - - for (y = 0; (y < im->sy); y++) - { - for (x = 0; (x < im->sx); x++) - { - /* ROW-MAJOR IN GD 1.3 */ - if (im->trueColor) - { - gdPutInt (im->tpixels[y][x], out); - } - else - { - gdPutC ((unsigned char) im->pixels[y][x], out); - } + int x, y; + + _gdPutHeader (im, out); + + for (y = 0; y < im->sy; y++) { + for (x = 0; x < im->sx; x++) { + /* ROW-MAJOR IN GD 1.3 */ + if (im->trueColor) { + gdPutInt (im->tpixels[y][x], out); + } else { + gdPutC((unsigned char) im->pixels[y][x], out); + } + } } - } } -void -gdImageGd (gdImagePtr im, FILE * outFile) +void gdImageGd (gdImagePtr im, FILE * outFile) { - gdIOCtx *out = gdNewFileCtx (outFile); - _gdImageGd (im, out); - out->gd_free (out); + gdIOCtx *out = gdNewFileCtx(outFile); + _gdImageGd(im, out); + out->gd_free(out); } -void * -gdImageGdPtr (gdImagePtr im, int *size) +void * gdImageGdPtr (gdImagePtr im, int *size) { - void *rv; - gdIOCtx *out = gdNewDynamicCtx (2048, NULL); - _gdImageGd (im, out); - rv = gdDPExtractData (out, size); - out->gd_free (out); - return rv; + void *rv; + gdIOCtx *out = gdNewDynamicCtx(2048, NULL); + _gdImageGd(im, out); + rv = gdDPExtractData(out, size); + out->gd_free(out); + return rv; } diff --git a/ext/gd/libgd/gd_gd2.c b/ext/gd/libgd/gd_gd2.c index 59c711763b..07fd0aac73 100644 --- a/ext/gd/libgd/gd_gd2.c +++ b/ext/gd/libgd/gd_gd2.c @@ -43,8 +43,7 @@ typedef struct { int offset; int size; -} -t_chunk_info; +} t_chunk_info; extern int _gdGetColors(gdIOCtx * in, gdImagePtr im, int gd2xFlag); extern void _gdPutColors(gdImagePtr im, gdIOCtx * out); diff --git a/ext/gd/libgd/gd_png.c b/ext/gd/libgd/gd_png.c index a5850c6511..534ab63d51 100644 --- a/ext/gd/libgd/gd_png.c +++ b/ext/gd/libgd/gd_png.c @@ -38,696 +38,628 @@ #ifndef PNG_SETJMP_NOT_SUPPORTED typedef struct _jmpbuf_wrapper - { - jmp_buf jmpbuf; - } -jmpbuf_wrapper; +{ + jmp_buf jmpbuf; +} jmpbuf_wrapper; static jmpbuf_wrapper gdPngJmpbufStruct; -static void -gdPngErrorHandler (png_structp png_ptr, png_const_charp msg) +static void gdPngErrorHandler (png_structp png_ptr, png_const_charp msg) { - jmpbuf_wrapper *jmpbuf_ptr; - - /* This function, aside from the extra step of retrieving the "error - * pointer" (below) and the fact that it exists within the application - * rather than within libpng, is essentially identical to libpng's - * default error handler. The second point is critical: since both - * setjmp() and longjmp() are called from the same code, they are - * guaranteed to have compatible notions of how big a jmp_buf is, - * regardless of whether _BSD_SOURCE or anything else has (or has not) - * been defined. */ - - php_gd_error_ex(E_ERROR, "gd-png: fatal libpng error: %s\n", msg); - - jmpbuf_ptr = png_get_error_ptr (png_ptr); - if (jmpbuf_ptr == NULL) - { /* we are completely hosed now */ - php_gd_error_ex(E_ERROR, "gd-png: EXTREMELY fatal error: jmpbuf unrecoverable; terminating.\n"); - exit (99); - } + jmpbuf_wrapper *jmpbuf_ptr; + + /* This function, aside from the extra step of retrieving the "error + * pointer" (below) and the fact that it exists within the application + * rather than within libpng, is essentially identical to libpng's + * default error handler. The second point is critical: since both + * setjmp() and longjmp() are called from the same code, they are + * guaranteed to have compatible notions of how big a jmp_buf is, + * regardless of whether _BSD_SOURCE or anything else has (or has not) + * been defined. + */ + + php_gd_error_ex(E_ERROR, "gd-png: fatal libpng error: %s\n", msg); + + jmpbuf_ptr = png_get_error_ptr (png_ptr); + if (jmpbuf_ptr == NULL) { /* we are completely hosed now */ + php_gd_error_ex(E_ERROR, "gd-png: EXTREMELY fatal error: jmpbuf unrecoverable; terminating.\n"); + } - longjmp (jmpbuf_ptr->jmpbuf, 1); + longjmp (jmpbuf_ptr->jmpbuf, 1); } #endif -static void -gdPngReadData (png_structp png_ptr, - png_bytep data, png_size_t length) +static void gdPngReadData (png_structp png_ptr, png_bytep data, png_size_t length) { - gdGetBuf (data, length, (gdIOCtx *) - png_get_io_ptr (png_ptr)); + gdGetBuf(data, length, (gdIOCtx *) png_get_io_ptr(png_ptr)); } -static void -gdPngWriteData (png_structp png_ptr, - png_bytep data, png_size_t length) +static void gdPngWriteData (png_structp png_ptr, png_bytep data, png_size_t length) { - gdPutBuf (data, length, (gdIOCtx *) - png_get_io_ptr (png_ptr)); + gdPutBuf (data, length, (gdIOCtx *) png_get_io_ptr(png_ptr)); } -static void -gdPngFlushData (png_structp png_ptr) +static void gdPngFlushData (png_structp png_ptr) { } -gdImagePtr -gdImageCreateFromPng (FILE * inFile) +gdImagePtr gdImageCreateFromPng (FILE * inFile) { - gdImagePtr im; - gdIOCtx *in = gdNewFileCtx (inFile); - im = gdImageCreateFromPngCtx (in); - in->gd_free (in); - return im; + gdImagePtr im; + gdIOCtx *in = gdNewFileCtx(inFile); + im = gdImageCreateFromPngCtx(in); + in->gd_free(in); + + return im; } /* This routine is based in part on the Chapter 13 demo code in "PNG: The * Definitive Guide" (http://www.cdrom.com/pub/png/pngbook.html). */ -gdImagePtr -gdImageCreateFromPngCtx (gdIOCtx * infile) +gdImagePtr gdImageCreateFromPngCtx (gdIOCtx * infile) { - png_byte sig[8]; - png_structp png_ptr; - png_infop info_ptr; - png_uint_32 width, height, rowbytes, w, h; - int bit_depth, color_type, interlace_type; - int num_palette, num_trans; - png_colorp palette; - png_color_16p trans_gray_rgb; - png_color_16p trans_color_rgb; - png_bytep trans; - png_bytep image_data = NULL; - png_bytepp row_pointers = NULL; - gdImagePtr im = NULL; - int i, j, *open = NULL; - volatile int transparent = -1; - volatile int palette_allocated = FALSE; - - /* 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)); - - /* 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 */ + png_byte sig[8]; + png_structp png_ptr; + png_infop info_ptr; + png_uint_32 width, height, rowbytes, w, h; + int bit_depth, color_type, interlace_type; + int num_palette, num_trans; + png_colorp palette; + png_color_16p trans_gray_rgb; + png_color_16p trans_color_rgb; + png_bytep trans; + png_bytep image_data = NULL; + png_bytepp row_pointers = NULL; + gdImagePtr im = NULL; + int i, j, *open = NULL; + volatile int transparent = -1; + volatile int palette_allocated = FALSE; + + /* 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)); + + /* 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)) { /* bad signature */ + return NULL; + } #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); + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); #endif - if (png_ptr == NULL) - { - php_gd_error("gd-png error: cannot allocate libpng main struct\n"); - return NULL; - } + if (png_ptr == NULL) { + php_gd_error("gd-png error: cannot allocate libpng main struct\n"); + return NULL; + } - info_ptr = png_create_info_struct (png_ptr); - if (info_ptr == NULL) - { - php_gd_error("gd-png error: cannot allocate libpng info struct\n"); - png_destroy_read_struct (&png_ptr, NULL, NULL); - return NULL; - } + info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == NULL) { + php_gd_error("gd-png error: cannot allocate libpng info struct\n"); + png_destroy_read_struct (&png_ptr, NULL, 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) */ + return NULL; + } - /* setjmp() must be called in every non-callback function that calls a - * PNG-reading libpng function */ + /* 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) + */ + + /* 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)) - { - php_gd_error("gd-png error: setjmp returns error condition\n"); - png_destroy_read_struct (&png_ptr, &info_ptr, NULL); - return NULL; - } -#endif + if (setjmp(gdPngJmpbufStruct.jmpbuf)) { + php_gd_error("gd-png error: setjmp returns error condition\n"); + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - png_set_sig_bytes (png_ptr, 8); /* we already read the 8 signature bytes */ + 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_set_sig_bytes(png_ptr, 8); /* we already read the 8 signature bytes */ - 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 - { - im = gdImageCreate ((int) width, (int) height); - } - if (im == NULL) - { - php_gd_error("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; - } + png_set_read_fn(png_ptr, (void *) infile, gdPngReadData); + png_read_info(png_ptr, info_ptr); /* read all PNG info up to image data */ - if (bit_depth == 16) - png_set_strip_16 (png_ptr); - else if (bit_depth < 8) - png_set_packing (png_ptr); /* expand to 1 byte per pixel */ - switch (color_type) - { - case PNG_COLOR_TYPE_PALETTE: - png_get_PLTE (png_ptr, info_ptr, &palette, &num_palette); -#ifdef DEBUG - php_gd_error("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. */ - int firstZero = 1; - png_get_tRNS (png_ptr, info_ptr, &trans, &num_trans, NULL); - for (i = 0; i < num_trans; ++i) - { - im->alpha[i] = gdAlphaMax - (trans[i] >> 1); - if ((trans[i] == 0) && (firstZero)) - { - transparent = i; - firstZero = 0; - } - } - } - break; - - 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) - { - php_gd_error("gd-png error: cannot allocate gray palette\n"); - png_destroy_read_struct (&png_ptr, &info_ptr, NULL); - return NULL; + 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 { + im = gdImageCreate((int) width, (int) height); } - palette_allocated = TRUE; - if (bit_depth < 8) - { - num_palette = 1 << bit_depth; - for (i = 0; i < 256; ++i) - { - j = (255 * i) / (num_palette - 1); - palette[i].red = palette[i].green = palette[i].blue = j; - } - } - else - { - num_palette = 256; - for (i = 0; i < 256; ++i) - { - palette[i].red = palette[i].green = palette[i].blue = i; - } + if (im == NULL) { + php_gd_error("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 (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 */ - transparent = trans_gray_rgb->gray >> 8; - 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 - * transparent pixels will be mapped into the transparent entry. - * There is no particularly good way around this in the case - * that all 256 8-bit shades are used, but one could write some - * custom 16-bit code to handle the case where there are gdFree - * palette entries. This error will be extremely rare in - * general, though. (Quite possibly there is only one such - * image in existence.) */ + + if (bit_depth == 16) { + png_set_strip_16(png_ptr); + } else if (bit_depth < 8) { + png_set_packing (png_ptr); /* expand to 1 byte per pixel */ } - break; - - case PNG_COLOR_TYPE_RGB: - case PNG_COLOR_TYPE_RGB_ALPHA: - /* 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)) - { - png_get_tRNS (png_ptr, info_ptr, NULL, NULL, &trans_color_rgb); - 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 - transparent = gdTrueColor (trans_color_rgb->red, - trans_color_rgb->green, - trans_color_rgb->blue); + + switch (color_type) { + case PNG_COLOR_TYPE_PALETTE: + png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette); +#ifdef DEBUG + php_gd_error("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. + */ + int firstZero = 1; + png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL); + for (i = 0; i < num_trans; ++i) { + im->alpha[i] = gdAlphaMax - (trans[i] >> 1); + if ((trans[i] == 0) && (firstZero)) { + transparent = i; + firstZero = 0; + } + } + } + break; + 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) { + php_gd_error("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) { + num_palette = 1 << bit_depth; + for (i = 0; i < 256; ++i) { + j = (255 * i) / (num_palette - 1); + palette[i].red = palette[i].green = palette[i].blue = j; + } + } else { + num_palette = 256; + 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)) { + png_get_tRNS(png_ptr, info_ptr, NULL, NULL, &trans_gray_rgb); + if (bit_depth == 16) { /* png_set_strip_16() not yet in effect */ + transparent = trans_gray_rgb->gray >> 8; + } 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 + * transparent pixels will be mapped into the transparent entry. + * There is no particularly good way around this in the case + * that all 256 8-bit shades are used, but one could write some + * custom 16-bit code to handle the case where there are gdFree + * palette entries. This error will be extremely rare in + * general, though. (Quite possibly there is only one such + * image in existence.) + */ + } + break; + + case PNG_COLOR_TYPE_RGB: + case PNG_COLOR_TYPE_RGB_ALPHA: + /* 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)) { + png_get_tRNS(png_ptr, info_ptr, NULL, NULL, &trans_color_rgb); + 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 { + transparent = gdTrueColor(trans_color_rgb->red, + trans_color_rgb->green, + trans_color_rgb->blue); + } + } + break; } - break; - } - png_read_update_info (png_ptr, info_ptr); + png_read_update_info(png_ptr, info_ptr); - /* allocate space for the PNG image data */ - rowbytes = png_get_rowbytes (png_ptr, info_ptr); - if ((image_data = (png_bytep) gdMalloc (rowbytes * height)) == NULL) - { - php_gd_error("gd-png error: cannot allocate image data\n"); - png_destroy_read_struct (&png_ptr, &info_ptr, NULL); - return NULL; - } - if ((row_pointers = (png_bytepp) gdMalloc (height * sizeof (png_bytep))) == NULL) - { - php_gd_error("gd-png error: cannot allocate row pointers\n"); - png_destroy_read_struct (&png_ptr, &info_ptr, NULL); - gdFree (image_data); - return NULL; - } + /* allocate space for the PNG image data */ + rowbytes = png_get_rowbytes(png_ptr, info_ptr); + image_data = (png_bytep) gdMalloc (rowbytes * height); - /* set the individual row_pointers to point at the correct offsets */ - for (h = 0; h < height; ++h) - { - row_pointers[h] = image_data + h * rowbytes; - } + row_pointers = (png_bytepp) gdMalloc (height * sizeof (png_bytep)); - png_read_image (png_ptr, row_pointers); /* read whole image... */ - png_read_end (png_ptr, NULL); /* ...done! */ - - if (!im->trueColor) - { - im->colorsTotal = num_palette; - im->transparent = transparent; - /* load the palette and mark all entries "open" (unused) for now */ - open = im->open; - 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; + /* set the individual row_pointers to point at the correct offsets */ + for (h = 0; h < height; ++h) { + row_pointers[h] = image_data + h * rowbytes; } - for (i = num_palette; i < gdMaxColors; ++i) - { - open[i] = 1; - } - } - im->interlace = (interlace_type == PNG_INTERLACE_ADAM7); - - /* can't nuke structs until done with palette */ - png_destroy_read_struct (&png_ptr, &info_ptr, NULL); - switch (color_type) - { - case PNG_COLOR_TYPE_RGB: - for (h = 0; h < height; h++) - { - int boffset = 0; - 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 (h = 0; h < height; h++) - { - int boffset = 0; - 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); - } + + png_read_image(png_ptr, row_pointers); /* read whole image... */ + png_read_end(png_ptr, NULL); /* ...done! */ + + if (!im->trueColor) { + im->colorsTotal = num_palette; + im->transparent = transparent; + /* load the palette and mark all entries "open" (unused) for now */ + open = im->open; + 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) { + open[i] = 1; + } } - break; - default: - /* Palette image, or something coerced to be one */ - 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; - } + + im->interlace = (interlace_type == PNG_INTERLACE_ADAM7); + + /* can't nuke structs until done with palette */ + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + switch (color_type) { + case PNG_COLOR_TYPE_RGB: + for (h = 0; h < height; h++) { + int boffset = 0; + 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 (h = 0; h < height; h++) { + int boffset = 0; + 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 (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]) - { - php_gd_error("gd-png warning: image data references out-of-range" - " color index (%d)\n", i); - } + if (!im->trueColor) { + for (i = num_palette; i < gdMaxColors; ++i) { + if (!open[i]) { + php_gd_error("gd-png warning: image data references out-of-range color index (%d)\n", i); + } + } } - } #endif - if (palette_allocated) - gdFree (palette); - gdFree (image_data); - gdFree (row_pointers); + if (palette_allocated) { + gdFree(palette); + } + gdFree(image_data); + gdFree(row_pointers); - return im; + return im; } -void -gdImagePng (gdImagePtr im, FILE * outFile) +void gdImagePng (gdImagePtr im, FILE * outFile) { - gdIOCtx *out = gdNewFileCtx (outFile); - gdImagePngCtx (im, out); - out->gd_free (out); + gdIOCtx *out = gdNewFileCtx(outFile); + gdImagePngCtx(im, out); + out->gd_free(out); } -void * -gdImagePngPtr (gdImagePtr im, int *size) +void * gdImagePngPtr (gdImagePtr im, int *size) { - void *rv; - gdIOCtx *out = gdNewDynamicCtx (2048, NULL); - gdImagePngCtx (im, out); - rv = gdDPExtractData (out, size); - out->gd_free (out); - return rv; + void *rv; + gdIOCtx *out = gdNewDynamicCtx(2048, NULL); + gdImagePngCtx(im, out); + rv = gdDPExtractData(out, size); + out->gd_free(out); + + return rv; } /* 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" * (http://www.cdrom.com/pub/png/pngbook.html). */ -void -gdImagePngCtx (gdImagePtr im, gdIOCtx * outfile) +void gdImagePngCtx (gdImagePtr im, gdIOCtx * outfile) { - int i, j, bit_depth = 0, interlace_type; - int width = im->sx; - int height = im->sy; - int colors = im->colorsTotal; - int *open = im->open; - int mapping[gdMaxColors]; /* mapping[gd_index] == png_index */ - png_byte trans_values[256]; - png_color_16 trans_rgb_value; - png_color palette[gdMaxColors]; - png_structp png_ptr; - png_infop info_ptr; - volatile int transparent = im->transparent; - volatile int remap = FALSE; - + int i, j, bit_depth = 0, interlace_type; + int width = im->sx; + int height = im->sy; + int colors = im->colorsTotal; + int *open = im->open; + int mapping[gdMaxColors]; /* mapping[gd_index] == png_index */ + png_byte trans_values[256]; + png_color_16 trans_rgb_value; + png_color palette[gdMaxColors]; + png_structp png_ptr; + png_infop info_ptr; + volatile int transparent = im->transparent; + volatile int remap = FALSE; #ifndef PNG_SETJMP_NOT_SUPPORTED - png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, - &gdPngJmpbufStruct, gdPngErrorHandler, NULL); + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, &gdPngJmpbufStruct, gdPngErrorHandler, NULL); #else - png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); #endif - if (png_ptr == NULL) - { - php_gd_error("gd-png error: cannot allocate libpng main struct\n"); - return; - } + if (png_ptr == NULL) { + php_gd_error("gd-png error: cannot allocate libpng main struct\n"); + return; + } - info_ptr = png_create_info_struct (png_ptr); - if (info_ptr == NULL) - { - php_gd_error("gd-png error: cannot allocate libpng info struct\n"); - png_destroy_write_struct (&png_ptr, (png_infopp) NULL); - return; + info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == NULL) { + php_gd_error("gd-png error: cannot allocate libpng info struct\n"); + png_destroy_write_struct (&png_ptr, (png_infopp) NULL); + + return; } #ifndef PNG_SETJMP_NOT_SUPPORTED - if (setjmp (gdPngJmpbufStruct.jmpbuf)) - { - php_gd_error("gd-png error: setjmp returns error condition\n"); - png_destroy_write_struct (&png_ptr, &info_ptr); - return; - } + if (setjmp (gdPngJmpbufStruct.jmpbuf)) { + php_gd_error("gd-png error: setjmp returns error condition\n"); + png_destroy_write_struct (&png_ptr, &info_ptr); + + return; + } #endif - png_set_write_fn (png_ptr, (void *) outfile, gdPngWriteData, gdPngFlushData); + png_set_write_fn(png_ptr, (void *) outfile, gdPngWriteData, gdPngFlushData); - /* This is best for palette images, and libpng defaults to it for - palette images anyway, so we don't need to do it explicitly. - What to ideally do for truecolor images depends, alas, on the image. - gd is intentionally imperfect and doesn't spend a lot of time - fussing with such things. */ -/* png_set_filter(png_ptr, 0, PNG_FILTER_NONE); */ + /* This is best for palette images, and libpng defaults to it for + * palette images anyway, so we don't need to do it explicitly. + * What to ideally do for truecolor images depends, alas, on the image. + * gd is intentionally imperfect and doesn't spend a lot of time + * fussing with such things. + */ + + /* png_set_filter(png_ptr, 0, PNG_FILTER_NONE); */ - /* may want to force maximum compression, but time penalty is large */ -/* png_set_compression_level(png_ptr, Z_BEST_COMPRESSION); */ + /* may want to force maximum compression, but time penalty is large + * png_set_compression_level(png_ptr, Z_BEST_COMPRESSION); + */ - /* can set this to a smaller value without compromising compression if all - * image data is 16K or less; will save some decoder memory [min == 8] */ -/* png_set_compression_window_bits(png_ptr, 15); */ + /* can set this to a smaller value without compromising compression if all + * image data is 16K or less; will save some decoder memory [min == 8] + */ - if (!im->trueColor) - { - if (transparent >= im->colorsTotal || - (transparent >= 0 && open[transparent])) - transparent = -1; - } - if (!im->trueColor) - { - for (i = 0; i < gdMaxColors; ++i) - mapping[i] = -1; - } - if (!im->trueColor) - { - /* count actual number of colors used (colorsTotal == high-water mark) */ - colors = 0; - for (i = 0; i < im->colorsTotal; ++i) - { - if (!open[i]) - { - mapping[i] = colors; - ++colors; - } - } - if (colors < im->colorsTotal) - { - remap = TRUE; - } - if (colors <= 2) - bit_depth = 1; - else if (colors <= 4) - bit_depth = 2; - else if (colors <= 16) - bit_depth = 4; - else - bit_depth = 8; - } - interlace_type = im->interlace ? PNG_INTERLACE_ADAM7 : PNG_INTERLACE_NONE; - - if (im->trueColor) - { - if (im->saveAlphaFlag) - { - png_set_IHDR (png_ptr, info_ptr, width, height, 8, - PNG_COLOR_TYPE_RGB_ALPHA, interlace_type, - PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + /* png_set_compression_window_bits(png_ptr, 15); */ + + if (!im->trueColor) { + if (transparent >= im->colorsTotal || (transparent >= 0 && open[transparent])) { + transparent = -1; + } + + for (i = 0; i < gdMaxColors; ++i) { + mapping[i] = -1; + } + + /* count actual number of colors used (colorsTotal == high-water mark) */ + colors = 0; + for (i = 0; i < im->colorsTotal; ++i) { + if (!open[i]) { + mapping[i] = colors; + ++colors; + } + } + if (colors < im->colorsTotal) { + remap = TRUE; + } + if (colors <= 2) { + bit_depth = 1; + } else if (colors <= 4) { + bit_depth = 2; + } else if (colors <= 16) { + bit_depth = 4; + } else { + bit_depth = 8; + } } - else - { - png_set_IHDR (png_ptr, info_ptr, width, height, 8, - PNG_COLOR_TYPE_RGB, interlace_type, - PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + + interlace_type = im->interlace ? PNG_INTERLACE_ADAM7 : PNG_INTERLACE_NONE; + + if (im->trueColor) { + if (im->saveAlphaFlag) { + png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB_ALPHA, interlace_type, + PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + } else { + png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB, interlace_type, + PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + } + } else { + png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, PNG_COLOR_TYPE_PALETTE, interlace_type, + PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); } - } - else - { - png_set_IHDR (png_ptr, info_ptr, width, height, bit_depth, - PNG_COLOR_TYPE_PALETTE, interlace_type, - PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); - } - if (im->trueColor && (!im->saveAlphaFlag) && (transparent >= 0)) - { - /* 2.0.9: fixed by Thomas Winzig */ - trans_rgb_value.red = gdTrueColorGetRed (im->transparent); - trans_rgb_value.green = gdTrueColorGetGreen (im->transparent); - trans_rgb_value.blue = gdTrueColorGetBlue (im->transparent); - png_set_tRNS (png_ptr, info_ptr, 0, 0, &trans_rgb_value); - } - if (!im->trueColor) - { - /* Oy veh. Remap the PNG palette to put the - entries with interesting alpha channel - values first. This minimizes the size - of the tRNS chunk and thus the size - of the PNG file as a whole. */ - int tc = 0; - int i; - int j; - int k; - for (i = 0; (i < im->colorsTotal); i++) - { - if ((!im->open[i]) && - (im->alpha[i] != gdAlphaOpaque)) - { - tc++; - } + + if (im->trueColor && !im->saveAlphaFlag && (transparent >= 0)) { + /* 2.0.9: fixed by Thomas Winzig */ + trans_rgb_value.red = gdTrueColorGetRed (im->transparent); + trans_rgb_value.green = gdTrueColorGetGreen (im->transparent); + trans_rgb_value.blue = gdTrueColorGetBlue (im->transparent); + png_set_tRNS(png_ptr, info_ptr, 0, 0, &trans_rgb_value); } - if (tc) - { + + if (!im->trueColor) { + /* Oy veh. Remap the PNG palette to put the entries with interesting alpha channel + * values first. This minimizes the size of the tRNS chunk and thus the size + * of the PNG file as a whole. + */ + + int tc = 0; + int i; + int j; + int k; + + for (i = 0; (i < im->colorsTotal); i++) { + if ((!im->open[i]) && (im->alpha[i] != gdAlphaOpaque)) { + tc++; + } + } + if (tc) { #if 0 - for (i = 0; (i < im->colorsTotal); i++) - { - trans_values[i] = 255 - - ((im->alpha[i] << 1) + - (im->alpha[i] >> 6)); - } - png_set_tRNS (png_ptr, info_ptr, trans_values, 256, NULL); + for (i = 0; (i < im->colorsTotal); i++) { + trans_values[i] = 255 - ((im->alpha[i] << 1) + (im->alpha[i] >> 6)); + } + png_set_tRNS (png_ptr, info_ptr, trans_values, 256, NULL); #endif - if (!remap) - { - remap = TRUE; - } - /* (Semi-)transparent indexes come up from the bottom - of the list of real colors; opaque - indexes come down from the top */ - j = 0; - k = colors - 1; - for (i = 0; (i < im->colorsTotal); i++) - { - if (!im->open[i]) - { - if (im->alpha[i] != gdAlphaOpaque) - { - /* Andrew Hull: >> 6, not >> 7! (gd 2.0.5) */ - trans_values[j] = 255 - - ((im->alpha[i] << 1) + - (im->alpha[i] >> 6)); - mapping[i] = j++; - } - else - { - mapping[i] = k--; - } + if (!remap) { + remap = TRUE; + } + + /* (Semi-)transparent indexes come up from the bottom of the list of real colors; opaque + * indexes come down from the top + */ + j = 0; + k = colors - 1; + + for (i = 0; i < im->colorsTotal; i++) { + if (!im->open[i]) { + if (im->alpha[i] != gdAlphaOpaque) { + /* Andrew Hull: >> 6, not >> 7! (gd 2.0.5) */ + trans_values[j] = 255 - ((im->alpha[i] << 1) + (im->alpha[i] >> 6)); + mapping[i] = j++; + } else { + mapping[i] = k--; + } + } + } + png_set_tRNS(png_ptr, info_ptr, trans_values, tc, NULL); } - } - png_set_tRNS (png_ptr, info_ptr, trans_values, tc, NULL); } - } - /* convert palette to libpng layout */ - if (!im->trueColor) - { - if (remap) - for (i = 0; i < im->colorsTotal; ++i) - { - if (mapping[i] < 0) - continue; - palette[mapping[i]].red = im->red[i]; - palette[mapping[i]].green = im->green[i]; - palette[mapping[i]].blue = im->blue[i]; - } - else - for (i = 0; i < colors; ++i) - { - palette[i].red = im->red[i]; - palette[i].green = im->green[i]; - palette[i].blue = im->blue[i]; - } - png_set_PLTE (png_ptr, info_ptr, palette, colors); - } - - /* write out the PNG header info (everything up to first IDAT) */ - png_write_info (png_ptr, info_ptr); - - /* make sure < 8-bit images are packed into pixels as tightly as possible */ - png_set_packing (png_ptr); - - /* This code allocates a set of row buffers and copies the gd image data - * into them only in the case that remapping is necessary; in gd 1.3 and - * later, the im->pixels array is laid out identically to libpng's row - * pointers and can be passed to png_write_image() function directly. - * The remapping case could be accomplished with less memory for non- - * interlaced images, but interlacing causes some serious complications. */ - if (im->trueColor) - { - int channels = im->saveAlphaFlag ? 4 : 3; - /* Our little 7-bit alpha channel trick costs us a bit here. */ - png_bytep *row_pointers; - row_pointers = gdMalloc (sizeof (png_bytep) * height); - for (j = 0; j < height; ++j) - { - int bo = 0; - row_pointers[j] = (png_bytep) gdMalloc (width * channels); - for (i = 0; i < width; ++i) - { - unsigned char a; - row_pointers[j][bo++] = gdTrueColorGetRed (im->tpixels[j][i]); - row_pointers[j][bo++] = gdTrueColorGetGreen (im->tpixels[j][i]); - row_pointers[j][bo++] = gdTrueColorGetBlue (im->tpixels[j][i]); - if (im->saveAlphaFlag) - { - /* convert the 7-bit alpha channel to an 8-bit alpha channel. - We do a little bit-flipping magic, repeating the MSB - as the LSB, to ensure that 0 maps to 0 and - 127 maps to 255. We also have to invert to match - PNG's convention in which 255 is opaque. */ - a = gdTrueColorGetAlpha (im->tpixels[j][i]); - /* Andrew Hull: >> 6, not >> 7! (gd 2.0.5) */ - row_pointers[j][bo++] = 255 - ((a << 1) + (a >> 6)); + /* convert palette to libpng layout */ + if (!im->trueColor) { + if (remap) { + for (i = 0; i < im->colorsTotal; ++i) { + if (mapping[i] < 0) { + continue; + } + + palette[mapping[i]].red = im->red[i]; + palette[mapping[i]].green = im->green[i]; + palette[mapping[i]].blue = im->blue[i]; + } + } else { + for (i = 0; i < colors; ++i) { + palette[i].red = im->red[i]; + palette[i].green = im->green[i]; + palette[i].blue = im->blue[i]; + } } - } + png_set_PLTE(png_ptr, info_ptr, palette, colors); } - png_write_image (png_ptr, row_pointers); - png_write_end (png_ptr, info_ptr); + /* write out the PNG header info (everything up to first IDAT) */ + png_write_info(png_ptr, info_ptr); + + /* make sure < 8-bit images are packed into pixels as tightly as possible */ + png_set_packing(png_ptr); + + /* This code allocates a set of row buffers and copies the gd image data + * into them only in the case that remapping is necessary; in gd 1.3 and + * later, the im->pixels array is laid out identically to libpng's row + * pointers and can be passed to png_write_image() function directly. + * The remapping case could be accomplished with less memory for non- + * interlaced images, but interlacing causes some serious complications. + */ + + if (im->trueColor) { + int channels = im->saveAlphaFlag ? 4 : 3; + /* Our little 7-bit alpha channel trick costs us a bit here. */ + png_bytep *row_pointers; + row_pointers = gdMalloc(sizeof (png_bytep) * height); + for (j = 0; j < height; ++j) { + int bo = 0; + row_pointers[j] = (png_bytep) gdMalloc(width * channels); + for (i = 0; i < width; ++i) { + unsigned char a; + row_pointers[j][bo++] = gdTrueColorGetRed(im->tpixels[j][i]); + row_pointers[j][bo++] = gdTrueColorGetGreen(im->tpixels[j][i]); + row_pointers[j][bo++] = gdTrueColorGetBlue(im->tpixels[j][i]); + if (im->saveAlphaFlag) { + /* convert the 7-bit alpha channel to an 8-bit alpha channel. + * We do a little bit-flipping magic, repeating the MSB + * as the LSB, to ensure that 0 maps to 0 and + * 127 maps to 255. We also have to invert to match + * PNG's convention in which 255 is opaque. + */ + a = gdTrueColorGetAlpha(im->tpixels[j][i]); + /* Andrew Hull: >> 6, not >> 7! (gd 2.0.5) */ + row_pointers[j][bo++] = 255 - ((a << 1) + (a >> 6)); + } + } + } - for (j = 0; j < height; ++j) - gdFree (row_pointers[j]); - gdFree (row_pointers); - } - else - { - if (remap) - { - png_bytep *row_pointers; - row_pointers = gdMalloc (sizeof (png_bytep) * height); - for (j = 0; j < height; ++j) - { - row_pointers[j] = (png_bytep) gdMalloc (width); - for (i = 0; i < width; ++i) - row_pointers[j][i] = mapping[im->pixels[j][i]]; - } - - png_write_image (png_ptr, row_pointers); - png_write_end (png_ptr, info_ptr); - - for (j = 0; j < height; ++j) - gdFree (row_pointers[j]); - gdFree (row_pointers); - } - else - { - png_write_image (png_ptr, im->pixels); - png_write_end (png_ptr, info_ptr); + png_write_image(png_ptr, row_pointers); + png_write_end(png_ptr, info_ptr); + + for (j = 0; j < height; ++j) { + gdFree(row_pointers[j]); + } + + gdFree(row_pointers); + } else { + if (remap) { + png_bytep *row_pointers; + row_pointers = gdMalloc(sizeof (png_bytep) * height); + for (j = 0; j < height; ++j) { + row_pointers[j] = (png_bytep) gdMalloc(width); + for (i = 0; i < width; ++i) { + row_pointers[j][i] = mapping[im->pixels[j][i]]; + } + } + + png_write_image(png_ptr, row_pointers); + png_write_end(png_ptr, info_ptr); + + for (j = 0; j < height; ++j) { + gdFree(row_pointers[j]); + } + + gdFree(row_pointers); + } else { + png_write_image(png_ptr, im->pixels); + png_write_end(png_ptr, info_ptr); + } } - } - /* 1.6.3: maybe we should give that memory BACK! TBB */ - png_destroy_write_struct (&png_ptr, &info_ptr); + /* 1.6.3: maybe we should give that memory BACK! TBB */ + png_destroy_write_struct(&png_ptr, &info_ptr); } - #endif /* HAVE_LIBPNG */ diff --git a/ext/gd/libgd/gd_ss.c b/ext/gd/libgd/gd_ss.c index 10bc6aa747..78f91df9c9 100644 --- a/ext/gd/libgd/gd_ss.c +++ b/ext/gd/libgd/gd_ss.c @@ -17,37 +17,33 @@ extern gdImagePtr gdImageCreateFromPngSource (gdSourcePtr inSource); #define GD_SS_DBG(s) #ifdef HAVE_LIBPNG -void -gdImagePngToSink (gdImagePtr im, gdSinkPtr outSink) +void gdImagePngToSink (gdImagePtr im, gdSinkPtr outSink) { - gdIOCtx *out = gdNewSSCtx (NULL, outSink); - gdImagePngCtx (im, out); - out->gd_free (out); + gdIOCtx *out = gdNewSSCtx(NULL, outSink); + gdImagePngCtx(im, out); + out->gd_free(out); } -gdImagePtr -gdImageCreateFromPngSource (gdSourcePtr inSource) +gdImagePtr gdImageCreateFromPngSource (gdSourcePtr inSource) { - gdIOCtx *in = gdNewSSCtx (inSource, NULL); - gdImagePtr im; + gdIOCtx *in = gdNewSSCtx(inSource, NULL); + gdImagePtr im; - im = gdImageCreateFromPngCtx (in); + im = gdImageCreateFromPngCtx(in); - in->gd_free (in); + in->gd_free(in); - return im; + return im; } #else /* no HAVE_LIBPNG */ -void -gdImagePngToSink (gdImagePtr im, gdSinkPtr outSink) +void gdImagePngToSink (gdImagePtr im, gdSinkPtr outSink) { - php_gd_error("PNG support is not available\n"); + php_gd_error("PNG support is not available\n"); } -gdImagePtr -gdImageCreateFromPngSource (gdSourcePtr inSource) +gdImagePtr gdImageCreateFromPngSource (gdSourcePtr inSource) { - php_gd_error("PNG support is not available\n"); - return NULL; + php_gd_error("PNG support is not available\n"); + return NULL; } #endif /* HAVE_LIBPNG */ diff --git a/ext/gd/libgd/gd_wbmp.c b/ext/gd/libgd/gd_wbmp.c index 860f70c0a5..7307d6f9e9 100644 --- a/ext/gd/libgd/gd_wbmp.c +++ b/ext/gd/libgd/gd_wbmp.c @@ -1,5 +1,3 @@ - - /* WBMP: Wireless Bitmap Type 0: B/W, Uncompressed Bitmap Specification of the WBMP format can be found in the file: @@ -67,10 +65,9 @@ ** Wrapper around gdPutC for use with writewbmp ** */ -void -gd_putout (int i, void *out) +void gd_putout (int i, void *out) { - gdPutC (i, (gdIOCtx *) out); + gdPutC(i, (gdIOCtx *) out); } @@ -79,10 +76,9 @@ gd_putout (int i, void *out) ** Wrapper around gdGetC for use with readwbmp ** */ -int -gd_getin (void *in) +int gd_getin (void *in) { - return (gdGetC ((gdIOCtx *) in)); + return (gdGetC((gdIOCtx *) in)); } @@ -95,124 +91,111 @@ gd_getin (void *in) ** considered as background and will not be written ** out: the stream where to write */ -void -gdImageWBMPCtx (gdImagePtr image, int fg, gdIOCtx * out) +void gdImageWBMPCtx (gdImagePtr image, int fg, gdIOCtx * out) { + int x, y, pos; + Wbmp *wbmp; - int x, y, pos; - Wbmp *wbmp; - - - /* create the WBMP */ - if ((wbmp = createwbmp (gdImageSX (image), gdImageSY (image), WBMP_WHITE)) == NULL) - php_gd_error("Could not create WBMP\n"); - - /* fill up the WBMP structure */ - pos = 0; - for (y = 0; y < gdImageSY (image); y++) - { - for (x = 0; x < gdImageSX (image); x++) - { - if (gdImageGetPixel (image, x, y) == fg) - { - wbmp->bitmap[pos] = WBMP_BLACK; - } - pos++; + /* create the WBMP */ + if ((wbmp = createwbmp (gdImageSX (image), gdImageSY (image), WBMP_WHITE)) == NULL) { + php_gd_error("Could not create WBMP\n"); } - } - /* write the WBMP to a gd file descriptor */ - if (writewbmp (wbmp, &gd_putout, out)) - php_gd_error("Could not save WBMP\n"); - /* des submitted this bugfix: gdFree the memory. */ - freewbmp (wbmp); -} + /* fill up the WBMP structure */ + pos = 0; + for (y = 0; y < gdImageSY(image); y++) { + for (x = 0; x < gdImageSX(image); x++) { + if (gdImageGetPixel (image, x, y) == fg) { + wbmp->bitmap[pos] = WBMP_BLACK; + } + pos++; + } + } + /* write the WBMP to a gd file descriptor */ + if (writewbmp (wbmp, &gd_putout, out)) { + php_gd_error("Could not save WBMP\n"); + } + /* des submitted this bugfix: gdFree the memory. */ + freewbmp(wbmp); +} /* gdImageCreateFromWBMPCtx ** ------------------------ ** Create a gdImage from a WBMP file input from an gdIOCtx */ -gdImagePtr -gdImageCreateFromWBMPCtx (gdIOCtx * infile) +gdImagePtr gdImageCreateFromWBMPCtx (gdIOCtx * infile) { - /* FILE *wbmp_file; */ - Wbmp *wbmp; - gdImagePtr im = NULL; - int black, white; - int col, row, pos; - - if (readwbmp (&gd_getin, infile, &wbmp)) - return (NULL); - - if (!(im = gdImageCreate (wbmp->width, wbmp->height))) - { - freewbmp (wbmp); - return (NULL); - } - - /* create the background color */ - white = gdImageColorAllocate (im, 255, 255, 255); - /* create foreground color */ - black = gdImageColorAllocate (im, 0, 0, 0); - - /* fill in image (in a wbmp 1 = white/ 0 = black) */ - pos = 0; - for (row = 0; row < wbmp->height; row++) - { - for (col = 0; col < wbmp->width; col++) - { - if (wbmp->bitmap[pos++] == WBMP_WHITE) - { - gdImageSetPixel (im, col, row, white); - } - else - { - gdImageSetPixel (im, col, row, black); - } + /* FILE *wbmp_file; */ + Wbmp *wbmp; + gdImagePtr im = NULL; + int black, white; + int col, row, pos; + + if (readwbmp (&gd_getin, infile, &wbmp)) { + return NULL; } - } - freewbmp (wbmp); + if (!(im = gdImageCreate (wbmp->width, wbmp->height))) { + freewbmp (wbmp); + return NULL; + } - return (im); -} + /* create the background color */ + white = gdImageColorAllocate(im, 255, 255, 255); + /* create foreground color */ + black = gdImageColorAllocate(im, 0, 0, 0); + + /* fill in image (in a wbmp 1 = white/ 0 = black) */ + pos = 0; + for (row = 0; row < wbmp->height; row++) { + for (col = 0; col < wbmp->width; col++) { + if (wbmp->bitmap[pos++] == WBMP_WHITE) { + gdImageSetPixel(im, col, row, white); + } else { + gdImageSetPixel(im, col, row, black); + } + } + } + freewbmp(wbmp); + + return im; +} /* gdImageCreateFromWBMP ** --------------------- */ -gdImagePtr -gdImageCreateFromWBMP (FILE * inFile) +gdImagePtr gdImageCreateFromWBMP (FILE * inFile) { - gdImagePtr im; - gdIOCtx *in = gdNewFileCtx (inFile); - im = gdImageCreateFromWBMPCtx (in); - in->gd_free (in); - return (im); + gdImagePtr im; + gdIOCtx *in = gdNewFileCtx(inFile); + im = gdImageCreateFromWBMPCtx(in); + in->gd_free(in); + + return im; } /* gdImageWBMP ** ----------- */ -void -gdImageWBMP (gdImagePtr im, int fg, FILE * outFile) +void gdImageWBMP (gdImagePtr im, int fg, FILE * outFile) { - gdIOCtx *out = gdNewFileCtx (outFile); - gdImageWBMPCtx (im, fg, out); - out->gd_free (out); + gdIOCtx *out = gdNewFileCtx(outFile); + gdImageWBMPCtx(im, fg, out); + out->gd_free(out); } /* gdImageWBMPPtr ** -------------- */ -void * -gdImageWBMPPtr (gdImagePtr im, int *size, int fg) +void * gdImageWBMPPtr (gdImagePtr im, int *size, int fg) { - void *rv; - gdIOCtx *out = gdNewDynamicCtx (2048, NULL); - gdImageWBMPCtx (im, fg, out); - rv = gdDPExtractData (out, size); - out->gd_free (out); - return rv; + void *rv; + gdIOCtx *out = gdNewDynamicCtx(2048, NULL); + gdImageWBMPCtx(im, fg, out); + rv = gdDPExtractData(out, size); + out->gd_free(out); + + return rv; } |