cvs: php4(PHP_4_3) /ext/gd gd.c gdcache.c gdcache.h gdttf.c php_gd.h /ext/gd/libgd gd.c gd.h gd_arc_f_buggy.c gd_gd2.c gd_gif_in.c gd_jpeg.c gd_png.c
gd_ss.c gd_topal.c gd_wbmp.c gdcache.c gdft.c gdhelpers.c gdhelpers.h gdkanji.c gdxpm.c
| From: | Ilia Alshanetsky | Date: | Wed, 05 Mar 2003 16:04:21 +0000 |
| Subject: | cvs: php4(PHP_4_3) /ext/gd gd.c gdcache.c gdcache.h gdttf.c php_gd.h /ext/gd/libgd gd.c gd.h gd_arc_f_buggy.c gd_gd2.c gd_gif_in.c gd_jpeg.c gd_png.c gd_ss.c gd_topal.c gd_wbmp.c gdcache.c gdft.c gdhelpers.c gdhelpers.h gdkanji.c gdxpm.c |
||
| Groups: | php.cvs | ||
| Request: | Send a blank email to php-cvs+get-19386@lists.php.net to get a copy of this message | ||
iliaa Wed Mar 5 11:04:21 2003 EDT
Modified files: (Branch: PHP_4_3)
/php4/ext/gd gd.c gdcache.c gdcache.h gdttf.c php_gd.h
/php4/ext/gd/libgd gd.c gd.h gd_arc_f_buggy.c gd_gd2.c gd_gif_in.c
gd_jpeg.c gd_png.c gd_ss.c gd_topal.c gd_wbmp.c
gdcache.c gdft.c gdhelpers.c gdhelpers.h
gdkanji.c gdxpm.c
Log:
Synchronized bundled gd with gd 2.0.11 (bug fixes).
MFH
1) Use Zend allocation macros instead of native allocation functions.
2) Better error reporting mechanism.
3) Some style fixes, which allow easier code synchronization & maintenance.
Index: php4/ext/gd/gd.c diff -u php4/ext/gd/gd.c:1.221.2.13 php4/ext/gd/gd.c:1.221.2.14 --- php4/ext/gd/gd.c:1.221.2.13 Fri Feb 28 20:15:32 2003 +++ php4/ext/gd/gd.c Wed Mar 5 11:04:20 2003 @@ -18,7 +18,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: gd.c,v 1.221.2.13 2003/03/01 01:15:32 pajoye Exp $ */ +/* $Id: gd.c,v 1.221.2.14 2003/03/05 16:04:20 iliaa Exp $ */ /* gd 1.2 is copyright 1994, 1995, Quest Protein Database Center, Cold Spring Harbor Labs. */ @@ -122,12 +122,12 @@ PHP_FE(imageellipse, NULL) PHP_FE(imagechar, NULL) PHP_FE(imagecharup, NULL) + PHP_FE(imagecolorat, NULL) PHP_FE(imagecolorallocate, NULL) #if HAVE_LIBGD15 PHP_FE(imagepalettecopy, NULL) PHP_FE(imagecreatefromstring, NULL) #endif - PHP_FE(imagecolorat, NULL) PHP_FE(imagecolorclosest, NULL) #if HAVE_COLORCLOSESTHWB PHP_FE(imagecolorclosesthwb, NULL) @@ -148,13 +148,14 @@ PHP_FE(imagecreate, NULL) #if HAVE_LIBGD20 PHP_FE(imagecreatetruecolor, NULL) - PHP_FE(imageistruecolor, NULL) + PHP_FE(imageistruecolor, NULL) PHP_FE(imagetruecolortopalette, NULL) PHP_FE(imagesetthickness, NULL) PHP_FE(imagefilledarc, NULL) PHP_FE(imagefilledellipse, NULL) PHP_FE(imagealphablending, NULL) - PHP_FE(imagesavealpha, NULL) + PHP_FE(imagesavealpha, NULL) + PHP_FE(imagecolorallocatealpha, NULL) PHP_FE(imagecolorresolvealpha, NULL) PHP_FE(imagecolorclosestalpha, NULL) PHP_FE(imagecolorexactalpha, NULL) @@ -163,6 +164,7 @@ #ifdef HAVE_GD_BUNDLED PHP_FE(imagerotate, NULL) + PHP_FE(imageantialias, NULL) #endif #if HAVE_GD_IMAGESETTILE @@ -282,7 +284,7 @@ PHP_MINIT(gd), NULL, NULL, - NULL, + PHP_RSHUTDOWN(gd), PHP_MINFO(gd), NO_VERSION_YET, STANDARD_MODULE_PROPERTIES @@ -361,6 +363,17 @@ } /* }}} */ +/* {{{ PHP_RSHUTDOWN_FUNCTION + */ +PHP_RSHUTDOWN_FUNCTION(gd) +{ +#if HAVE_LIBGD20 && HAVE_GD_STRINGFT + gdFreeFontCache(); +#endif + return SUCCESS; +} +/* }}} */ + /* {{{ PHP_MINFO_FUNCTION */ PHP_MINFO_FUNCTION(gd) @@ -430,10 +443,8 @@ RETURN_FALSE; } - if (array_init(return_value) == FAILURE) { - php_error_docref(NULL TSRMLS_CC, E_ERROR, "Unable to initialize array"); - RETURN_FALSE; - } + array_init(return_value); + #if HAVE_GD_BUNDLED add_assoc_string(return_value, "GD Version", "bundled (2.0 compatible)", 1); #elif HAVE_LIBGD20 @@ -563,7 +574,7 @@ /* {{{ proto int imageloadfont(string filename) Load a new font */ -PHP_FUNCTION(imageloadfont) +PHP_FUNCTION(imageloadfont) { zval **file; int hdr_size = sizeof(gdFont) - sizeof(char *); @@ -591,7 +602,7 @@ * byte 8-11: (int) pixel width of each character * byte 12-15: (int) pixel height of each character * bytes 16-: (char) array with character data, one byte per pixel - * in each character, for a total of + * in each character, for a total of * (nchars*width*height) bytes. */ font = (gdFontPtr)emalloc(sizeof(gdFont)); @@ -673,7 +684,7 @@ stylearr = emalloc(sizeof(int) * zend_hash_num_elements(HASH_OF(*styles))); zend_hash_internal_pointer_reset_ex(HASH_OF(*styles), &pos); - + for (index=0;; zend_hash_move_forward_ex(HASH_OF(*styles), &pos)) { zval ** item; @@ -714,7 +725,7 @@ /* }}} */ /* {{{ proto int imageistruecolor(int im) - * return true if the image uses truecolor */ + return true if the image uses truecolor */ PHP_FUNCTION(imageistruecolor) { zval **IM; @@ -724,7 +735,7 @@ ZEND_WRONG_PARAM_COUNT(); } - ZEND_FETCH_RESOURCE(im, gdImagePtr, IM, -1, "Image", le_gd); + ZEND_FETCH_RESOURCE(im, gdImagePtr, IM, -1, "Image", le_gd); RETURN_BOOL(im->trueColor); } @@ -744,7 +755,7 @@ ZEND_FETCH_RESOURCE(im, gdImagePtr, IM, -1, "Image", le_gd); convert_to_boolean_ex(dither); convert_to_long_ex(ncolors); - + gdImageTrueColorToPalette(im, Z_LVAL_PP(dither), Z_LVAL_PP(ncolors)); RETURN_TRUE; @@ -802,7 +813,7 @@ ZEND_FETCH_RESOURCE(im, gdImagePtr, IM, -1, "Image", le_gd); convert_to_long_ex(thick); - + gdImageSetThickness(im, Z_LVAL_PP(thick)); RETURN_TRUE; @@ -819,7 +830,7 @@ if (ZEND_NUM_ARGS() != 6 || zend_get_parameters_ex(6, &IM, &cx, &cy, &w, &h, &color) == FAILURE) { ZEND_WRONG_PARAM_COUNT(); } - + ZEND_FETCH_RESOURCE(im, gdImagePtr, IM, -1, "Image", le_gd); convert_to_long_ex(cx); @@ -866,7 +877,7 @@ gdImageFilledArc(im, Z_LVAL_PP(cx), Z_LVAL_PP(cy), Z_LVAL_PP(w), Z_LVAL_PP(h), st, e, Z_LVAL_PP(col), Z_LVAL_PP(style)); RETURN_TRUE; } -/* }}} */ +/* }}} */ /* {{{ proto void imagealphablending(resource im, bool on) Turn alpha blending mode on or off for the given image */ @@ -881,7 +892,7 @@ ZEND_FETCH_RESOURCE(im, gdImagePtr, IM, -1, "Image", le_gd); convert_to_boolean_ex(blend); - + gdImageAlphaBlending(im, Z_LVAL_PP(blend)); RETURN_TRUE; @@ -890,22 +901,22 @@ #if HAVE_LIBGD20 /* {{{ proto void imagesavealpha(resource im, bool on) - * Include alpha channel to a saved image */ + Include alpha channel to a saved image */ PHP_FUNCTION(imagesavealpha) { - zval **IM, **save; - gdImagePtr im; + zval **IM, **save; + gdImagePtr im; - if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &IM, &save) == FAILURE) { - ZEND_WRONG_PARAM_COUNT(); - } + if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &IM, &save) == FAILURE) { + ZEND_WRONG_PARAM_COUNT(); + } - ZEND_FETCH_RESOURCE(im, gdImagePtr, IM, -1, "Image", le_gd); - convert_to_boolean_ex(save); + ZEND_FETCH_RESOURCE(im, gdImagePtr, IM, -1, "Image", le_gd); + convert_to_boolean_ex(save); - gdImageSaveAlpha(im, Z_LVAL_PP(save)); + gdImageSaveAlpha(im, Z_LVAL_PP(save)); - RETURN_TRUE; + RETURN_TRUE; } #endif @@ -931,6 +942,24 @@ /* }}} */ #endif +/* {{{ proto int imagecolorallocatealpha(resource im, int red, int green, int blue, int alpha) + Allocate a color with an alpha level. Works for true color and palette based images */ +PHP_FUNCTION(imagecolorallocatealpha) +{ + zval *IM; + int red, green, blue, alpha; + gdImagePtr im; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zllll", &IM, &red, &green, &blue, &alpha) == FAILURE) { + RETURN_FALSE; + } + + ZEND_FETCH_RESOURCE(im, gdImagePtr, &IM, -1, "Image", le_gd); + + RETURN_LONG(gdImageColorAllocateAlpha(im, red, green, blue, alpha)); +} +/* }}} */ + /* {{{ proto int imagecolorresolvealpha(resource im, int red, int green, int blue, int alpha) Resolve/Allocate a colour with an alpha level. Works for true colour and palette based images */ PHP_FUNCTION(imagecolorresolvealpha) @@ -941,7 +970,7 @@ if (ZEND_NUM_ARGS() != 5 || zend_get_parameters_ex(5, &IM, &red, &green, &blue, &alpha) == FAILURE) { ZEND_WRONG_PARAM_COUNT(); } - + ZEND_FETCH_RESOURCE(im, gdImagePtr, IM, -1, "Image", le_gd); convert_to_long_ex(red); @@ -963,7 +992,7 @@ if (ZEND_NUM_ARGS() != 5 || zend_get_parameters_ex(5, &IM, &red, &green, &blue, &alpha) == FAILURE) { ZEND_WRONG_PARAM_COUNT(); } - + ZEND_FETCH_RESOURCE(im, gdImagePtr, IM, -1, "Image", le_gd); convert_to_long_ex(red); @@ -985,14 +1014,14 @@ if (ZEND_NUM_ARGS() != 5 || zend_get_parameters_ex(5, &IM, &red, &green, &blue, &alpha) == FAILURE) { ZEND_WRONG_PARAM_COUNT(); } - + ZEND_FETCH_RESOURCE(im, gdImagePtr, IM, -1, "Image", le_gd); convert_to_long_ex(red); convert_to_long_ex(green); convert_to_long_ex(blue); convert_to_long_ex(alpha); - + RETURN_LONG(gdImageColorExactAlpha(im, Z_LVAL_PP(red), Z_LVAL_PP(green), Z_LVAL_PP(blue), Z_LVAL_PP(alpha))); } /* }}} */ @@ -1138,7 +1167,7 @@ Return the types of images supported in a bitfield - 1=GIF, 2=JPEG, 4=PNG, 8=WBMP, 16=XPM */ PHP_FUNCTION(imagetypes) { - int ret=0; + int ret=0; #ifdef HAVE_GD_GIF_CREATE ret = 1; #endif @@ -1151,7 +1180,7 @@ #ifdef HAVE_GD_WBMP ret |= 8; #endif -#ifdef HAVE_GD_XPM +#if defined(HAVE_GD_XPM) && defined(HAVE_GD_BUNDLED) ret |= 16; #endif if (ZEND_NUM_ARGS() != 0) { @@ -1194,15 +1223,15 @@ io_ctx->gd_free(io_ctx); #else io_ctx->free(io_ctx); -#endif +#endif return PHP_GDIMG_TYPE_WBM; } else { #if HAVE_LIBGD204 io_ctx->gd_free(io_ctx); #else io_ctx->free(io_ctx); -#endif - } +#endif + } } } #endif @@ -1211,7 +1240,7 @@ } /* }}} */ -#ifdef HAVE_LIBGD15 +#ifdef HAVE_LIBGD15 /* {{{ _php_image_create_from_string */ gdImagePtr _php_image_create_from_string(zval **data, char *tn, gdImagePtr (*ioctx_func_p)() TSRMLS_DC) @@ -1234,7 +1263,7 @@ io_ctx->gd_free(io_ctx); #else io_ctx->free(io_ctx); -#endif +#endif return im; } /* }}} */ @@ -1251,7 +1280,7 @@ if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &data) == FAILURE) { ZEND_WRONG_PARAM_COUNT(); } - + convert_to_string_ex(data); memcpy(sig, Z_STRVAL_PP(data), 8); @@ -1275,7 +1304,7 @@ RETURN_FALSE; #endif break; - + case PHP_GDIMG_TYPE_GIF: #ifdef HAVE_GD_GIF_READ im = _php_image_create_from_string (data, "GIF", gdImageCreateFromGifCtx TSRMLS_CC); @@ -1320,7 +1349,7 @@ /* {{{ _php_image_create_from */ -static void _php_image_create_from(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn, gdImagePtr (*func_p)(), gdImagePtr (*ioctx_func_p)()) +static void _php_image_create_from(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn, gdImagePtr (*func_p)(), gdImagePtr (*ioctx_func_p)()) { zval **file, **srcx, **srcy, **width, **height; gdImagePtr im = NULL; @@ -1328,19 +1357,19 @@ php_stream *stream; FILE * fp = NULL; int argc=ZEND_NUM_ARGS(); - + if ((image_type == PHP_GDIMG_TYPE_GD2PART && argc != 5) || - (image_type != PHP_GDIMG_TYPE_GD2PART && argc != 1) || + (image_type != PHP_GDIMG_TYPE_GD2PART && argc != 1) || zend_get_parameters_ex(argc, &file, &srcx, &srcy, &width, &height) == FAILURE) { ZEND_WRONG_PARAM_COUNT(); } - + convert_to_string_ex(file); if (argc == 5 && image_type == PHP_GDIMG_TYPE_GD2PART) { multi_convert_to_long_ex(4, srcx, srcy, width, height); } - + fn = Z_STRVAL_PP(file); stream = php_stream_open_wrapper(fn, "rb", REPORT_ERRORS|IGNORE_PATH|IGNORE_URL_WIN, NULL); @@ -1372,7 +1401,7 @@ php_error_docref(NULL TSRMLS_CC, E_WARNING,"Cannot read image data"); goto out_err; } - + io_ctx = gdNewDynamicCtx(buff_size, buff); if(!io_ctx) { php_error_docref(NULL TSRMLS_CC, E_WARNING,"Cannot allocate GD IO context"); @@ -1387,16 +1416,16 @@ io_ctx->gd_free(io_ctx); #else io_ctx->free(io_ctx); -#endif +#endif -#endif +#endif } else { /* try and force the stream to be FILE* */ if (FAILURE == php_stream_cast(stream, PHP_STREAM_AS_STDIO | PHP_STREAM_CAST_TRY_HARD, (void**)&fp, REPORT_ERRORS)) goto out_err; } - + if (!im && fp) { switch (image_type) { case PHP_GDIMG_TYPE_GD2PART: @@ -1517,19 +1546,20 @@ /* {{{ _php_image_output */ -static void _php_image_output(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn, void (*func_p)()) +static void _php_image_output(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn, void (*func_p)()) { - zval **imgind, **file, **quality; + zval **imgind, **file, **quality, **type; gdImagePtr im; char *fn = NULL; FILE *fp; int argc = ZEND_NUM_ARGS(); - int q = -1, i; + int q = -1, i, t = 1; /* The quality parameter for Wbmp stands for the threshold when called from image2wbmp() */ /* When called from imagewbmp() the quality parameter stands for the foreground color. Default: black. */ + /* The quality parameter for gd2 stands for chunk size */ - if (argc < 1 || argc > 3 || zend_get_parameters_ex(argc, &imgind, &file, &quality) == FAILURE) { + if (argc < 1 || argc > 4 || zend_get_parameters_ex(argc, &imgind, &file, &quality, &type) == FAILURE) { ZEND_WRONG_PARAM_COUNT(); } @@ -1542,6 +1572,10 @@ convert_to_long_ex(quality); q = Z_LVAL_PP(quality); } + if (argc == 4) { + convert_to_long_ex(type); + t = Z_LVAL_PP(type); + } } if ((argc == 2) || (argc == 3 && Z_STRLEN_PP(file))) { @@ -1555,7 +1589,7 @@ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to open '%s' for writing", fn); RETURN_FALSE; } - + switch(image_type) { case PHP_GDIMG_CONVERT_WBM: if(q<0||q>255) { @@ -1577,9 +1611,12 @@ } (*func_p)(im, fp); break; -#endif +#endif default: - (*func_p)(im, fp); + if (q == -1) { + q = 128; + } + (*func_p)(im, fp, q, t); break; } fflush(fp); @@ -1616,7 +1653,7 @@ } (*func_p)(im, tmp); break; -#endif +#endif default: (*func_p)(im, tmp); break; @@ -1706,7 +1743,7 @@ /* }}} */ #ifdef HAVE_GD_GD2 -/* {{{ proto int imagegd2(int im [, string filename]) +/* {{{ proto int imagegd2(int im [, string filename, [, int chunk_size, [, int type]]]) Output GD2 image to browser or file */ PHP_FUNCTION(imagegd2) { @@ -1734,6 +1771,7 @@ } /* }}} */ + /* {{{ proto int imagecolorallocate(int im, int red, int green, int blue) Allocate a color for an image */ PHP_FUNCTION(imagecolorallocate) @@ -1744,13 +1782,13 @@ if (ZEND_NUM_ARGS() != 4 || zend_get_parameters_ex(4, &IM, &red, &green, &blue) == FAILURE) { ZEND_WRONG_PARAM_COUNT(); } - + ZEND_FETCH_RESOURCE(im, gdImagePtr, IM, -1, "Image", le_gd); convert_to_long_ex(red); convert_to_long_ex(green); convert_to_long_ex(blue); - + RETURN_LONG(gdImageColorAllocate(im, Z_LVAL_PP(red), Z_LVAL_PP(green), Z_LVAL_PP(blue))); } /* }}} */ @@ -1766,7 +1804,7 @@ if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &dstim, &srcim) == FAILURE) { ZEND_WRONG_PARAM_COUNT(); } - + ZEND_FETCH_RESOURCE(dst, gdImagePtr, dstim, -1, "Image", le_gd); ZEND_FETCH_RESOURCE(src, gdImagePtr, srcim, -1, "Image", le_gd); @@ -1785,7 +1823,7 @@ if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &IM, &x, &y) == FAILURE) { ZEND_WRONG_PARAM_COUNT(); } - + ZEND_FETCH_RESOURCE(im, gdImagePtr, IM, -1, "Image", le_gd); convert_to_long_ex(x); @@ -1827,13 +1865,13 @@ if (ZEND_NUM_ARGS() != 4 || zend_get_parameters_ex(4, &IM, &red, &green, &blue) == FAILURE) { ZEND_WRONG_PARAM_COUNT(); } - + ZEND_FETCH_RESOURCE(im, gdImagePtr, IM, -1, "Image", le_gd); convert_to_long_ex(red); convert_to_long_ex(green); convert_to_long_ex(blue); - + RETURN_LONG(gdImageColorClosest(im, Z_LVAL_PP(red), Z_LVAL_PP(green), Z_LVAL_PP(blue))); } /* }}} */ @@ -1845,13 +1883,13 @@ { zval **IM, **red, **green, **blue; gdImagePtr im; - + if (ZEND_NUM_ARGS() != 4 || zend_get_parameters_ex(4, &IM, &red, &green, &blue) == FAILURE) { ZEND_WRONG_PARAM_COUNT(); } ZEND_FETCH_RESOURCE(im, gdImagePtr, IM, -1, "Image", le_gd); - + convert_to_long_ex(red); convert_to_long_ex(green); convert_to_long_ex(blue); @@ -1881,6 +1919,7 @@ RETURN_TRUE; } #endif + convert_to_long_ex(index); col = Z_LVAL_PP(index); @@ -1904,13 +1943,13 @@ if (ZEND_NUM_ARGS() != 4 || zend_get_parameters_ex(4, &IM, &red, &green, &blue) == FAILURE) { ZEND_WRONG_PARAM_COUNT(); } - + ZEND_FETCH_RESOURCE(im, gdImagePtr, IM, -1, "Image", le_gd); convert_to_long_ex(red); convert_to_long_ex(green); convert_to_long_ex(blue); - + RETURN_LONG(gdImageColorResolve(im, Z_LVAL_PP(red), Z_LVAL_PP(green), Z_LVAL_PP(blue))); } /* }}} */ @@ -1925,13 +1964,13 @@ if (ZEND_NUM_ARGS() != 4 || zend_get_parameters_ex(4, &IM, &red, &green, &blue) == FAILURE) { ZEND_WRONG_PARAM_COUNT(); } - + ZEND_FETCH_RESOURCE(im, gdImagePtr, IM, -1, "Image", le_gd); convert_to_long_ex(red); convert_to_long_ex(green); convert_to_long_ex(blue); - + RETURN_LONG(gdImageColorExact(im, Z_LVAL_PP(red), Z_LVAL_PP(green), Z_LVAL_PP(blue))); } /* }}} */ @@ -1947,16 +1986,16 @@ if (ZEND_NUM_ARGS() != 5 || zend_get_parameters_ex(5, &IM, &color, &red, &green, &blue) == FAILURE) { ZEND_WRONG_PARAM_COUNT(); } - + ZEND_FETCH_RESOURCE(im, gdImagePtr, IM, -1, "Image", le_gd); convert_to_long_ex(color); convert_to_long_ex(red); convert_to_long_ex(green); convert_to_long_ex(blue); - + col = Z_LVAL_PP(color); - + if (col >= 0 && col < gdImageColorsTotal(im)) { im->red[col] = Z_LVAL_PP(red); im->green[col] = Z_LVAL_PP(green); @@ -1978,26 +2017,24 @@ if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &IM, &index) == FAILURE) { ZEND_WRONG_PARAM_COUNT(); } - + ZEND_FETCH_RESOURCE(im, gdImagePtr, IM, -1, "Image", le_gd); convert_to_long_ex(index); col = Z_LVAL_PP(index); #if HAVE_LIBGD20 if ((col >= 0 && gdImageTrueColor(im)) || (!gdImageTrueColor(im) && col >= 0 && col < gdImageColorsTotal(im))) { - if (array_init(return_value) == FAILURE) { - RETURN_FALSE; - } + array_init(return_value); + add_assoc_long(return_value,"red", gdImageRed(im,col)); add_assoc_long(return_value,"green", gdImageGreen(im,col)); add_assoc_long(return_value,"blue", gdImageBlue(im,col)); add_assoc_long(return_value,"alpha", gdImageAlpha(im,col)); - } + } #else if (col >= 0 && col < gdImageColorsTotal(im)) { - if (array_init(return_value) == FAILURE) { - RETURN_FALSE; - } + array_init(return_value); + add_assoc_long(return_value,"red", im->red[col]); add_assoc_long(return_value,"green", im->green[col]); add_assoc_long(return_value,"blue", im->blue[col]); @@ -2038,7 +2075,7 @@ for (y = 0; y < gdImageSY(im); y++) { for (x = 0; x < gdImageSX(im); x++) { c = gdImageGetPixel(im, x, y); - gdImageSetPixel(im, x, y, + gdImageSetPixel(im, x, y, gdTrueColor( (int)((pow((pow((gdTrueColorGetRed(c) / 255.0), input)), 1.0 / output) * 255)+.5), (int)((pow((pow((gdTrueColorGetGreen(c) / 255.0), input)), 1.0 / output) * 255)+.5), @@ -2081,7 +2118,7 @@ RETURN_TRUE; } -/* }}} */ +/* }}} */ /* {{{ proto int imageline(int im, int x1, int y1, int x2, int y2, int col) Draw a line */ @@ -2102,10 +2139,15 @@ convert_to_long_ex(y2); convert_to_long_ex(col); - gdImageLine(im, Z_LVAL_PP(x1), Z_LVAL_PP(y1), Z_LVAL_PP(x2), Z_LVAL_PP(y2), Z_LVAL_PP(col)); +#ifdef HAVE_GD_BUNDLED + if (im->antialias) + gdImageAALine(im, Z_LVAL_PP(x1), Z_LVAL_PP(y1), Z_LVAL_PP(x2), Z_LVAL_PP(y2), Z_LVAL_PP(col)); + else +#endif + gdImageLine(im, Z_LVAL_PP(x1), Z_LVAL_PP(y1), Z_LVAL_PP(x2), Z_LVAL_PP(y2), Z_LVAL_PP(col)); RETURN_TRUE; } -/* }}} */ +/* }}} */ /* {{{ proto int imagedashedline(int im, int x1, int y1, int x2, int y2, int col) Draw a dashed line */ @@ -2153,7 +2195,7 @@ gdImageRectangle(im, Z_LVAL_PP(x1), Z_LVAL_PP(y1), Z_LVAL_PP(x2), Z_LVAL_PP(y2), Z_LVAL_PP(col)); RETURN_TRUE; } -/* }}} */ +/* }}} */ /* {{{ proto int imagefilledrectangle(int im, int x1, int y1, int x2, int y2, int col) Draw a filled rectangle */ @@ -2177,7 +2219,7 @@ gdImageFilledRectangle(im, Z_LVAL_PP(x1), Z_LVAL_PP(y1), Z_LVAL_PP(x2), Z_LVAL_PP(y2), Z_LVAL_PP(col)); RETURN_TRUE; } -/* }}} */ +/* }}} */ /* {{{ proto int imagearc(int im, int cx, int cy, int w, int h, int s, int e, int col) Draw a partial ellipse */ @@ -2210,7 +2252,7 @@ gdImageArc(im, Z_LVAL_PP(cx), Z_LVAL_PP(cy), Z_LVAL_PP(w), Z_LVAL_PP(h), st, e, Z_LVAL_PP(col)); RETURN_TRUE; } -/* }}} */ +/* }}} */ /* {{{ proto void imageellipse(resource im, int cx, int cy, int w, int h, int color) Draw an ellipse */ @@ -2222,7 +2264,7 @@ if (ZEND_NUM_ARGS() != 6 || zend_get_parameters_ex(6, &IM, &cx, &cy, &w, &h, &color) == FAILURE) { ZEND_WRONG_PARAM_COUNT(); } - + ZEND_FETCH_RESOURCE(im, gdImagePtr, IM, -1, "Image", le_gd); convert_to_long_ex(cx); @@ -2262,7 +2304,7 @@ gdImageFillToBorder(im, Z_LVAL_PP(x), Z_LVAL_PP(y), Z_LVAL_PP(border), Z_LVAL_PP(col)); RETURN_TRUE; } -/* }}} */ +/* }}} */ /* {{{ proto int imagefill(int im, int x, int y, int col) Flood fill */ @@ -2284,7 +2326,7 @@ gdImageFill(im, Z_LVAL_PP(x), Z_LVAL_PP(y), Z_LVAL_PP(col)); RETURN_TRUE; } -/* }}} */ +/* }}} */ /* {{{ proto int imagecolorstotal(int im) Find out the number of colors in an image's palette */ @@ -2301,7 +2343,7 @@ RETURN_LONG(gdImageColorsTotal(im)); } -/* }}} */ +/* }}} */ /* {{{ proto int imagecolortransparent(int im [, int col]) Define a color as transparent */ @@ -2334,7 +2376,7 @@ RETURN_LONG(gdImageGetTransparent(im)); } -/* }}} */ +/* }}} */ /* {{{ proto int imageinterlace(int im [, int interlace]) Enable or disable interlace */ @@ -2367,18 +2409,18 @@ RETURN_LONG(gdImageGetInterlaced(im)); } -/* }}} */ +/* }}} */ /* {{{ php_imagepolygon arg = 0 normal polygon arg = 1 filled polygon */ /* im, points, num_points, col */ -static void php_imagepolygon(INTERNAL_FUNCTION_PARAMETERS, int filled) +static void php_imagepolygon(INTERNAL_FUNCTION_PARAMETERS, int filled) { zval **IM, **POINTS, **NPOINTS, **COL; pval **var = NULL; gdImagePtr im; - gdPointPtr points; + gdPointPtr points; int npoints, col, nelem, i; if (ZEND_NUM_ARGS() != 4 || zend_get_parameters_ex(4, &IM, &POINTS, &NPOINTS, &COL) == FAILURE) { @@ -2458,7 +2500,7 @@ gdFontPtr font; int ind_type; TSRMLS_FETCH(); - + switch (size) { case 1: font = gdFontTiny; @@ -2503,7 +2545,7 @@ if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &SIZE) == FAILURE) { ZEND_WRONG_PARAM_COUNT(); } - + convert_to_long_ex(SIZE); font = php_find_gd_font(Z_LVAL_PP(SIZE)); @@ -2541,7 +2583,7 @@ for (py = y; (py > (y - f->w)); py--) { for (px = x; (px < (x + f->h)); px++) { if (f->data[fline + cy * f->w + cx]) { - gdImageSetPixel(im, px, py, color); + gdImageSetPixel(im, px, py, color); } cy++; } @@ -2557,7 +2599,7 @@ * arg = 2 ImageString * arg = 3 ImageStringUp */ -static void php_imagechar(INTERNAL_FUNCTION_PARAMETERS, int mode) +static void php_imagechar(INTERNAL_FUNCTION_PARAMETERS, int mode) { zval **IM, **SIZE, **X, **Y, **C, **COL; gdImagePtr im; @@ -2623,8 +2665,8 @@ /* }}} */ /* {{{ proto int imagechar(int im, int font, int x, int y, string c, int col) - Draw a character */ -PHP_FUNCTION(imagechar) + Draw a character */ +PHP_FUNCTION(imagechar) { php_imagechar(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); } @@ -2632,7 +2674,7 @@ /* {{{ proto int imagecharup(int im, int font, int x, int y, string c, int col) Draw a character rotated 90 degrees counter-clockwise */ -PHP_FUNCTION(imagecharup) +PHP_FUNCTION(imagecharup) { php_imagechar(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); } @@ -2640,7 +2682,7 @@ /* {{{ proto int imagestring(int im, int font, int x, int y, string str, int col) Draw a string horizontally */ -PHP_FUNCTION(imagestring) +PHP_FUNCTION(imagestring) { php_imagechar(INTERNAL_FUNCTION_PARAM_PASSTHRU, 2); } @@ -2648,21 +2690,21 @@ /* {{{ proto int imagestringup(int im, int font, int x, int y, string str, int col) Draw a string vertically - rotated 90 degrees counter-clockwise */ -PHP_FUNCTION(imagestringup) +PHP_FUNCTION(imagestringup) { php_imagechar(INTERNAL_FUNCTION_PARAM_PASSTHRU, 3); } /* }}} */ /* {{{ proto int imagecopy(int dst_im, int src_im, int dst_x, int dst_y, int src_x, int src_y, int src_w, int src_h) - Copy part of an image */ + Copy part of an image */ PHP_FUNCTION(imagecopy) { zval **SIM, **DIM, **SX, **SY, **SW, **SH, **DX, **DY; gdImagePtr im_dst, im_src; int srcH, srcW, srcY, srcX, dstY, dstX; - if (ZEND_NUM_ARGS() != 8 || + if (ZEND_NUM_ARGS() != 8 || zend_get_parameters_ex(8, &DIM, &SIM, &DX, &DY, &SX, &SY, &SW, &SH) == FAILURE) { ZEND_WRONG_PARAM_COUNT(); } @@ -2802,7 +2844,7 @@ gdImageCopyResized(im_dst, im_src, dstX, dstY, srcX, srcY, dstW, dstH, srcW, srcH); RETURN_TRUE; } -/* }}} */ +/* }}} */ /* {{{ proto int imagesx(int im) Get image width */ @@ -2861,7 +2903,7 @@ php_imagettftext_common(INTERNAL_FUNCTION_PARAM_PASSTHRU, TTFTEXT_DRAW, 1); } /* }}} */ -#endif +#endif /* {{{ proto array imagettfbbox(int size, int angle, string font_file, string text) @@ -2898,7 +2940,7 @@ #if !HAVE_GD_STRINGFTEX assert(!extended); #endif - + argc = ZEND_NUM_ARGS(); if (mode == TTFTEXT_BBOX) { @@ -2933,12 +2975,12 @@ #if HAVE_GD_STRINGFTEX if (EXT) { /* parse extended info */ - + HashPosition pos; - + convert_to_array_ex(EXT); memset(&strex, 0, sizeof(strex)); - + /* walk the assoc array */ zend_hash_internal_pointer_reset_ex(HASH_OF(*EXT), &pos); do { @@ -2950,17 +2992,17 @@ if (zend_hash_get_current_data_ex(HASH_OF(*EXT), (void**)&item, &pos) == FAILURE) continue; - + if (strcmp("linespacing", key) == 0) { convert_to_double_ex(item); strex.flags |= gdFTEX_LINESPACE; strex.linespacing = Z_DVAL_PP(item); } - + } while(zend_hash_move_forward_ex(HASH_OF(*EXT), &pos) == SUCCESS); } #endif - + } ptsize = Z_DVAL_PP(PTSIZE); @@ -3001,10 +3043,8 @@ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", error); RETURN_FALSE; } - - if (array_init(return_value) == FAILURE) { - RETURN_FALSE; - } + + array_init(return_value); /* return array with the text's bounding box */ for (i = 0; i < 8; i++) { @@ -3249,15 +3289,15 @@ GLYPH *str_img; T1_OUTLINE *char_path, *str_path; T1_TMATRIX *transform = NULL; - char *_str; - int _str_len; + char *str; + int str_len; int argc = ZEND_NUM_ARGS(); - + if (argc != 8 && argc != 12) { ZEND_WRONG_PARAM_COUNT(); } - - if (zend_parse_parameters(ZEND_NUM_ARGS(), "rsrlllll|lldl", &img, &_str, &_str_len, &fnt, &size, &_fg, &_bg, &x, &y, &space, &width, &angle, &aa_steps) == FAILURE) { + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsrlllll|lldl", &img, &str, &str_len, &fnt, &size, &_fg, &_bg, &x, &y, &space, &width, &angle, &aa_steps) == FAILURE) { return; } @@ -3269,7 +3309,7 @@ if (_fg < 0 || (!gdImageTrueColor(bg_img) && _fg > gdImageColorsTotal(bg_img))) { #else if (_fg < 0 || _fg > gdImageColorsTotal(bg_img)) { -#endif +#endif php_error_docref(NULL TSRMLS_CC, E_WARNING, "Foreground color index %d out of range", _fg); RETURN_FALSE; } @@ -3278,11 +3318,11 @@ if (_bg < 0 || (!gdImageTrueColor(bg_img) && _fg > gdImageColorsTotal(bg_img))) { #else if (_bg < 0 || _bg > gdImageColorsTotal(bg_img)) { -#endif +#endif php_error_docref(NULL TSRMLS_CC, E_WARNING, "Background color index %d out of range", _bg); RETURN_FALSE; } - + fg_rd = gdImageRed (bg_img, _fg); fg_gr = gdImageGreen(bg_img, _fg); fg_bl = gdImageBlue (bg_img, _fg); @@ -3331,24 +3371,24 @@ } extend = T1_GetExtend(*f_ind); - str_path = T1_GetCharOutline(*f_ind, _str[0], size, transform); + str_path = T1_GetCharOutline(*f_ind, str[0], size, transform); if (!str_path) { if (T1_errno) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "libt1 returned error %d", T1_errno); - } + } RETURN_FALSE; } - for (i = 1; i < _str_len; i++) { - amount_kern = (int) T1_GetKerning(*f_ind, _str[i-1], _str[i]); - amount_kern += _str[i-1] == ' ' ? space : 0; + for (i = 1; i < str_len; i++) { + amount_kern = (int) T1_GetKerning(*f_ind, str[i-1], str[i]); + amount_kern += str[i-1] == ' ' ? space : 0; add_width = (int) (amount_kern+width)/extend; char_path = T1_GetMoveOutline(*f_ind, add_width, 0, 0, size, transform); str_path = T1_ConcatOutlines(str_path, char_path); - char_path = T1_GetCharOutline(*f_ind, _str[i], size, transform); + char_path = T1_GetCharOutline(*f_ind, str[i], size, transform); str_path = T1_ConcatOutlines(str_path, char_path); } str_img = T1_AAFillOutline(str_path, 0); @@ -3374,10 +3414,7 @@ } } - if (array_init(return_value) == FAILURE) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Couldn't initialize array for returning bounding box"); - RETURN_FALSE; - } + array_init(return_value); add_next_index_long(return_value, str_img->metrics.leftSideBearing); add_next_index_long(return_value, str_img->metrics.descent); @@ -3479,10 +3516,8 @@ str_bbox = T1_GetStringBBox(*f_ind, Z_STRVAL_PP(str), Z_STRLEN_PP(str), space, T1_KERNING); } if (T1_errno) RETURN_FALSE; - - if (array_init(return_value) == FAILURE) { - RETURN_FALSE; - } + + array_init(return_value); /* printf("%d %d %d %d\n", str_bbox.llx, str_bbox.lly, str_bbox.urx, str_bbox.ury); */ @@ -3492,7 +3527,7 @@ add_next_index_long(return_value, (int) ceil(((double) str_bbox.ury)*Z_LVAL_PP(sz)/1000)); } /* }}} */ -#endif +#endif #ifdef HAVE_GD_WBMP /* {{{ proto int image2wbmp(int im [, string filename [, int threshold]]) @@ -3527,7 +3562,7 @@ #ifdef HAVE_GD_WBMP /* {{{ _php_image_bw_convert * It converts a gd Image to bw using a threshold value */ -static void _php_image_bw_convert( gdImagePtr im_org, gdIOCtx *out, int threshold) +static void _php_image_bw_convert( gdImagePtr im_org, gdIOCtx *out, int threshold) { gdImagePtr im_dest; int white, black; @@ -3536,7 +3571,7 @@ int dest_width = gdImageSX (im_org); int x, y; TSRMLS_FETCH(); - + im_dest = gdImageCreate (dest_width, dest_height); if (im_dest == NULL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to allocate temporary buffer"); @@ -3578,7 +3613,7 @@ /* {{{ _php_image_convert * _php_image_convert converts jpeg/png images to wbmp and resizes them as needed */ -static void _php_image_convert(INTERNAL_FUNCTION_PARAMETERS, int image_type ) +static void _php_image_convert(INTERNAL_FUNCTION_PARAMETERS, int image_type ) { zval **f_org, **f_dest, **height, **width, **threshold; gdImagePtr im_org, im_dest, im_tmp; @@ -3769,6 +3804,25 @@ } /* }}} */ #endif /* HAVE_GD_WBMP */ + +#ifdef HAVE_GD_BUNDLED +/* {{{ proto imagesetantialias(int im, bool on) + Should antialiased functions used or not*/ +PHP_FUNCTION(imageantialias) +{ + zval **IM, **alias; + gdImagePtr im; + + if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &IM, &alias) == FAILURE) { + ZEND_WRONG_PARAM_COUNT(); + } + ZEND_FETCH_RESOURCE(im, gdImagePtr, IM, -1, "Image", le_gd); + convert_to_boolean_ex(alias); + gdImageAntialias(im, Z_LVAL_PP(alias)); + RETURN_TRUE; +} +/* }}} */ +#endif #endif /* HAVE_LIBGD */ Index: php4/ext/gd/gdcache.c diff -u php4/ext/gd/gdcache.c:1.5 php4/ext/gd/gdcache.c:1.5.2.1 --- php4/ext/gd/gdcache.c:1.5 Thu Oct 24 09:14:35 2002 +++ php4/ext/gd/gdcache.c Wed Mar 5 11:04:20 2003 @@ -1,5 +1,5 @@ /* - * $Id: gdcache.c,v 1.5 2002/10/24 13:14:35 sas Exp $ + * $Id: gdcache.c,v 1.5.2.1 2003/03/05 16:04:20 iliaa Exp $ * * Caches of pointers to user structs in which the least-recently-used * element is replaced in the event of a cache miss after the cache has @@ -36,6 +36,8 @@ * sizes of a few tens of elements. */ +#include "php.h" + /* This just seems unessacary */ #if PHP_WIN32 #define ENABLE_GD_TTF @@ -61,7 +63,7 @@ { gdCache_head_t *head; - head = (gdCache_head_t *)malloc(sizeof(gdCache_head_t)); + head = (gdCache_head_t *)pemalloc(sizeof(gdCache_head_t), 1); head->mru = NULL; head->size = size; head->gdCacheTest = gdCacheTest; @@ -80,9 +82,9 @@ (*(head->gdCacheRelease))(elem->userdata); prev = elem; elem = elem->next; - free((char *)prev); + pefree((char *)prev, 1); } - free((char *)head); + pefree((char *)head, 1); } void * @@ -114,7 +116,7 @@ return NULL; } if (i < head->size) { /* cache still growing - add new elem */ - elem = (gdCache_element_t *)malloc(sizeof(gdCache_element_t)); + elem = (gdCache_element_t *)pemalloc(sizeof(gdCache_element_t), 1); } else { /* cache full - replace least-recently-used */ /* preveprev becomes new end of list */ Index: php4/ext/gd/gdcache.h diff -u php4/ext/gd/gdcache.h:1.2.14.1 php4/ext/gd/gdcache.h:1.2.14.2 --- php4/ext/gd/gdcache.h:1.2.14.1 Fri Nov 29 06:15:43 2002 +++ php4/ext/gd/gdcache.h Wed Mar 5 11:04:20 2003 @@ -1,5 +1,5 @@ /* - * $Id: gdcache.h,v 1.2.14.1 2002/11/29 11:15:43 martin Exp $ + * $Id: gdcache.h,v 1.2.14.2 2003/03/05 16:04:20 iliaa Exp $ * * Caches of pointers to user structs in which the least-recently-used * element is replaced in the event of a cache miss after the cache has Index: php4/ext/gd/gdttf.c diff -u php4/ext/gd/gdttf.c:1.16 php4/ext/gd/gdttf.c:1.16.10.1 --- php4/ext/gd/gdttf.c:1.16 Sat Aug 11 12:38:30 2001 +++ php4/ext/gd/gdttf.c Wed Mar 5 11:04:20 2003 @@ -2,7 +2,7 @@ /* */ /* John Ellson ellson@lucent.com */ -/* $Id: gdttf.c,v 1.16 2001/08/11 16:38:30 zeev Exp $ */ +/* $Id: gdttf.c,v 1.16.10.1 2003/03/05 16:04:20 iliaa Exp $ */ #include "php.h" @@ -334,15 +334,16 @@ short platform, encoding; TSRMLS_FETCH(); - a = (font_t *)malloc(sizeof(font_t)); + a = (font_t *)pemalloc(sizeof(font_t), 1); #ifdef VIRTUAL_DIR /* a->fontname will be freed in fontRelease() later on */ if (virtual_filepath(b->fontname, &a->fontname TSRMLS_CC)) { *error = "Could not find/open font"; + pefree(a, 1); return NULL; } #else - a->fontname = (char *)malloc(strlen(b->fontname) + 1); + a->fontname = (char *)pemalloc(strlen(b->fontname) + 1, 1); strcpy(a->fontname, b->fontname); #endif a->ptsize = b->ptsize; @@ -357,6 +358,7 @@ else { *error = "Could not read font"; } + pefree(a, 1); return NULL; } /* get face properties and allocate preload arrays */ @@ -365,20 +367,19 @@ /* create instance */ if (TT_New_Instance(a->face, &a->instance)) { *error = "Could not create face instance"; + pefree(a, 1); return NULL; } if (TT_Set_Instance_Resolutions(a->instance, RESOLUTION, RESOLUTION)) { *error = "Could not set device resolutions"; + pefree(a, 1); return NULL; -map_found = 0; -a->have_char_map_Unicode = 0; -a->have_char_map_Big5 = 0; -a->have_char_map_Roman = 0; } if (TT_Set_Instance_CharSize(a->instance, (TT_F26Dot6)(a->ptsize*64))) { *error = "Could not set character size"; + pefree(a, 1); return NULL; } @@ -403,13 +404,14 @@ TT_Get_CharMap(a->face, i, &a->char_map_Roman); a->have_char_map_Roman = 1; map_found++; - } + } } if (! map_found) { *error = "Unable to find a CharMap that I can handle"; - return NULL; - } + pefree(a, 1); + return NULL; + } a->matrix.xx = (TT_Fixed) (a->cos_a * (1<<16)); a->matrix.yx = (TT_Fixed) (a->sin_a * (1<<16)); @@ -430,8 +432,8 @@ gdCacheDelete(a->glyphCache); TT_Done_Instance(a->instance); TT_Close_Face(a->face); - free(a->fontname); - free( (char *)element ); + pefree(a->fontname, 1); + pefree((char *)element, 1); } /********************************************************************/ @@ -458,7 +460,7 @@ int crect[8], xmin, xmax, ymin, ymax; double cos_a, sin_a; - a = (glyph_t *)malloc(sizeof(glyph_t)); + a = (glyph_t *)pemalloc(sizeof(glyph_t), 1); a->character = b->character; a->hinting = b->hinting; a->gray_render = b->gray_render; @@ -467,6 +469,7 @@ /* create glyph container */ if ((TT_New_Glyph(b->font->face, &a->glyph))) { *error = "Could not create glyph container"; + pefree(a, 1); return NULL; } @@ -483,6 +486,7 @@ } if ((err=TT_Load_Glyph(b->font->instance, a->glyph, glyph_code, flags))) { *error = "TT_Load_Glyph problem"; + pefree(a, 1); return NULL; } @@ -540,7 +544,7 @@ gdCacheDelete(a->bitmapCache); TT_Done_Glyph( a->glyph ); - free( (char *)element ); + pefree ((char *)element, 1); } /********************************************************************/ @@ -565,11 +569,11 @@ bitmap_t *a; bitmapkey_t *b=(bitmapkey_t *)key; - a = (bitmap_t *)malloc(sizeof(bitmap_t)); + a = (bitmap_t *)pemalloc(sizeof(bitmap_t), 1); a->xoffset = b->xoffset; a->yoffset = b->yoffset; - b->glyph->Bit.bitmap = a->bitmap = (char *)malloc(b->glyph->Bit.size); + b->glyph->Bit.bitmap = a->bitmap = (char *)pemalloc(b->glyph->Bit.size, 1); memset(a->bitmap, 0, b->glyph->Bit.size); /* render glyph */ if (b->glyph->gray_render) { @@ -588,8 +592,8 @@ { bitmap_t *a=(bitmap_t *)element; - free( a->bitmap ); - free( (char *)element ); + pefree (a->bitmap, 1); + pefree ((char *)element, 1); } /********************************************************************/ @@ -615,7 +619,7 @@ int pixel, npixel, bg, fg; gdImagePtr im; - a = (tweencolor_t *)malloc(sizeof(tweencolor_t)); + a = (tweencolor_t *)pemalloc(sizeof(tweencolor_t), 1); pixel = a->pixel = b->pixel; bg = a->bgcolor = b->bgcolor; fg = a->fgcolor = b->fgcolor; @@ -638,7 +642,7 @@ static void tweenColorRelease(void *element) { - free((char *)element); + pefree((char *)element, 1); } /********************************************************************/ Index: php4/ext/gd/php_gd.h diff -u php4/ext/gd/php_gd.h:1.44.2.3 php4/ext/gd/php_gd.h:1.44.2.4 --- php4/ext/gd/php_gd.h:1.44.2.3 Fri Feb 28 20:15:47 2003 +++ php4/ext/gd/php_gd.h Wed Mar 5 11:04:20 2003 @@ -1,4 +1,4 @@ -/* +/* +----------------------------------------------------------------------+ | PHP Version 4 | +----------------------------------------------------------------------+ @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_gd.h,v 1.44.2.3 2003/03/01 01:15:47 pajoye Exp $ */ +/* $Id: php_gd.h,v 1.44.2.4 2003/03/05 16:04:20 iliaa Exp $ */ #ifndef PHP_GD_H #define PHP_GD_H @@ -58,11 +58,14 @@ PHP_MINFO_FUNCTION(gd); PHP_MINIT_FUNCTION(gd); PHP_MSHUTDOWN_FUNCTION(gd); +PHP_RSHUTDOWN_FUNCTION(gd); PHP_FUNCTION(gd_info); PHP_FUNCTION(imagearc); +PHP_FUNCTION(imageellipse); PHP_FUNCTION(imagechar); PHP_FUNCTION(imagecharup); +PHP_FUNCTION(imageistruecolor); PHP_FUNCTION(imagecolorallocate); PHP_FUNCTION(imagepalettecopy); PHP_FUNCTION(imagecolorat); @@ -83,26 +86,27 @@ PHP_FUNCTION(imageftbbox); PHP_FUNCTION(imagefttext); +#ifdef HAVE_LIBGD20 PHP_FUNCTION(imagecreatetruecolor); -PHP_FUNCTION(imageistruecolor); PHP_FUNCTION(imagetruecolortopalette); PHP_FUNCTION(imagesetthickness); -PHP_FUNCTION(imageellipse); PHP_FUNCTION(imagefilledellipse); PHP_FUNCTION(imagefilledarc); PHP_FUNCTION(imagealphablending); PHP_FUNCTION(imagesavealpha); +PHP_FUNCTION(imagecolorallocatealpha); PHP_FUNCTION(imagecolorresolvealpha); PHP_FUNCTION(imagecolorclosestalpha); PHP_FUNCTION(imagecolorexactalpha); PHP_FUNCTION(imagecopyresampled); +#endif #ifdef HAVE_GD_BUNDLED PHP_FUNCTION(imagerotate); +PHP_FUNCTION(imageantialias); #endif PHP_FUNCTION(imagesetthickness); -PHP_FUNCTION(imagesettile); PHP_FUNCTION(imagecopymergegray); PHP_FUNCTION(imagesetbrush); PHP_FUNCTION(imagesettile); @@ -168,6 +172,7 @@ #if HAVE_GD_BUNDLED PHP_FUNCTION(imagelayereffect); PHP_FUNCTION(imagecolormatch); +PHP_FUNCTION(imagefilter); #endif PHP_GD_API int phpi_get_le_gd(void); Index: php4/ext/gd/libgd/gd.c diff -u php4/ext/gd/libgd/gd.c:1.24.2.4 php4/ext/gd/libgd/gd.c:1.24.2.5 --- php4/ext/gd/libgd/gd.c:1.24.2.4 Mon Feb 24 22:53:22 2003 +++ php4/ext/gd/libgd/gd.c Wed Mar 5 11:04:20 2003 @@ -81,6 +81,9 @@ }; #endif /*CHARSET_EBCDIC */ +/* 2.0.10: cast instead of floor() yields 35% performance improvement. Thanks to John Buckman. */ +#define floor_cast(exp) ((long) exp) + extern int gdCosT[]; extern int gdSinT[]; @@ -92,6 +95,28 @@ static int gdAlphaOverlayColor(int src, int dst, int max); static int gdImageGetTrueColorPixel(gdImagePtr im, int x, int y); +void php_gd_error_ex(int type, const char *format, ...) +{ + va_list args; + + TSRMLS_FETCH(); + + va_start(args, format); + php_verror(NULL, "", type, format, args TSRMLS_CC); + va_end(args); +} + +void php_gd_error(const char *format, ...) +{ + va_list args; + + TSRMLS_FETCH(); + + va_start(args, format); + php_verror(NULL, "", E_WARNING, format, args TSRMLS_CC); + va_end(args); +} + gdImagePtr gdImageCreate (int sx, int sy) { @@ -319,7 +344,7 @@ } else { - diff = fabsf (HWB1.H - HWB2.H); + diff = fabsf(HWB1.H - HWB2.H); if (diff > 3.0f) { diff = 6.0f - diff; /* Remember, it's a colour circle */ @@ -375,8 +400,9 @@ } return RGB; + } -#endif /* 0 */ +#endif int gdImageColorClosestHWB (gdImagePtr im, int r, int g, int b) @@ -516,12 +542,12 @@ op = c; /* Save open slot */ continue; /* Color not in use */ } - if (c == im->transparent) - { - /* don't ever resolve to the color that has - * been designated as the transparent color */ - continue; - } + if (c == im->transparent) + { + /* don't ever resolve to the color that has + * been designated as the transparent color */ + continue; + } rd = (long) (im->red[c] - r); gd = (long) (im->green[c] - g); bd = (long) (im->blue[c] - b); @@ -572,7 +598,7 @@ if (im->transparent != -1) { im->alpha[im->transparent] = gdAlphaOpaque; } - if (color > -1 && color <= gdMaxColors) { + if (color > -1 && color<=gdMaxColors) { im->alpha[color] = gdAlphaTransparent; } else { return; @@ -638,6 +664,76 @@ } +/* 2.0.10: before the drawing routines, some code to clip points that are + * outside the drawing window. Nick Atty (nick@canalplan.org.uk) + * + * This is the Sutherland Hodgman Algorithm, as implemented by + * Duvanenko, Robbins and Gyurcsik - SH(DRG) for short. See Dr Dobb's + * Journal, January 1996, pp107-110 and 116-117 + * + * Given the end points of a line, and a bounding rectangle (which we + * know to be from (0,0) to (SX,SY)), adjust the endpoints to be on + * the edges of the rectangle if the line should be drawn at all, + * otherwise return a failure code + */ + +/* this does "one-dimensional" clipping: note that the second time it + * is called, all the x parameters refer to height and the y to width + * - the comments ignore this (if you can understand it when it's + * looking at the X parameters, it should become clear what happens on + * the second call!) The code is simplified from that in the article, + * as we know that gd images always start at (0,0) + */ + +static int clip_1d(int *x0, int *y0, int *x1, int *y1, int maxdim) { + double m; /* gradient of line */ + + if (*x0 < 0) { /* start of line is left of window */ + if(*x1 < 0) { /* as is the end, so the line never cuts the window */ + return 0; + } + m = (*y1 - *y0)/(double)(*x1 - *x0); /* calculate the slope of the line */ + /* adjust x0 to be on the left boundary (ie to be zero), and y0 to match */ + *y0 -= (int)(m * *x0); + *x0 = 0; + /* now, perhaps, adjust the far end of the line as well */ + if (*x1 > maxdim) { + *y1 += (int)(m * (maxdim - *x1)); + *x1 = maxdim; + } + return 1; + } + if (*x0 > maxdim) { /* start of line is right of window - complement of above */ + if (*x1 > maxdim) { /* as is the end, so the line misses the window */ + return 0; + } + m = (*y1 - *y0)/(double)(*x1 - *x0); /* calculate the slope of the line */ + *y0 += (int)(m * (maxdim - *x0)); /* adjust so point is on the right boundary */ + *x0 = maxdim; + /* now, perhaps, adjust the end of the line */ + if (*x1 < 0) { + *y1 -= (int)(m * *x1); + *x1 = 0; + } + return 1; + } + /* the final case - the start of the line is inside the window */ + if (*x1 > maxdim) { /* other end is outside to the right */ + m = (*y1 - *y0)/(double)(*x1 - *x0); /* calculate the slope of the line */ + *y1 += (int)(m * (maxdim - *x1)); + *x1 = maxdim; + return 1; + } + if (*x1 < 0) { /* other end is outside to the left */ + m = (*y1 - *y0)/(double)(*x1 - *x0); /* calculate the slope of the line */ + *y1 -= (int)(m * *x1); + *x1 = 0; + return 1; + } + /* only get here if both points are inside the window */ + return 1; +} + void gdImageSetPixel (gdImagePtr im, int x, int y, int color) { @@ -725,74 +821,60 @@ static void gdImageBrushApply (gdImagePtr im, int x, int y) { - int lx, ly; - int hy; - int hx; - int x1, y1, x2, y2; - int srcx, srcy; - if (!im->brush) - { - return; - } - hy = gdImageSY (im->brush) / 2; - y1 = y - hy; - y2 = y1 + gdImageSY (im->brush); - hx = gdImageSX (im->brush) / 2; - x1 = x - hx; - x2 = x1 + gdImageSX (im->brush); - srcy = 0; - if (im->trueColor) - { - for (ly = y1; (ly < y2); ly++) - { - srcx = 0; - for (lx = x1; (lx < x2); lx++) - { - int p; - p = gdImageGetTrueColorPixel ( - im->brush, srcx, srcy); - gdImageSetPixel (im, lx, ly, - p); - srcx++; - } - srcy++; - } - } - else - { - for (ly = y1; (ly < y2); ly++) - { - srcx = 0; - for (lx = x1; (lx < x2); lx++) - { - int p; - p = gdImageGetPixel (im->brush, srcx, srcy); - /* Allow for non-square brushes! */ - if (p != gdImageGetTransparent (im->brush)) - { - /* Truecolor brush. Very slow - on a palette destination. */ - if (im->brush->trueColor) - { - gdImageSetPixel (im, lx, ly, - gdImageColorResolveAlpha ( - im, - gdTrueColorGetRed (p), - gdTrueColorGetGreen (p), - gdTrueColorGetBlue (p), - gdTrueColorGetAlpha (p))); - } - else - { - gdImageSetPixel (im, lx, ly, - im->brushColorMap[p]); - } + int lx, ly; + int hy, hx; + int x1, y1, x2, y2; + int srcx, srcy; + + if (!im->brush) { + return; + } + + hy = gdImageSY (im->brush) / 2; + y1 = y - hy; + y2 = y1 + gdImageSY (im->brush); + hx = gdImageSX (im->brush) / 2; + x1 = x - hx; + x2 = x1 + gdImageSX (im->brush); + srcy = 0; + + if (im->trueColor) { + for (ly = y1; (ly < y2); ly++) { + srcx = 0; + for (lx = x1; (lx < x2); lx++) { + int p; + p = gdImageGetTrueColorPixel (im->brush, srcx, srcy); + /* 2.0.9, Thomas Winzig: apply simple full transparency */ + if (p != gdImageGetTransparent (im->brush)) { + gdImageSetPixel (im, lx, ly, p); + } + srcx++; + } + srcy++; + } + } else { + for (ly = y1; (ly < y2); ly++) { + srcx = 0; + for (lx = x1; (lx < x2); lx++) { + int p; + p = gdImageGetPixel (im->brush, srcx, srcy); + /* Allow for non-square brushes! */ + if (p != gdImageGetTransparent (im->brush)) { + /* Truecolor brush. Very slow on a palette destination. */ + if (im->brush->trueColor) { + gdImageSetPixel(im, lx, ly, gdImageColorResolveAlpha(im, gdTrueColorGetRed(p), + gdTrueColorGetGreen(p), + gdTrueColorGetBlue(p), + gdTrueColorGetAlpha(p))); + } else { + gdImageSetPixel(im, lx, ly, im->brushColorMap[p]); + } + } + srcx++; + } + srcy++; } - srcx++; - } - srcy++; } - } } static void @@ -862,151 +944,272 @@ void gdImageLine (gdImagePtr im, int x1, int y1, int x2, int y2, int color) { - int dx, dy, incr1, incr2, d, x, y, xend, yend, xdirflag, ydirflag; - int wid; - int w, wstart; - int thick = im->thick; - dx = abs (x2 - x1); - dy = abs (y2 - y1); - if (dy <= dx) - { - /* More-or-less horizontal. use wid for vertical stroke */ - wid = (int)(thick * cos (atan2 (dy, dx))); - if (wid == 0) - wid = 1; - - d = 2 * dy - dx; - incr1 = 2 * dy; - incr2 = 2 * (dy - dx); - if (x1 > x2) - { - x = x2; - y = y2; - ydirflag = (-1); - xend = x1; - } - else - { - x = x1; - y = y1; - ydirflag = 1; - xend = x2; + int dx, dy, incr1, incr2, d, x, y, xend, yend, xdirflag, ydirflag; + int wid; + int w, wstart; + int thick = im->thick; + + /* 2.0.10: Nick Atty: clip to edges of drawing rectangle, return if no points need to be drawn */ + if (!clip_1d(&x1,&y1,&x2,&y2,gdImageSX(im)) || !clip_1d(&y1,&x1,&y2,&x2,gdImageSY(im))) { + return; } - - /* Set up line thickness */ - wstart = y - wid / 2; - for (w = wstart; w < wstart + wid; w++) - gdImageSetPixel (im, x, w, color); - - if (((y2 - y1) * ydirflag) > 0) - { - while (x < xend) - { - x++; - if (d < 0) - { - d += incr1; + + dx = abs(x2 - x1); + dy = abs(y2 - y1); + if (dy <= dx) { + /* More-or-less horizontal. use wid for vertical stroke */ + /* Doug Claar: watch out for NaN in atan2 (2.0.5) */ + if ((dx == 0) && (dy == 0)) { + wid = 1; + } else { + wid = (int)(thick * cos (atan2 (dy, dx))); + if (wid == 0) { + wid = 1; + } } - else - { - y++; - d += incr2; + d = 2 * dy - dx; + incr1 = 2 * dy; + incr2 = 2 * (dy - dx); + if (x1 > x2) { + x = x2; + y = y2; + ydirflag = (-1); + xend = x1; + } else { + x = x1; + y = y1; + ydirflag = 1; + xend = x2; + } + + /* Set up line thickness */ + wstart = y - wid / 2; + for (w = wstart; w < wstart + wid; w++) { + gdImageSetPixel(im, x, w, color); + } + + if (((y2 - y1) * ydirflag) > 0) { + while (x < xend) { + x++; + if (d < 0) { + d += incr1; + } else { + y++; + d += incr2; + } + wstart = y - wid / 2; + for (w = wstart; w < wstart + wid; w++) { + gdImageSetPixel (im, x, w, color); + } + } + } else { + while (x < xend) { + x++; + if (d < 0) { + d += incr1; + } else { + y--; + d += incr2; + } + wstart = y - wid / 2; + for (w = wstart; w < wstart + wid; w++) { + gdImageSetPixel (im, x, w, color); + } + } } - wstart = y - wid / 2; - for (w = wstart; w < wstart + wid; w++) - gdImageSetPixel (im, x, w, color); - } - } - else - { - while (x < xend) - { - x++; - if (d < 0) - { - d += incr1; + } else { + /* More-or-less vertical. use wid for horizontal stroke */ + wid = (int)(thick * sin (atan2 (dy, dx))); + if (wid == 0) { + wid = 1; } - else - { - y--; - d += incr2; + + d = 2 * dx - dy; + incr1 = 2 * dx; + incr2 = 2 * (dx - dy); + if (y1 > y2) { + y = y2; + x = x2; + yend = y1; + xdirflag = (-1); + } else { + y = y1; + x = x1; + yend = y2; + xdirflag = 1; + } + + /* Set up line thickness */ + wstart = x - wid / 2; + for (w = wstart; w < wstart + wid; w++) { + gdImageSetPixel (im, w, y, color); + } + + if (((x2 - x1) * xdirflag) > 0) { + while (y < yend) { + y++; + if (d < 0) { + d += incr1; + } else { + x++; + d += incr2; + } + wstart = x - wid / 2; + for (w = wstart; w < wstart + wid; w++) { + gdImageSetPixel (im, w, y, color); + } + } + } else { + while (y < yend) { + y++; + if (d < 0) { + d += incr1; + } else { + x--; + d += incr2; + } + wstart = x - wid / 2; + for (w = wstart; w < wstart + wid; w++) { + gdImageSetPixel (im, w, y, color); + } + } } - wstart = y - wid / 2; - for (w = wstart; w < wstart + wid; w++) - gdImageSetPixel (im, x, w, color); - } } - } - else - { - /* More-or-less vertical. use wid for horizontal stroke */ - wid = (int)(thick * sin (atan2 (dy, dx))); - if (wid == 0) - wid = 1; +} - d = 2 * dx - dy; - incr1 = 2 * dx; - incr2 = 2 * (dx - dy); - if (y1 > y2) - { - y = y2; - x = x2; - yend = y1; - xdirflag = (-1); - } - else - { - y = y1; - x = x1; - yend = y2; - xdirflag = 1; - } - /* Set up line thickness */ - wstart = x - wid / 2; - for (w = wstart; w < wstart + wid; w++) - gdImageSetPixel (im, w, y, color); +/* + * Added on 2003/12 by Pierre-Alain Joye (pajoye@pearfr.org) + * */ +#define BLEND_COLOR(a, nc, c, cc) \ +nc = (cc) + (((((c) - (cc)) * (a)) + ((((c) - (cc)) * (a)) >> 8) + 0x80) >> 8); + +inline static void gdImageSetAAPixelColor(gdImagePtr im, int x, int y, int color, int t) +{ + int dr,dg,db,p,r,g,b; + dr = gdTrueColorGetRed(color); + dg = gdTrueColorGetGreen(color); + db = gdTrueColorGetBlue(color); + + p = gdImageGetPixel(im,x,y); + r = gdTrueColorGetRed(p); + g = gdTrueColorGetGreen(p); + b = gdTrueColorGetBlue(p); + + BLEND_COLOR(t, dr, r, dr); + BLEND_COLOR(t, dg, g, dg); + BLEND_COLOR(t, db, b, db); + im->tpixels[y][x]=gdTrueColorAlpha(dr, dg, db, gdAlphaOpaque); +} - if (((x2 - x1) * xdirflag) > 0) - { - while (y < yend) - { - y++; - if (d < 0) - { - d += incr1; - } - else - { - x++; - d += incr2; - } - wstart = x - wid / 2; - for (w = wstart; w < wstart + wid; w++) - gdImageSetPixel (im, w, y, color); - } - } - else - { - while (y < yend) - { - y++; - if (d < 0) - { - d += incr1; +/* + * Added on 2003/12 by Pierre-Alain Joye (pajoye@pearfr.org) + **/ +void gdImageAALine (gdImagePtr im, int x1, int y1, int x2, int y2, int col) +{ + /* keep them as 32bits */ + long x, y, inc; + long dx, dy,tmp; + + if (y1 < 0 && y2 < 0) { + return; + } + if (y1 < 0) { + x1 += (y1 * (x1 - x2)) / (y2 - y1); + y1 = 0; + } + if (y2 < 0) { + x2 += (y2 * (x1 - x2)) / (y2 - y1); + y2 = 0; + } + + /* bottom edge */ + if (y1 >= im->sy && y2 >= im->sy) { + return; + } + if (y1 >= im->sy) { + x1 -= ((im->sy - y1) * (x1 - x2)) / (y2 - y1); + y1 = im->sy - 1; + } + if (y2 >= im->sy) { + x2 -= ((im->sy - y2) * (x1 - x2)) / (y2 - y1); + y2 = im->sy - 1; + } + + /* left edge */ + if (x1 < 0 && x2 < 0) { + return; + } + if (x1 < 0) { + y1 += (x1 * (y1 - y2)) / (x2 - x1); + x1 = 0; + } + if (x2 < 0) { + y2 += (x2 * (y1 - y2)) / (x2 - x1); + x2 = 0; + } + /* right edge */ + if (x1 >= im->sx && x2 >= im->sx) { + return; + } + if (x1 >= im->sx) { + y1 -= ((im->sx - x1) * (y1 - y2)) / (x2 - x1); + x1 = im->sx - 1; + } + if (x2 >= im->sx) { + y2 -= ((im->sx - x2) * (y1 - y2)) / (x2 - x1); + x2 = im->sx - 1; + } + + dx = x2 - x1; + dy = y2 - y1; + + if (dx == 0 && dy == 0) { + return; + } + if (abs(dx) > abs(dy)) { + if (dx < 0) { + tmp = x1; + x1 = x2; + x2 = tmp; + tmp = y1; + y1 = y2; + y2 = tmp; + dx = x2 - x1; + dy = y2 - y1; + } + x = x1 << 16; + y = y1 << 16; + inc = (dy * 65536) / dx; + while ((x >> 16) < x2) { + gdImageSetAAPixelColor(im, x >> 16, y >> 16, col, (y >> 8) & 0xFF); + gdImageSetAAPixelColor(im, x >> 16, (y >> 16) + 1,col, (~y >> 8) & 0xFF); + x += (1 << 16); + y += inc; } - else - { - x--; - d += incr2; + } else { + if (dy < 0) { + tmp = x1; + x1 = x2; + x2 = tmp; + tmp = y1; + y1 = y2; + y2 = tmp; + dx = x2 - x1; + dy = y2 - y1; + } + x = x1 << 16; + y = y1 << 16; + inc = (dx * 65536) / dy; + while ((y>>16) < y2) { + gdImageSetAAPixelColor(im, x >> 16, y >> 16, col, (x >> 8) & 0xFF); + gdImageSetAAPixelColor(im, (x >> 16) + 1, (y >> 16),col, (~x >> 8) & 0xFF); + x += inc; + y += (1<<16); } - wstart = x - wid / 2; - for (w = wstart; w < wstart + wid; w++) - gdImageSetPixel (im, w, y, color); - } } - } } + static void dashedSet (gdImagePtr im, int x, int y, int color, int *onP, int *dashStepP, int wid, int vert); @@ -1175,13 +1378,6 @@ *onP = on; } -int -gdImageBoundsSafe (gdImagePtr im, int x, int y) -{ - return (!(((y < 0) || (y >= im->sy)) || - ((x < 0) || (x >= im->sx)))); -} - void gdImageChar (gdImagePtr im, gdFontPtr f, int x, int y, int c, int color) @@ -1428,6 +1624,7 @@ } } + /** * Integer Ellipse functions (gdImageEllipse and gdImageFilledEllipse) * Function added by Pierre-Alain Joye 02/08/2003 (paj@pearfr.org) @@ -1785,136 +1982,127 @@ void gdImageFilledRectangle (gdImagePtr im, int x1, int y1, int x2, int y2, int color) { - int x, y; - for (y = y1; (y <= y2); y++) - { - for (x = x1; (x <= x2); x++) - { - gdImageSetPixel (im, x, y, color); + int x, y; + + /* Nick Atty: limit the points at the edge. Note that this also + * nicely kills any plotting for rectangles completely outside the + * window as it makes the tests in the for loops fail + */ + if (x1 < 0) { + x1 = 0; + } + if (x1 > gdImageSX(im)) { + x1 = gdImageSX(im); + } + if(y1 < 0) { + y1 = 0; + } + if (y1 > gdImageSY(im)) { + y1 = gdImageSY(im); + } + + for (y = y1; (y <= y2); y++) { + for (x = x1; (x <= x2); x++) { + gdImageSetPixel (im, x, y, color); + } } - } } void gdImageCopy (gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int srcX, int srcY, int w, int h) { - int c; - int x, y; - int tox, toy; - int i; - int colorMap[gdMaxColors]; - if (dst->trueColor) - { - /* 2.0: much easier when the destination is truecolor. */ + int c; + int x, y; + int tox, toy; + int i; + int colorMap[gdMaxColors]; + if (dst->trueColor) { + /* 2.0: much easier when the destination is truecolor. */ + /* 2.0.10: needs a transparent-index check that is still valid if + * the source is not truecolor. Thanks to Frank Warmerdam. + */ - if (src->trueColor) { - for (y = 0; (y < h); y++) - { - for (x = 0; (x < w); x++) - { - int c = gdImageGetTrueColorPixel (src, srcX + x, - srcY + y); - gdImageSetPixel (dst, - dstX + x, - dstY + y, - c); + if (src->trueColor) { + for (y = 0; (y < h); y++) { + for (x = 0; (x < w); x++) { + int c = gdImageGetTrueColorPixel (src, srcX + x, srcY + y); + gdImageSetPixel (dst, dstX + x, dstY + y, c); } } - - } - else { + } else { /* source is palette based */ - for (y = 0; (y < h); y++) - { - for (x = 0; (x < w); x++) - { - int c = gdImageGetPixel (src, srcX + x, - srcY + y); - if (c != src->transparent) - { - gdImageSetPixel (dst, - dstX + x, - dstY + y, - gdTrueColor(src->red[c], src->green[c], src->blue[c])); + for (y = 0; (y < h); y++) { + for (x = 0; (x < w); x++) { + int c = gdImageGetPixel (src, srcX + x, srcY + y); + if (c != src->transparent) { + gdImageSetPixel (dst, dstX + x, dstY + y, gdTrueColor(src->red[c], src->green[c], src->blue[c])); } + } + } } - } + return; } - return; - } - - /* Destination is palette based */ - if (src->trueColor) { /* But source is truecolor (Ouch!) */ - toy = dstY; - for (y = srcY; (y < (srcY + h)); y++) - { - tox = dstX; - for (x = srcX; (x < (srcX + w)); x++) - { - int nc; - c = gdImageGetPixel (src, x, y); - - /* Get best match possible. */ - nc = gdImageColorResolveAlpha ( - dst, - gdTrueColorGetRed(c), - gdTrueColorGetGreen(c), - gdTrueColorGetBlue(c), - gdTrueColorGetAlpha(c)); - - gdImageSetPixel (dst, tox, toy, nc); - tox++; - } - toy++; - } - return; - } + /* Destination is palette based */ + if (src->trueColor) { /* But source is truecolor (Ouch!) */ + toy = dstY; + for (y = srcY; (y < (srcY + h)); y++) { + tox = dstX; + for (x = srcX; (x < (srcX + w)); x++) { + int nc; + c = gdImageGetPixel (src, x, y); - /* Palette based to palette based */ + /* Get best match possible. */ + nc = gdImageColorResolveAlpha (dst, gdTrueColorGetRed(c), gdTrueColorGetGreen(c), gdTrueColorGetBlue(c), gdTrueColorGetAlpha(c)); - for (i = 0; (i < gdMaxColors); i++) - { - colorMap[i] = (-1); - } - toy = dstY; - for (y = srcY; (y < (srcY + h)); y++) - { - tox = dstX; - for (x = srcX; (x < (srcX + w)); x++) - { - int nc; - c = gdImageGetPixel (src, x, y); - /* Added 7/24/95: support transparent copies */ - if (gdImageGetTransparent (src) == c) - { - tox++; - continue; - } - /* Have we established a mapping for this color? */ - if (colorMap[c] == (-1)) - { - /* If it's the same image, mapping is trivial */ - if (dst == src) - { - nc = c; + gdImageSetPixel (dst, tox, toy, nc); + tox++; + } + toy++; } - else - { - /* Get best match possible. This - function never returns error. */ - nc = gdImageColorResolveAlpha ( - dst, - src->red[c], src->green[c], - src->blue[c], src->alpha[c]); + return; + } + + /* Palette based to palette based */ + for (i = 0; (i < gdMaxColors); i++) { + colorMap[i] = (-1); + } + toy = dstY; + for (y = srcY; (y < (srcY + h)); y++) { + tox = dstX; + for (x = srcX; (x < (srcX + w)); x++) { + int nc; + int mapTo; + c = gdImageGetPixel (src, x, y); + /* Added 7/24/95: support transparent copies */ + if (gdImageGetTransparent (src) == c) { + tox++; + continue; + } + /* Have we established a mapping for this color? */ + if (src->trueColor) { + /* 2.05: remap to the palette available in the destination image. This is slow and + * works badly, but it beats crashing! Thanks to Padhrig McCarthy. + */ + mapTo = gdImageColorResolveAlpha (dst, gdTrueColorGetRed (c), gdTrueColorGetGreen (c), gdTrueColorGetBlue (c), gdTrueColorGetAlpha (c)); + } else if (colorMap[c] == (-1)) { + /* If it's the same image, mapping is trivial */ + if (dst == src) { + nc = c; + } else { + /* Get best match possible. This function never returns error. */ + nc = gdImageColorResolveAlpha (dst, src->red[c], src->green[c], src->blue[c], src->alpha[c]); + } + colorMap[c] = nc; + mapTo = colorMap[c]; + } else { + mapTo = colorMap[c]; + } + gdImageSetPixel (dst, tox, toy, mapTo); + tox++; } - colorMap[c] = nc; - } - gdImageSetPixel (dst, tox, toy, colorMap[c]); - tox++; + toy++; } - toy++; - } } /* This function is a substitute for real alpha channel operations, @@ -1950,12 +2138,12 @@ { dc = gdImageGetPixel (dst, tox, toy); - ncR = (int)( gdImageRed (src, c) * (pct / 100.0f) - + gdImageRed (dst, dc) * ((100 - pct) / 100.0f)); - ncG = (int)( gdImageGreen (src, c) * (pct / 100.0f) - + gdImageGreen (dst, dc) * ((100 - pct) / 100.0f)); - ncB = (int)( gdImageBlue (src, c) * (pct / 100.0f) - + gdImageBlue (dst, dc) * ((100 - pct) / 100.0f)); + ncR = (int)(gdImageRed (src, c) * (pct / 100.0f) + + gdImageRed (dst, dc) * ((100 - pct) / 100.0f)); + ncG = (int)(gdImageGreen (src, c) * (pct / 100.0f) + + gdImageGreen (dst, dc) * ((100 - pct) / 100.0f)); + ncB = (int)(gdImageBlue (src, c) * (pct / 100.0f) + + gdImageBlue (dst, dc) * ((100 - pct) / 100.0f)); /* Find a reasonable color */ nc = gdImageColorResolve (dst, ncR, ncG, ncB); @@ -1972,185 +2160,157 @@ void gdImageCopyMergeGray (gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int srcX, int srcY, int w, int h, int pct) { - - int c, dc; - int x, y; - int tox, toy; - int ncR, ncG, ncB; - float g; - toy = dstY; - for (y = srcY; (y < (srcY + h)); y++) - { - tox = dstX; - for (x = srcX; (x < (srcX + w)); x++) - { - int nc; - c = gdImageGetPixel (src, x, y); - /* Added 7/24/95: support transparent copies */ - if (gdImageGetTransparent (src) == c) - { - tox++; - continue; - } - /* If it's the same image, mapping is trivial */ - if (dst == src) - { - nc = c; - } - else - { - dc = gdImageGetPixel (dst, tox, toy); - g = (0.29900f * gdImageRed(dst, dc)) + (0.58700f * gdImageGreen(dst, dc)) + (0.11400f * gdImageBlue(dst, dc)); - - ncR = (int)( gdImageRed (src, c) * (pct / 100.0f) - + gdImageRed (dst, dc) * g * ((100 - pct) / 100.0f)); - - ncG = (int)( gdImageGreen (src, c) * (pct / 100.0f) - + gdImageGreen (dst, dc) * g * ((100 - pct) / 100.0f)); - - ncB = (int)( gdImageBlue (src, c) * (pct / 100.0f) - + gdImageBlue (dst, dc) * g * ((100 - pct) / 100.0f)); - - - /* First look for an exact match */ - nc = gdImageColorExact (dst, ncR, ncG, ncB); - if (nc == (-1)) - { - /* No, so try to allocate it */ - nc = gdImageColorAllocate (dst, ncR, ncG, ncB); - /* If we're out of colors, go for the - closest color */ - if (nc == (-1)) - { - nc = gdImageColorClosest (dst, ncR, ncG, ncB); - } + int c, dc; + int x, y; + int tox, toy; + int ncR, ncG, ncB; + float g; + toy = dstY; + + for (y = srcY; (y < (srcY + h)); y++) { + tox = dstX; + for (x = srcX; (x < (srcX + w)); x++) { + int nc; + c = gdImageGetPixel (src, x, y); + /* Added 7/24/95: support transparent copies */ + if (gdImageGetTransparent(src) == c) { + tox++; + continue; + } + /* If it's the same image, mapping is trivial */ + if (dst == src) { + nc = c; + } else { + dc = gdImageGetPixel(dst, tox, toy); + g = (0.29900f * gdImageRed(dst, dc)) + (0.58700f * gdImageGreen(dst, dc)) + (0.11400f * gdImageBlue(dst, dc)); + + ncR = (int)(gdImageRed (src, c) * (pct / 100.0f) + gdImageRed(dst, dc) * g * ((100 - pct) / 100.0f)); + ncG = (int)(gdImageGreen (src, c) * (pct / 100.0f) + gdImageGreen(dst, dc) * g * ((100 - pct) / 100.0f)); + ncB = (int)(gdImageBlue (src, c) * (pct / 100.0f) + gdImageBlue(dst, dc) * g * ((100 - pct) / 100.0f)); + + /* First look for an exact match */ + nc = gdImageColorExact(dst, ncR, ncG, ncB); + if (nc == (-1)) { + /* No, so try to allocate it */ + nc = gdImageColorAllocate(dst, ncR, ncG, ncB); + /* If we're out of colors, go for the closest color */ + if (nc == (-1)) { + nc = gdImageColorClosest(dst, ncR, ncG, ncB); + } + } + } + gdImageSetPixel(dst, tox, toy, nc); + tox++; } - } - gdImageSetPixel (dst, tox, toy, nc); - tox++; + toy++; } - toy++; - } } void gdImageCopyResized (gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int srcX, int srcY, int dstW, int dstH, int srcW, int srcH) { - int c; - int x, y; - int tox, toy; - int ydest; - int i; - int colorMap[gdMaxColors]; - /* Stretch vectors */ - int *stx; - int *sty; - /* We only need to use floating point to determine the correct - stretch vector for one line's worth. */ - double accum; - stx = (int *) gdMalloc (sizeof (int) * srcW); - sty = (int *) gdMalloc (sizeof (int) * srcH); - accum = 0; - for (i = 0; (i < srcW); i++) - { - int got; - accum += (double) dstW / (double) srcW; - got = (int) floor (accum); - stx[i] = got; - accum -= got; - } - accum = 0; - for (i = 0; (i < srcH); i++) - { - int got; - accum += (double) dstH / (double) srcH; - got = (int) floor (accum); - sty[i] = got; - accum -= got; - } - for (i = 0; (i < gdMaxColors); i++) - { - colorMap[i] = (-1); - } - toy = dstY; - for (y = srcY; (y < (srcY + srcH)); y++) - { - for (ydest = 0; (ydest < sty[y - srcY]); ydest++) - { - tox = dstX; - for (x = srcX; (x < (srcX + srcW)); x++) - { - int nc = 0; - int mapTo; - if (!stx[x - srcX]) - { - continue; - } - if (dst->trueColor) - { - mapTo = gdImageGetTrueColorPixel (src, x, y); - /* Added 7/24/95: support transparent copies */ - if (gdImageGetTransparent (src) == mapTo) - { - tox++; - continue; - } - } - else - { - c = gdImageGetPixel (src, x, y); - /* Added 7/24/95: support transparent copies */ - if (gdImageGetTransparent (src) == c) - { - tox += stx[x - srcX]; - continue; - } - if (src->trueColor) - { - /* Remap to the palette available in the - destination image. This is slow and - works badly. */ - mapTo = gdImageColorResolveAlpha (dst, - gdTrueColorGetRed (c), - gdTrueColorGetGreen (c), - gdTrueColorGetBlue (c), - gdTrueColorGetAlpha (c)); - } - else - { - /* Have we established a mapping for this color? */ - if (colorMap[c] == (-1)) - { - /* If it's the same image, mapping is trivial */ - if (dst == src) - { - nc = c; - } - else - { - /* Find or create the best match */ - mapTo = gdImageColorResolveAlpha (dst, - gdTrueColorGetRed (c), - gdTrueColorGetGreen (c), - gdTrueColorGetBlue (c), - gdTrueColorGetAlpha (c)); - } - colorMap[c] = nc; + int c; + int x, y; + int tox, toy; + int ydest; + int i; + int colorMap[gdMaxColors]; + /* Stretch vectors */ + int *stx, *sty; + /* We only need to use floating point to determine the correct stretch vector for one line's worth. */ + double accum; + stx = (int *) gdMalloc (sizeof (int) * srcW); + sty = (int *) gdMalloc (sizeof (int) * srcH); + accum = 0; + + for (i = 0; (i < srcW); i++) { + int got; + accum += (double) dstW / (double) srcW; + got = (int) floor (accum); + stx[i] = got; + accum -= got; + } + accum = 0; + for (i = 0; (i < srcH); i++) { + int got; + accum += (double) dstH / (double) srcH; + got = (int) floor (accum); + sty[i] = got; + accum -= got; + } + for (i = 0; (i < gdMaxColors); i++) { + colorMap[i] = (-1); + } + toy = dstY; + for (y = srcY; (y < (srcY + srcH)); y++) { + for (ydest = 0; (ydest < sty[y - srcY]); ydest++) { + tox = dstX; + for (x = srcX; (x < (srcX + srcW)); x++) { + int nc = 0; + int mapTo; + if (!stx[x - srcX]) { + continue; + } + if (dst->trueColor) { + /* 2.0.9: Thorben Kundinger: Maybe the source image is not a truecolor image */ + if (!src->trueColor) { + int tmp = gdImageGetPixel (src, x, y); + mapTo = gdImageGetTrueColorPixel (src, x, y); + if (gdImageGetTransparent (src) == tmp) { + tox++; + continue; + } + } else { + /* TK: old code follows */ + mapTo = gdImageGetTrueColorPixel (src, x, y); + /* Added 7/24/95: support transparent copies */ + if (gdImageGetTransparent (src) == mapTo) { + tox++; + continue; + } + } + } else { + c = gdImageGetPixel (src, x, y); + /* Added 7/24/95: support transparent copies */ + if (gdImageGetTransparent (src) == c) { + tox += stx[x - srcX]; + continue; + } + if (src->trueColor) { + /* Remap to the palette available in the destination image. This is slow and works badly. */ + mapTo = gdImageColorResolveAlpha(dst, gdTrueColorGetRed(c), + gdTrueColorGetGreen(c), + gdTrueColorGetBlue(c), + gdTrueColorGetAlpha (c)); + } else { + /* Have we established a mapping for this color? */ + if (colorMap[c] == (-1)) { + /* If it's the same image, mapping is trivial */ + if (dst == src) { + nc = c; + } else { + /* Find or create the best match */ + /* 2.0.5: can't use gdTrueColorGetRed, etc with palette */ + nc = gdImageColorResolveAlpha(dst, gdImageRed(src, c), + gdImageGreen(src, c), + gdImageBlue(src, c), + gdImageAlpha(src, c)); + } + colorMap[c] = nc; + } + mapTo = colorMap[c]; + } + } + for (i = 0; (i < stx[x - srcX]); i++) { + gdImageSetPixel (dst, tox, toy, mapTo); + tox++; + } } - mapTo = colorMap[c]; - } - } - for (i = 0; (i < stx[x - srcX]); i++) - { - gdImageSetPixel (dst, tox, toy, mapTo); - tox++; + toy++; } - } - toy++; } - } - gdFree (stx); - gdFree (sty); + gdFree (stx); + gdFree (sty); } /* When gd 1.x was first created, floating point was to be avoided. @@ -2158,144 +2318,112 @@ arithmetic. The routine below is shamelessly, gloriously floating point. TBB */ -void -gdImageCopyResampled (gdImagePtr dst, - gdImagePtr src, - int dstX, int dstY, - int srcX, int srcY, - int dstW, int dstH, - int srcW, int srcH) +void gdImageCopyResampled (gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int srcX, int srcY, int dstW, int dstH, int srcW, int srcH) { - int x, y; - if (!dst->trueColor) - { - gdImageCopyResized ( - dst, src, dstX, dstY, srcX, srcY, dstW, dstH, - srcW, srcH); - return; - } - for (y = dstY; (y < dstY + dstH); y++) - { - for (x = dstX; (x < dstX + dstW); x++) - { - float sy1, sy2, sx1, sx2; - float sx, sy; - float spixels = 0.0f; - float red = 0.0f, green = 0.0f, blue = 0.0f, alpha = 0.0f; - float alpha_factor, alpha_sum = 0.0f, contrib_sum = 0.0f; - sy1 = ((float)(y - dstY)) * (float)srcH / - (float)dstH; - sy2 = ((float)(y + 1 - dstY)) * (float) srcH / - (float) dstH; - sy = sy1; - do - { - float yportion; - if (floorf(sy) == floorf(sy1)) - { - yportion = 1.0f - (sy - floorf(sy)); - if (yportion > sy2 - sy1) - { - yportion = sy2 - sy1; - } - sy = floorf(sy); - } - else if (sy == floorf(sy2)) - { - yportion = sy2 - floorf(sy2); - } - else - { - yportion = 1.0f; - } - sx1 = ((float)(x - dstX)) * (float) srcW / - dstW; - sx2 = ((float)(x + 1 - dstX)) * (float) srcW / - dstW; - sx = sx1; - do - { - float xportion; - float pcontribution; - int p; - if (floorf(sx) == floorf(sx1)) - { - xportion = 1.0f - (sx - floorf(sx)); - if (xportion > sx2 - sx1) - { - xportion = sx2 - sx1; + int x, y; + if (!dst->trueColor) { + gdImageCopyResized (dst, src, dstX, dstY, srcX, srcY, dstW, dstH, srcW, srcH); + return; + } + for (y = dstY; (y < dstY + dstH); y++) { + for (x = dstX; (x < dstX + dstW); x++) { + float sy1, sy2, sx1, sx2; + float sx, sy; + float spixels = 0.0f; + float red = 0.0f, green = 0.0f, blue = 0.0f, alpha = 0.0f; + float alpha_factor, alpha_sum = 0.0f, contrib_sum = 0.0f; + sy1 = ((float)(y - dstY)) * (float)srcH / (float)dstH; + sy2 = ((float)(y + 1 - dstY)) * (float) srcH / (float) dstH; + sy = sy1; + do { + float yportion; + if (floor_cast(sy) == floor_cast(sy1)) { + yportion = 1.0f - (sy - floor_cast(sy)); + if (yportion > sy2 - sy1) { + yportion = sy2 - sy1; + } + sy = floor_cast(sy); + } else if (sy == floorf(sy2)) { + yportion = sy2 - floor_cast(sy2); + } else { + yportion = 1.0f; + } + sx1 = ((float)(x - dstX)) * (float) srcW / dstW; + sx2 = ((float)(x + 1 - dstX)) * (float) srcW / dstW; + sx = sx1; + do { + float xportion; + float pcontribution; + int p; + if (floorf(sx) == floor_cast(sx1)) { + xportion = 1.0f - (sx - floor_cast(sx)); + if (xportion > sx2 - sx1) { + xportion = sx2 - sx1; + } + sx = floor_cast(sx); + } else if (sx == floorf(sx2)) { + xportion = sx2 - floor_cast(sx2); + } else { + xportion = 1.0f; + } + pcontribution = xportion * yportion; + p = gdImageGetTrueColorPixel(src, (int) sx + srcX, (int) sy + srcY); + + alpha_factor = ((gdAlphaMax - gdTrueColorGetAlpha(p))) * pcontribution; + red += gdTrueColorGetRed (p) * alpha_factor; + green += gdTrueColorGetGreen (p) * alpha_factor; + blue += gdTrueColorGetBlue (p) * alpha_factor; + alpha += gdTrueColorGetAlpha (p) * pcontribution; + alpha_sum += alpha_factor; + contrib_sum += pcontribution; + spixels += xportion * yportion; + sx += 1.0f; + } + while (sx < sx2); + + sy += 1.0f; } - sx = floorf(sx); - } - else if (sx == floorf(sx2)) - { - xportion = sx2 - floorf(sx2); - } - else - { - xportion = 1.0f; - } - pcontribution = xportion * yportion; - p = gdImageGetTrueColorPixel ( - src, - (int) sx + srcX, - (int) sy + srcY); - alpha_factor = ((gdAlphaMax - gdTrueColorGetAlpha(p))) * pcontribution; - red += gdTrueColorGetRed (p) * alpha_factor; - green += gdTrueColorGetGreen (p) * alpha_factor; - blue += gdTrueColorGetBlue (p) * alpha_factor; - alpha += gdTrueColorGetAlpha (p) * pcontribution; - alpha_sum += alpha_factor; - contrib_sum += pcontribution; - spixels += xportion * yportion; - sx += 1.0f; - } - while (sx < sx2); - sy += 1.0f; - } - while (sy < sy2); - if (spixels != 0.0f) - { - red /= spixels; - green /= spixels; - blue /= spixels; - alpha /= spixels; - } - if ( alpha_sum != 0.0f) - { - if( contrib_sum != 0.0f ) alpha_sum /= contrib_sum; - red /= alpha_sum; - green /= alpha_sum; - blue /= alpha_sum; - } - /* Clamping to allow for rounding errors above */ - if (red > 255.0f) - { - red = 255.0f; - } - if (green > 255.0f) - { - green = 255.0f; - } - if (blue > 255.0f) - { - blue = 255.0f; - } - if (alpha > gdAlphaMax) - { - alpha = gdAlphaMax; - } - gdImageSetPixel (dst, - x, y, - gdTrueColorAlpha ((int) red, - (int) green, - (int) blue, - (int) alpha)); + + while (sy < sy2); + + if (spixels != 0.0f) { + red /= spixels; + green /= spixels; + blue /= spixels; + alpha /= spixels; + } + if ( alpha_sum != 0.0f) { + if( contrib_sum != 0.0f) { + alpha_sum /= contrib_sum; + } + red /= alpha_sum; + green /= alpha_sum; + blue /= alpha_sum; + } + /* Clamping to allow for rounding errors above */ + if (red > 255.0f) { + red = 255.0f; + } + if (green > 255.0f) { + green = 255.0f; + } + if (blue > 255.0f) { + blue = 255.0f; + } + if (alpha > gdAlphaMax) { + alpha = gdAlphaMax; + } + gdImageSetPixel(dst, x, y, gdTrueColorAlpha ((int) red, (int) green, (int) blue, (int) alpha)); + } } - } } +/* + * Rotate function Added on 2003/12 + * by Pierre-Alain Joye (pajoye@pearfr.org) + **/ +/* Begin rotate function */ #ifdef ROTATE_PI #undef ROTATE_PI #endif /* ROTATE_PI */ @@ -2307,7 +2435,7 @@ int i, r, g, b, a; FuncPtr f; - int pxlOldLeft, pxlLeft, pxlSrc; + int pxlOldLeft, pxlLeft=0, pxlSrc; if (src->trueColor) { f = gdImageGetTrueColorPixel; @@ -2393,7 +2521,7 @@ typedef int (*FuncPtr)(gdImagePtr, int, int); int i, iYPos=0, r, g, b, a; FuncPtr f; - int pxlOldLeft, pxlLeft, pxlSrc; + int pxlOldLeft, pxlLeft=0, pxlSrc; if (src->trueColor) { f = gdImageGetTrueColorPixel; @@ -2477,10 +2605,10 @@ FuncPtr f; if (src->trueColor) { - dst = gdImageCreateTrueColor ( src->sx,src->sy); + dst = gdImageCreateTrueColor(src->sy, src->sx); f = gdImageGetTrueColorPixel; } else { - dst = gdImageCreate (src->sx, src->sy); + dst = gdImageCreate (src->sy, src->sx); f = gdImageGetPixel; } @@ -2508,10 +2636,10 @@ FuncPtr f; if (src->trueColor) { - dst = gdImageCreateTrueColor(src->sy, src->sx); + dst = gdImageCreateTrueColor ( src->sx,src->sy); f = gdImageGetTrueColorPixel; } else { - dst = gdImageCreate (src->sy, src->sx); + dst = gdImageCreate (src->sx, src->sy); f = gdImageGetPixel; } @@ -2727,7 +2855,9 @@ return rotatedImg; } +/* End Rotate function */ +#if MBO_0 gdImagePtr gdImageCreateFromXbm (FILE * fd) { @@ -2801,7 +2931,7 @@ for (i = 0; (i < bytes); i++) { char h[3]; - int b; + unsigned int b; /* Skip spaces, commas, CRs, 0x */ while (1) { @@ -2847,32 +2977,39 @@ } } /* Shouldn't happen */ - fprintf (stderr, "Error: bug in gdImageCreateFromXbm!\n"); + php_gd_error("Error: bug in gdImageCreateFromXbm\n"); return 0; fail: gdImageDestroy (im); return 0; } +#endif /* MBO_0 */ void gdImagePolygon (gdImagePtr im, gdPointPtr p, int n, int c) { - int i; - int lx, ly; - if (!n) - { - return; - } - lx = p->x; - ly = p->y; - gdImageLine (im, lx, ly, p[n - 1].x, p[n - 1].y, c); - for (i = 1; (i < n); i++) - { - p++; - gdImageLine (im, lx, ly, p->x, p->y, c); - lx = p->x; - ly = p->y; - } + int i; + int lx, ly; + typedef void (*image_line)(gdImagePtr im, int x1, int y1, int x2, int y2, int color); + image_line draw_line; + + if (!n) { + return; + } + if ( im->antialias) { + draw_line = gdImageAALine; + } else { + draw_line = gdImageLine; + } + lx = p->x; + ly = p->y; + draw_line(im, lx, ly, p[n - 1].x, p[n - 1].y, c); + for (i = 1; (i < n); i++) { + p++; + draw_line(im, lx, ly, p->x, p->y, c); + lx = p->x; + ly = p->y; + } } int gdCompareInt (const void *a, const void *b); @@ -3161,6 +3298,14 @@ gdImageAlphaBlending (gdImagePtr im, int alphaBlendingArg) { im->alphaBlendingFlag = alphaBlendingArg; +} + +void +gdImageAntialias (gdImagePtr im, int antialias) +{ + if (im->trueColor){ + im->antialias = antialias; + } } void Index: php4/ext/gd/libgd/gd.h diff -u php4/ext/gd/libgd/gd.h:1.7.2.3 php4/ext/gd/libgd/gd.h:1.7.2.4 --- php4/ext/gd/libgd/gd.h:1.7.2.3 Sat Feb 8 03:54:11 2003 +++ php4/ext/gd/libgd/gd.h Wed Mar 5 11:04:20 2003 @@ -30,6 +30,11 @@ #include <stdio.h> #include "gd_io.h" +void php_gd_error_ex(int type, const char *format, ...); + +void php_gd_error(const char *format, ...); + + /* The maximum number of palette entries in palette-based images. In the wonderful new world of gd 2.0, you can of course have many more colors when using truecolor mode. */ @@ -136,6 +141,8 @@ To do that, build your image as a truecolor image, then quantize down to 8 bits. */ int alphaBlendingFlag; + /* Should antialias functions be used */ + int antialias; /* Should the alpha channel of the image be saved? This affects PNG at the moment; other future formats may also have that capability. JPEG doesn't. */ @@ -239,6 +246,7 @@ int gdImageGetPixel(gdImagePtr im, int x, int y); void gdImageLine(gdImagePtr im, int x1, int y1, int x2, int y2, int color); +void gdImageAALine(gdImagePtr im, int x1, int y1, int x2, int y2, int color); /* For backwards compatibility only. Use gdImageSetStyle() for much more flexible line drawing. */ @@ -248,7 +256,6 @@ void gdImageRectangle(gdImagePtr im, int x1, int y1, int x2, int y2, int color); /* Solid bar. Upper left corner first, lower right corner second. */ void gdImageFilledRectangle(gdImagePtr im, int x1, int y1, int x2, int y2, int color); -int gdImageBoundsSafe(gdImagePtr im, int x, int y); void gdImageChar(gdImagePtr im, gdFontPtr f, int x, int y, int c, int color); void gdImageCharUp(gdImagePtr im, gdFontPtr f, int x, int y, int c, int color); void gdImageString(gdImagePtr im, gdFontPtr f, int x, int y, unsigned char *s, int color); @@ -300,6 +307,8 @@ beats the exact same color with radically different transparency */ int gdImageColorClosestAlpha(gdImagePtr im, int r, int g, int b, int a); +/* An alternate method */ +int gdImageColorClosestHWB(gdImagePtr im, int r, int g, int b); /* Returns exact, 100% opaque matches only */ int gdImageColorExact(gdImagePtr im, int r, int g, int b); /* Returns an exact match only, including alpha */ @@ -472,6 +481,7 @@ /* On or off (1 or 0) for all three of these. */ void gdImageInterlace(gdImagePtr im, int interlaceArg); void gdImageAlphaBlending(gdImagePtr im, int alphaBlendingArg); +void gdImageAntialias(gdImagePtr im, int antialias); void gdImageSaveAlpha(gdImagePtr im, int saveAlphaArg); /* Macros to access information about images. */ @@ -538,5 +548,7 @@ #ifdef __cplusplus } #endif + +#define gdImageBoundsSafe(im, x, y) (!(y < 0 || y >= (im)->sy || x < 0 || x >= (im)->sx)) #endif /* GD_H */ Index: php4/ext/gd/libgd/gd_arc_f_buggy.c diff -u php4/ext/gd/libgd/gd_arc_f_buggy.c:1.1 php4/ext/gd/libgd/gd_arc_f_buggy.c:1.1.4.1 --- php4/ext/gd/libgd/gd_arc_f_buggy.c:1.1 Fri Apr 12 22:03:08 2002 +++ php4/ext/gd/libgd/gd_arc_f_buggy.c Wed Mar 5 11:04:20 2003 @@ -726,12 +726,12 @@ out = fopen ("test/arctest.png", "wb"); if (!out) { - fprintf (stderr, "Can't create test/arctest.png\n"); + php_gd_error("Can't create test/arctest.png\n"); exit (1); } gdImagePng (im, out); fclose (out); - fprintf (stderr, "Test image written to test/arctest.png\n"); + php_gd_error("Test image written to test/arctest.png\n"); /* Destroy it */ gdImageDestroy (im); Index: php4/ext/gd/libgd/gd_gd2.c diff -u php4/ext/gd/libgd/gd_gd2.c:1.4.2.1 php4/ext/gd/libgd/gd_gd2.c:1.4.2.2 --- php4/ext/gd/libgd/gd_gd2.c:1.4.2.1 Wed Dec 4 12:28:55 2002 +++ php4/ext/gd/libgd/gd_gd2.c Wed Mar 5 11:04:20 2003 @@ -23,273 +23,248 @@ #define TRUE 1 #define FALSE 0 +/* 2.11: not part of the API, as the save routine can figure it out + * from im->trueColor, and the load routine doesn't need to tell + * the end user the saved format. NOTE: adding 2 is assumed + * to result in the correct format value for truecolor! +*/ +#define GD2_FMT_TRUECOLOR_RAW 3 +#define GD2_FMT_TRUECOLOR_COMPRESSED 4 + +#define gd2_compressed(fmt) (((fmt) == GD2_FMT_COMPRESSED) || ((fmt) == GD2_FMT_TRUECOLOR_COMPRESSED)) +#define gd2_truecolor(fmt) (((fmt) == GD2_FMT_TRUECOLOR_RAW) || ((fmt) == GD2_FMT_TRUECOLOR_COMPRESSED)) + /* Use this for commenting out debug-print statements. */ /* Just use the first '#define' to allow all the prints... */ -/*#define GD2_DBG(s) (s) */ +/* #define GD2_DBG(s) (s) */ #define GD2_DBG(s) typedef struct - { - int offset; - int size; - } +{ + int offset; + int size; +} t_chunk_info; -extern int _gdGetColors (gdIOCtx * in, gdImagePtr im, int gd2xFlag); -extern void _gdPutColors (gdImagePtr im, gdIOCtx * out); +extern int _gdGetColors(gdIOCtx * in, gdImagePtr im, int gd2xFlag); +extern void _gdPutColors(gdImagePtr im, gdIOCtx * out); /* */ /* Read the extra info in the gd2 header. */ /* */ -static -int -_gd2GetHeader (gdIOCtxPtr in, int *sx, int *sy, - int *cs, int *vers, int *fmt, int *ncx, int *ncy, t_chunk_info ** chunkIdx) -{ - int i; - int ch; - char id[5]; - t_chunk_info *cidx; - int sidx; - int nc; - - GD2_DBG (printf ("Reading gd2 header info\n")); - - for (i = 0; i < 4; i++) - { - ch = gdGetC (in); - if (ch == EOF) - { - goto fail1; - }; - id[i] = ch; - }; - id[4] = 0; - - GD2_DBG (printf ("Got file code: %s\n", id)); - - /* Equiv. of 'magick'. */ - if (strcmp (id, GD2_ID) != 0) - { - GD2_DBG (printf ("Not a valid gd2 file\n")); - goto fail1; - }; - - /* Version */ - if (gdGetWord (vers, in) != 1) - { - goto fail1; - }; - GD2_DBG (printf ("Version: %d\n", *vers)); - - if ((*vers != 1) && (*vers != 2)) - { - GD2_DBG (printf ("Bad version: %d\n", *vers)); - goto fail1; - }; - - /* Image Size */ - if (!gdGetWord (sx, in)) - { - GD2_DBG (printf ("Could not get x-size\n")); - goto fail1; - } - if (!gdGetWord (sy, in)) - { - GD2_DBG (printf ("Could not get y-size\n")); - goto fail1; - } - GD2_DBG (printf ("Image is %dx%d\n", *sx, *sy)); - - /* Chunk Size (pixels, not bytes!) */ - if (gdGetWord (cs, in) != 1) - { - goto fail1; - }; - GD2_DBG (printf ("ChunkSize: %d\n", *cs)); - - if ((*cs < GD2_CHUNKSIZE_MIN) || (*cs > GD2_CHUNKSIZE_MAX)) - { - GD2_DBG (printf ("Bad chunk size: %d\n", *cs)); - goto fail1; - }; - - /* Data Format */ - if (gdGetWord (fmt, in) != 1) - { - goto fail1; - }; - GD2_DBG (printf ("Format: %d\n", *fmt)); - - if ((*fmt != GD2_FMT_RAW) && (*fmt != GD2_FMT_COMPRESSED)) - { - GD2_DBG (printf ("Bad data format: %d\n", *fmt)); - goto fail1; - }; - - - /* # of chunks wide */ - if (gdGetWord (ncx, in) != 1) - { - goto fail1; - }; - GD2_DBG (printf ("%d Chunks Wide\n", *ncx)); - - /* # of chunks high */ - if (gdGetWord (ncy, in) != 1) - { - goto fail1; - }; - GD2_DBG (printf ("%d Chunks vertically\n", *ncy)); - - if ((*fmt) == GD2_FMT_COMPRESSED) - { - nc = (*ncx) * (*ncy); - GD2_DBG (printf ("Reading %d chunk index entries\n", nc)); - sidx = sizeof (t_chunk_info) * nc; - cidx = gdCalloc (sidx, 1); - for (i = 0; i < nc; i++) - { - if (gdGetInt (&cidx[i].offset, in) != 1) - { - goto fail1; - }; - if (gdGetInt (&cidx[i].size, in) != 1) - { - goto fail1; - }; - }; - *chunkIdx = cidx; - }; +static int _gd2GetHeader(gdIOCtxPtr in, int *sx, int *sy, int *cs, int *vers, int *fmt, int *ncx, int *ncy, t_chunk_info ** chunkIdx) +{ + int i; + int ch; + char id[5]; + t_chunk_info *cidx; + int sidx; + int nc; + + GD2_DBG(php_gd_error("Reading gd2 header info\n")); + + for (i = 0; i < 4; i++) { + ch = gdGetC(in); + if (ch == EOF) { + goto fail1; + } + id[i] = ch; + } + id[4] = 0; - GD2_DBG (printf ("gd2 header complete\n")); + GD2_DBG(php_gd_error("Got file code: %s\n", id)); - return 1; + /* Equiv. of 'magick'. */ + if (strcmp(id, GD2_ID) != 0) { + GD2_DBG(php_gd_error("Not a valid gd2 file\n")); + goto fail1; + } + + /* Version */ + if (gdGetWord(vers, in) != 1) { + goto fail1; + } + GD2_DBG(php_gd_error("Version: %d\n", *vers)); + + if ((*vers != 1) && (*vers != 2)) { + GD2_DBG(php_gd_error("Bad version: %d\n", *vers)); + goto fail1; + } + + /* Image Size */ + if (!gdGetWord(sx, in)) { + GD2_DBG(php_gd_error("Could not get x-size\n")); + goto fail1; + } + if (!gdGetWord(sy, in)) { + GD2_DBG(php_gd_error("Could not get y-size\n")); + goto fail1; + } + GD2_DBG(php_gd_error("Image is %dx%d\n", *sx, *sy)); + + /* Chunk Size (pixels, not bytes!) */ + if (gdGetWord(cs, in) != 1) { + goto fail1; + } + GD2_DBG(php_gd_error("ChunkSize: %d\n", *cs)); + + if ((*cs < GD2_CHUNKSIZE_MIN) || (*cs > GD2_CHUNKSIZE_MAX)) { + GD2_DBG(php_gd_error("Bad chunk size: %d\n", *cs)); + goto fail1; + } + + /* Data Format */ + if (gdGetWord(fmt, in) != 1) { + goto fail1; + } + GD2_DBG(php_gd_error("Format: %d\n", *fmt)); + + if ((*fmt != GD2_FMT_RAW) && (*fmt != GD2_FMT_COMPRESSED) && (*fmt != GD2_FMT_TRUECOLOR_RAW) && (*fmt != GD2_FMT_TRUECOLOR_COMPRESSED)) { + GD2_DBG(php_gd_error("Bad data format: %d\n", *fmt)); + goto fail1; + } + + /* # of chunks wide */ + if (gdGetWord(ncx, in) != 1) { + goto fail1; + } + GD2_DBG(php_gd_error("%d Chunks Wide\n", *ncx)); + + /* # of chunks high */ + if (gdGetWord(ncy, in) != 1) { + goto fail1; + } + GD2_DBG(php_gd_error("%d Chunks vertically\n", *ncy)); + + if (gd2_compressed(*fmt)) { + nc = (*ncx) * (*ncy); + GD2_DBG(php_gd_error("Reading %d chunk index entries\n", nc)); + sidx = sizeof(t_chunk_info) * nc; + cidx = gdCalloc(sidx, 1); + for (i = 0; i < nc; i++) { + if (gdGetInt(&cidx[i].offset, in) != 1) { + goto fail1; + } + if (gdGetInt(&cidx[i].size, in) != 1) { + goto fail1; + } + } + *chunkIdx = cidx; + } + + GD2_DBG(php_gd_error("gd2 header complete\n")); + + return 1; fail1: - return 0; + return 0; } -static - gdImagePtr -_gd2CreateFromFile (gdIOCtxPtr in, int *sx, int *sy, - int *cs, int *vers, int *fmt, - int *ncx, int *ncy, t_chunk_info ** cidx) -{ - gdImagePtr im; - - if (_gd2GetHeader (in, sx, sy, cs, vers, fmt, ncx, ncy, cidx) != 1) - { - GD2_DBG (printf ("Bad GD2 header\n")); - goto fail1; - } - - im = gdImageCreateTrueColor(*sx, *sy); - if (im == NULL) - { - GD2_DBG (printf ("Could not create gdImage\n")); - goto fail1; - }; - - if (!_gdGetColors (in, im, (*vers) == 2)) - { - GD2_DBG (printf ("Could not read color palette\n")); - goto fail2; - } - GD2_DBG (printf ("Image palette completed: %d colours\n", im->colorsTotal)); +static gdImagePtr _gd2CreateFromFile (gdIOCtxPtr in, int *sx, int *sy, int *cs, int *vers, int *fmt, int *ncx, int *ncy, t_chunk_info ** cidx) +{ + gdImagePtr im; + + if (_gd2GetHeader (in, sx, sy, cs, vers, fmt, ncx, ncy, cidx) != 1) { + GD2_DBG(php_gd_error("Bad GD2 header\n")); + goto fail1; + } + + if (gd2_truecolor(*fmt)) { + im = gdImageCreateTrueColor(*sx, *sy); + } else { + im = gdImageCreate(*sx, *sy); + } + if (im == NULL) { + GD2_DBG(php_gd_error("Could not create gdImage\n")); + goto fail1; + } - return im; + if (!_gdGetColors(in, im, (*vers) == 2)) { + GD2_DBG(php_gd_error("Could not read color palette\n")); + goto fail2; + } + GD2_DBG(php_gd_error("Image palette completed: %d colours\n", im->colorsTotal)); + + return im; fail2: - gdImageDestroy (im); - return 0; + gdImageDestroy(im); + return 0; fail1: - return 0; + return 0; +} + +static int _gd2ReadChunk (int offset, char *compBuf, int compSize, char *chunkBuf, uLongf * chunkLen, gdIOCtx * in) +{ + int zerr; + if (gdTell(in) != offset) { + GD2_DBG(php_gd_error("Positioning in file to %d\n", offset)); + gdSeek(in, offset); + } else { + GD2_DBG(php_gd_error("Already Positioned in file to %d\n", offset)); + } + + /* Read and uncompress an entire chunk. */ + GD2_DBG(php_gd_error("Reading file\n")); + if (gdGetBuf(compBuf, compSize, in) != compSize) { + return FALSE; + } + GD2_DBG(php_gd_error("Got %d bytes. Uncompressing into buffer of %d bytes\n", compSize, (int)*chunkLen)); + zerr = uncompress((unsigned char *) chunkBuf, chunkLen, (unsigned char *) compBuf, compSize); + if (zerr != Z_OK) { + GD2_DBG(php_gd_error("Error %d from uncompress\n", zerr)); + return FALSE; + } + GD2_DBG(php_gd_error("Got chunk\n")); + + return TRUE; } -static -int -_gd2ReadChunk (int offset, char *compBuf, int compSize, char *chunkBuf, uLongf * chunkLen, gdIOCtx * in) -{ - int zerr; - - if (gdTell (in) != offset) - { - GD2_DBG (printf ("Positioning in file to %d\n", offset)); - gdSeek (in, offset); - } - else - { - GD2_DBG (printf ("Already Positioned in file to %d\n", offset)); - }; - - /* Read and uncompress an entire chunk. */ - GD2_DBG (printf ("Reading file\n")); - if (gdGetBuf (compBuf, compSize, in) != compSize) - { - return FALSE; - }; - GD2_DBG (printf ("Got %d bytes. Uncompressing into buffer of %d bytes\n", compSize, *chunkLen)); - zerr = uncompress ((unsigned char *) chunkBuf, chunkLen, - (unsigned char *) compBuf, compSize); - if (zerr != Z_OK) - { - GD2_DBG (printf ("Error %d from uncompress\n", zerr)); - return FALSE; - }; - GD2_DBG (printf ("Got chunk\n")); - return TRUE; -} - -gdImagePtr -gdImageCreateFromGd2 (FILE * inFile) -{ - gdIOCtx *in = gdNewFileCtx (inFile); - gdImagePtr im; - - im = gdImageCreateFromGd2Ctx (in); - - in->gd_free (in); - - return im; -} - -gdImagePtr -gdImageCreateFromGd2Ctx (gdIOCtxPtr in) -{ - int sx, sy; - int i; - int ncx, ncy, nc, cs, cx, cy; - int x, y, ylo, yhi, xlo, xhi; - int vers, fmt; - t_chunk_info *chunkIdx = NULL; /* So we can gdFree it with impunity. */ - unsigned char *chunkBuf = NULL; /* So we can gdFree it with impunity. */ - int chunkNum = 0; - int chunkMax = 0; - uLongf chunkLen; - int chunkPos = 0; - int compMax = 0; - int bytesPerPixel; - char *compBuf = NULL; /* So we can gdFree it with impunity. */ - - gdImagePtr im; - - /* Get the header */ - im = _gd2CreateFromFile (in, &sx, &sy, &cs, &vers, &fmt, &ncx, &ncy, &chunkIdx); - - if (im == NULL) - { - return 0; - }; - bytesPerPixel = im->trueColor ? 4 : 1; - nc = ncx * ncy; +gdImagePtr gdImageCreateFromGd2 (FILE * inFile) +{ + gdIOCtx *in = gdNewFileCtx(inFile); + gdImagePtr im; + + im = gdImageCreateFromGd2Ctx(in); + + in->gd_free(in); + + return im; +} - if (fmt == GD2_FMT_COMPRESSED) { +gdImagePtr gdImageCreateFromGd2Ctx (gdIOCtxPtr in) +{ + int sx, sy; + int i; + int ncx, ncy, nc, cs, cx, cy; + int x, y, ylo, yhi, xlo, xhi; + int vers, fmt; + t_chunk_info *chunkIdx = NULL; /* So we can gdFree it with impunity. */ + unsigned char *chunkBuf = NULL; /* So we can gdFree it with impunity. */ + int chunkNum = 0; + int chunkMax = 0; + uLongf chunkLen; + int chunkPos = 0; + int compMax = 0; + int bytesPerPixel; + char *compBuf = NULL; /* So we can gdFree it with impunity. */ + + gdImagePtr im; + + /* Get the header */ + if (!(im = _gd2CreateFromFile(in, &sx, &sy, &cs, &vers, &fmt, &ncx, &ncy, &chunkIdx))) { + return 0; + } + + bytesPerPixel = im->trueColor ? 4 : 1; + nc = ncx * ncy; + + if (gd2_compressed(fmt)) { /* Find the maximum compressed chunk size. */ compMax = 0; - for (i = 0; i < nc; i++) { + for (i = 0; (i < nc); i++) { if (chunkIdx[i].size > compMax) { compMax = chunkIdx[i].size; } @@ -298,47 +273,50 @@ /* Allocate buffers */ chunkMax = cs * bytesPerPixel * cs; - chunkBuf = gdCalloc (chunkMax, 1); - compBuf = gdCalloc (compMax, 1); - GD2_DBG(printf("Largest compressed chunk is %d bytes\n", compMax)); + chunkBuf = gdCalloc(chunkMax, 1); + compBuf = gdCalloc(compMax, 1); + + GD2_DBG(php_gd_error("Largest compressed chunk is %d bytes\n", compMax)); } /* Read the data... */ - for (cy = 0; cy < ncy; cy++) { - for (cx = 0; cx < ncx; cx++) { + for (cy = 0; (cy < ncy); cy++) { + for (cx = 0; (cx < ncx); cx++) { ylo = cy * cs; yhi = ylo + cs; if (yhi > im->sy) { yhi = im->sy; } - GD2_DBG(printf("Processing Chunk %d (%d, %d), y from %d to %d\n", chunkNum, cx, cy, ylo, yhi)); - if (fmt == GD2_FMT_COMPRESSED) { + GD2_DBG(php_gd_error("Processing Chunk %d (%d, %d), y from %d to %d\n", chunkNum, cx, cy, ylo, yhi)); + + if (gd2_compressed(fmt)) { chunkLen = chunkMax; - if (!_gd2ReadChunk (chunkIdx[chunkNum].offset, compBuf, chunkIdx[chunkNum].size, chunkBuf, &chunkLen, in)) { - GD2_DBG(printf("Error reading comproessed chunk\n")); + if (!_gd2ReadChunk(chunkIdx[chunkNum].offset, compBuf, chunkIdx[chunkNum].size, chunkBuf, &chunkLen, in)) { + GD2_DBG(php_gd_error("Error reading comproessed chunk\n")); goto fail2; } + chunkPos = 0; } - for (y = ylo; y < yhi; y++) { + for (y = ylo; (y < yhi); y++) { xlo = cx * cs; xhi = xlo + cs; if (xhi > im->sx) { xhi = im->sx; } - if (fmt == GD2_FMT_RAW) { + if (!gd2_compressed(fmt)) { for (x = xlo; x < xhi; x++) { if (im->trueColor) { - if (!gdGetInt (&im->tpixels[y][x], in)) { + if (!gdGetInt(&im->tpixels[y][x], in)) { im->tpixels[y][x] = 0; } } else { int ch; - if (!gdGetByte (&ch, in)) { + if (!gdGetByte(&ch, in)) { ch = 0; } im->pixels[y][x] = ch; @@ -347,6 +325,7 @@ } else { for (x = xlo; x < xhi; x++) { if (im->trueColor) { + /* 2.0.1: work around a gcc bug by being verbose. TBB */ int a = chunkBuf[chunkPos++] << 24; int r = chunkBuf[chunkPos++] << 16; int g = chunkBuf[chunkPos++] << 8; @@ -362,517 +341,449 @@ } } - GD2_DBG(printf("Freeing memory\n")); + GD2_DBG(php_gd_error("Freeing memory\n")); - gdFree (chunkBuf); - gdFree (compBuf); - gdFree (chunkIdx); + if (chunkBuf) { + gdFree(chunkBuf); + } + if (compBuf) { + gdFree(compBuf); + } + if (chunkIdx) { + gdFree(chunkIdx); + } - GD2_DBG(printf("Done\n")); + GD2_DBG(php_gd_error("Done\n")); return im; fail2: - gdImageDestroy (im); - gdFree (chunkBuf); - gdFree (compBuf); - gdFree (chunkIdx); + gdImageDestroy(im); + if (chunkBuf) { + gdFree(chunkBuf); + } + if (compBuf) { + gdFree(compBuf); + } + if (chunkIdx) { + gdFree(chunkIdx); + } + return 0; } -gdImagePtr -gdImageCreateFromGd2Part (FILE * inFile, int srcx, int srcy, int w, int h) +gdImagePtr gdImageCreateFromGd2Part (FILE * inFile, int srcx, int srcy, int w, int h) +{ + gdImagePtr im; + gdIOCtx *in = gdNewFileCtx(inFile); + + im = gdImageCreateFromGd2PartCtx(in, srcx, srcy, w, h); + + in->gd_free(in); + + return im; +} + +gdImagePtr gdImageCreateFromGd2PartCtx (gdIOCtx * in, int srcx, int srcy, int w, int h) { - gdImagePtr im; - gdIOCtx *in = gdNewFileCtx (inFile); + int scx, scy, ecx, ecy, fsx, fsy; + int nc, ncx, ncy, cs, cx, cy; + int x, y, ylo, yhi, xlo, xhi; + int dstart, dpos; + int i; + int ch, vers, fmt; + t_chunk_info *chunkIdx = NULL; + char *chunkBuf = NULL; + int chunkNum; + int chunkMax = 0; + uLongf chunkLen; + int chunkPos = 0; + int compMax; + char *compBuf = NULL; + + gdImagePtr im; + + /* The next few lines are basically copied from gd2CreateFromFile + * we change the file size, so don't want to use the code directly. + * but we do need to know the file size. + */ + if (_gd2GetHeader(in, &fsx, &fsy, &cs, &vers, &fmt, &ncx, &ncy, &chunkIdx) != 1) { + goto fail1; + } - im = gdImageCreateFromGd2PartCtx (in, srcx, srcy, w, h); + GD2_DBG(php_gd_error("File size is %dx%d\n", fsx, fsy)); + + /* This is the difference - make a file based on size of chunks. */ + if (gd2_truecolor(fmt)) { + im = gdImageCreateTrueColor(w, h); + } else { + im = gdImageCreate(w, h); + } + if (im == NULL) { + goto fail1; + } + + if (!_gdGetColors(in, im, vers == 2)) { + goto fail2; + } + GD2_DBG(php_gd_error("Image palette completed: %d colours\n", im->colorsTotal)); + + /* Process the header info */ + nc = ncx * ncy; + + if (gd2_compressed(fmt)) { + /* Find the maximum compressed chunk size. */ + compMax = 0; + for (i = 0; (i < nc); i++) { + if (chunkIdx[i].size > compMax) { + compMax = chunkIdx[i].size; + } + } + compMax++; - in->gd_free (in); - - return im; -} - -gdImagePtr -gdImageCreateFromGd2PartCtx (gdIOCtx * in, int srcx, int srcy, int w, int h) -{ - int scx, scy, ecx, ecy, fsx, fsy; - int nc, ncx, ncy, cs, cx, cy; - int x, y, ylo, yhi, xlo, xhi; - int dstart, dpos; - int i; - int ch, vers, fmt; - t_chunk_info *chunkIdx = NULL; - char *chunkBuf = NULL; - int chunkNum; - int chunkMax = 0; - uLongf chunkLen; - int chunkPos = 0; - int compMax; - char *compBuf = NULL; - - gdImagePtr im; - - /* */ - /* The next few lines are basically copied from gd2CreateFromFile */ - /* - we change the file size, so don't want to use the code directly. */ - /* but we do need to know the file size. */ - /* */ - if (_gd2GetHeader (in, &fsx, &fsy, &cs, &vers, &fmt, &ncx, &ncy, &chunkIdx) != 1) - { - goto fail1; - } - - GD2_DBG (printf ("File size is %dx%d\n", fsx, fsy)); - - /* This is the difference - make a file based on size of chunks. */ - im = gdImageCreate (w, h); - if (im == NULL) - { - goto fail1; - }; - - if (!_gdGetColors (in, im, vers == 2)) - { - goto fail2; - } - GD2_DBG (printf ("Image palette completed: %d colours\n", im->colorsTotal)); - - /* Process the header info */ - nc = ncx * ncy; - - if (fmt == GD2_FMT_COMPRESSED) - { - /* Find the maximum compressed chunk size. */ - compMax = 0; - for (i = 0; (i < nc); i++) - { - if (chunkIdx[i].size > compMax) - { - compMax = chunkIdx[i].size; - }; - }; - compMax++; - - if (im->trueColor) - { - chunkMax = cs * cs * 4; - } - else - { - chunkMax = cs * cs; - } - chunkBuf = gdCalloc (chunkMax, 1); - compBuf = gdCalloc (compMax, 1); - }; - -/* Don't bother with this... */ -/* if ( (ncx != sx / cs) || (ncy != sy / cs)) { */ -/* goto fail2; */ -/* }; */ - - - /* Work out start/end chunks */ - scx = srcx / cs; - scy = srcy / cs; - if (scx < 0) - { - scx = 0; - }; - if (scy < 0) - { - scy = 0; - }; - - ecx = (srcx + w) / cs; - ecy = (srcy + h) / cs; - if (ecx >= ncx) - { - ecx = ncx - 1; - }; - if (ecy >= ncy) - { - ecy = ncy - 1; - }; - - /* Remember file position of image data. */ - dstart = gdTell (in); - GD2_DBG (printf ("Data starts at %d\n", dstart)); - - /* Loop through the chunks. */ - for (cy = scy; (cy <= ecy); cy++) - { - - ylo = cy * cs; - yhi = ylo + cs; - if (yhi > fsy) - { - yhi = fsy; - }; - - for (cx = scx; (cx <= ecx); cx++) - { - - xlo = cx * cs; - xhi = xlo + cs; - if (xhi > fsx) - { - xhi = fsx; - }; - - GD2_DBG (printf ("Processing Chunk (%d, %d), from %d to %d\n", cx, cy, ylo, yhi)); - - if (fmt == GD2_FMT_RAW) - { - GD2_DBG (printf ("Using raw format data\n")); - if (im->trueColor) - { - dpos = (cy * (cs * fsx) + cx * cs * (yhi - ylo) * 4) + dstart; + if (im->trueColor) { + chunkMax = cs * cs * 4; + } else { + chunkMax = cs * cs; } - else - { - dpos = cy * (cs * fsx) + cx * cs * (yhi - ylo) + dstart; + chunkBuf = gdCalloc(chunkMax, 1); + compBuf = gdCalloc(compMax, 1); + } + + /* Work out start/end chunks */ + scx = srcx / cs; + scy = srcy / cs; + if (scx < 0) { + scx = 0; + } + if (scy < 0) { + scy = 0; + } + + ecx = (srcx + w) / cs; + ecy = (srcy + h) / cs; + if (ecx >= ncx) { + ecx = ncx - 1; + } + if (ecy >= ncy) { + ecy = ncy - 1; + } + + /* Remember file position of image data. */ + dstart = gdTell(in); + GD2_DBG(php_gd_error("Data starts at %d\n", dstart)); + + /* Loop through the chunks. */ + for (cy = scy; (cy <= ecy); cy++) { + ylo = cy * cs; + yhi = ylo + cs; + if (yhi > fsy) { + yhi = fsy; } - if (gdSeek (in, dpos) != 0) - { - printf ("Error from seek: %d\n", errno); - goto fail2; - }; - GD2_DBG (printf ("Reading (%d, %d) from position %d\n", cx, cy, dpos - dstart)); - } - else - { - chunkNum = cx + cy * ncx; - - chunkLen = chunkMax; - if (!_gd2ReadChunk (chunkIdx[chunkNum].offset, - compBuf, - chunkIdx[chunkNum].size, - chunkBuf, &chunkLen, in)) - { - printf ("Error reading comproessed chunk\n"); - goto fail2; - }; - chunkPos = 0; - GD2_DBG (printf ("Reading (%d, %d) from chunk %d\n", cx, cy, chunkNum)); - }; - - GD2_DBG (printf (" into (%d, %d) - (%d, %d)\n", xlo, ylo, xhi, yhi)); - for (y = ylo; (y < yhi); y++) - { - - for (x = xlo; x < xhi; x++) - { - if (fmt == GD2_FMT_RAW) - { - if (im->trueColor) - { - if (!gdGetInt (&ch, in)) - { - ch = 0; - /*printf("EOF while reading file\n"); */ - /*goto fail2; */ - } - } - else - { - ch = gdGetC (in); - if (ch == EOF) - { - ch = 0; - /*printf("EOF while reading file\n"); */ - /*goto fail2; */ - } - } - } - else - { - if (im->trueColor) - { - ch = chunkBuf[chunkPos++]; - ch = (ch << 8) + chunkBuf[chunkPos++]; - ch = (ch << 8) + chunkBuf[chunkPos++]; - ch = (ch << 8) + chunkBuf[chunkPos++]; - } - else - { - ch = chunkBuf[chunkPos++]; - } - }; - - /* Only use a point that is in the image. */ - if ((x >= srcx) && (x < (srcx + w)) && (x < fsx) && (x >= 0) - && (y >= srcy) && (y < (srcy + h)) && (y < fsy) && (y >= 0) - ) - { - im->pixels[y - srcy][x - srcx] = ch; - } - }; - }; - }; - }; - - gdFree (chunkBuf); - gdFree (compBuf); - gdFree (chunkIdx); + for (cx = scx; cx <= ecx; cx++) { - return im; + xlo = cx * cs; + xhi = xlo + cs; + if (xhi > fsx) { + xhi = fsx; + } + + GD2_DBG(php_gd_error("Processing Chunk (%d, %d), from %d to %d\n", cx, cy, ylo, yhi)); + + if (!gd2_compressed(fmt)) { + GD2_DBG(php_gd_error("Using raw format data\n")); + if (im->trueColor) { + dpos = (cy * (cs * fsx) * 4 + cx * cs * (yhi - ylo) * 4) + dstart; + } else { + dpos = cy * (cs * fsx) + cx * cs * (yhi - ylo) + dstart; + } + + /* gd 2.0.11: gdSeek returns TRUE on success, not 0. Longstanding bug. 01/16/03 */ + if (!gdSeek(in, dpos)) { + php_gd_error_ex(E_WARNING, "Error from seek: %d\n", errno); + goto fail2; + } + GD2_DBG(php_gd_error("Reading (%d, %d) from position %d\n", cx, cy, dpos - dstart)); + } else { + chunkNum = cx + cy * ncx; + + chunkLen = chunkMax; + if (!_gd2ReadChunk (chunkIdx[chunkNum].offset, compBuf, chunkIdx[chunkNum].size, chunkBuf, &chunkLen, in)) { + php_gd_error("Error reading comproessed chunk\n"); + goto fail2; + } + chunkPos = 0; + GD2_DBG(php_gd_error("Reading (%d, %d) from chunk %d\n", cx, cy, chunkNum)); + } + + GD2_DBG(php_gd_error(" into (%d, %d) - (%d, %d)\n", xlo, ylo, xhi, yhi)); + + for (y = ylo; (y < yhi); y++) { + for (x = xlo; x < xhi; x++) { + if (!gd2_compressed(fmt)) { + if (im->trueColor) { + if (!gdGetInt(&ch, in)) { + ch = 0; + } + } else { + ch = gdGetC(in); + if (ch == EOF) { + ch = 0; + } + } + } else { + if (im->trueColor) { + ch = chunkBuf[chunkPos++]; + ch = (ch << 8) + chunkBuf[chunkPos++]; + ch = (ch << 8) + chunkBuf[chunkPos++]; + ch = (ch << 8) + chunkBuf[chunkPos++]; + } else { + ch = chunkBuf[chunkPos++]; + } + } + + /* Only use a point that is in the image. */ + if ((x >= srcx) && (x < (srcx + w)) && (x < fsx) && (x >= 0) && (y >= srcy) && (y < (srcy + h)) && (y < fsy) && (y >= 0)) { + if (im->trueColor) { + im->tpixels[y - srcy][x - srcx] = ch; + } else { + im->pixels[y - srcy][x - srcx] = ch; + } + } + } + } + } + } + + if (chunkBuf) { + gdFree(chunkBuf); + } + if (compBuf) { + gdFree(compBuf); + } + if (chunkIdx) { + gdFree(chunkIdx); + } + + return im; fail2: - gdImageDestroy (im); + gdImageDestroy(im); fail1: - gdFree (chunkBuf); - gdFree (compBuf); - gdFree (chunkIdx); - - return 0; - -} - -static -void -_gd2PutHeader (gdImagePtr im, gdIOCtx * out, int cs, int fmt, int cx, int cy) -{ - int i; - - /* Send the gd2 id, to verify file format. */ - for (i = 0; i < 4; i++) - { - gdPutC ((unsigned char) (GD2_ID[i]), out); - }; - - /* */ - /* We put the version info first, so future versions can easily change header info. */ - /* */ - gdPutWord (GD2_VERS, out); - gdPutWord (im->sx, out); - gdPutWord (im->sy, out); - gdPutWord (cs, out); - gdPutWord (fmt, out); - gdPutWord (cx, out); - gdPutWord (cy, out); - -} - -static void -_gdImageGd2 (gdImagePtr im, gdIOCtx * out, int cs, int fmt) -{ - int ncx, ncy, cx, cy; - int x, y, ylo, yhi, xlo, xhi; - int chunkLen; - int chunkNum = 0; - char *chunkData = NULL; /* So we can gdFree it with impunity. */ - char *compData = NULL; /* So we can gdFree it with impunity. */ - uLongf compLen; - int idxPos = 0; - int idxSize; - t_chunk_info *chunkIdx = NULL; - int posSave; - int bytesPerPixel = im->trueColor ? 4 : 1; - int compMax = 0; - - /*printf("Trying to write GD2 file\n"); */ - - /* */ - /* Force fmt to a valid value since we don't return anything. */ - /* */ - if ((fmt == 0) || ((fmt != GD2_FMT_RAW) && (fmt != GD2_FMT_COMPRESSED))) - { - fmt = GD2_FMT_COMPRESSED; - }; - - /* */ - /* Make sure chunk size is valid. These are arbitrary values; 64 because it seems */ - /* a little silly to expect performance improvements on a 64x64 bit scale, and */ - /* 4096 because we buffer one chunk, and a 16MB buffer seems a little largei - it may be */ - /* OK for one user, but for another to read it, they require the buffer. */ - /* */ - if (cs == 0) - { - cs = GD2_CHUNKSIZE; - } - else if (cs < GD2_CHUNKSIZE_MIN) - { - cs = GD2_CHUNKSIZE_MIN; - } - else if (cs > GD2_CHUNKSIZE_MAX) - { - cs = GD2_CHUNKSIZE_MAX; - }; - - /* Work out number of chunks. */ - ncx = im->sx / cs + 1; - ncy = im->sy / cs + 1; - - /* Write the standard header. */ - _gd2PutHeader (im, out, cs, fmt, ncx, ncy); - - if (fmt == GD2_FMT_COMPRESSED) - { - /* */ - /* Work out size of buffer for compressed data, If CHUNKSIZE is large, */ - /* then these will be large! */ - /* */ - /* The zlib notes say output buffer size should be (input size) * 1.01 * 12 */ - /* - we'll use 1.02 to be paranoid. */ - /* */ - compMax = (int)(cs * bytesPerPixel * cs * 1.02 + 12); - - /* */ - /* Allocate the buffers. */ - /* */ - chunkData = gdCalloc (cs * bytesPerPixel * cs, 1); - compData = gdCalloc (compMax, 1); - - /* */ - /* Save the file position of chunk index, and allocate enough space for */ - /* each chunk_info block . */ - /* */ - idxPos = gdTell (out); - idxSize = ncx * ncy * sizeof (t_chunk_info); - GD2_DBG (printf ("Index size is %d\n", idxSize)); - gdSeek (out, idxPos + idxSize); - - chunkIdx = gdCalloc (idxSize * sizeof (t_chunk_info), 1); - }; - - _gdPutColors (im, out); - - GD2_DBG (printf ("Size: %dx%d\n", im->sx, im->sy)); - GD2_DBG (printf ("Chunks: %dx%d\n", ncx, ncy)); - - for (cy = 0; (cy < ncy); cy++) - { - for (cx = 0; (cx < ncx); cx++) - { - - ylo = cy * cs; - yhi = ylo + cs; - if (yhi > im->sy) - { - yhi = im->sy; - }; - - GD2_DBG (printf ("Processing Chunk (%dx%d), y from %d to %d\n", cx, cy, ylo, yhi)); - chunkLen = 0; - for (y = ylo; (y < yhi); y++) - { - - /*GD2_DBG(printf("y=%d: ",y)); */ - - xlo = cx * cs; - xhi = xlo + cs; - if (xhi > im->sx) - { - xhi = im->sx; - }; - - if (fmt == GD2_FMT_COMPRESSED) - { - for (x = xlo; x < xhi; x++) - { - GD2_DBG(printf("%d...",x)); - if (im->trueColor) - { - int p = im->tpixels[y][x]; - chunkData[chunkLen++] = gdTrueColorGetAlpha (p); - chunkData[chunkLen++] = gdTrueColorGetRed (p); - chunkData[chunkLen++] = gdTrueColorGetGreen (p); - chunkData[chunkLen++] = gdTrueColorGetBlue (p); - } - else - { - chunkData[chunkLen++] = im->pixels[y][x]; + if (chunkBuf) { + gdFree(chunkBuf); + } + if (compBuf) { + gdFree(compBuf); + } + if (chunkIdx) { + gdFree(chunkIdx); + } + + return 0; +} + +static void _gd2PutHeader (gdImagePtr im, gdIOCtx * out, int cs, int fmt, int cx, int cy) +{ + int i; + + /* Send the gd2 id, to verify file format. */ + for (i = 0; i < 4; i++) { + gdPutC((unsigned char) (GD2_ID[i]), out); + } + + /* We put the version info first, so future versions can easily change header info. */ + + gdPutWord(GD2_VERS, out); + gdPutWord(im->sx, out); + gdPutWord(im->sy, out); + gdPutWord(cs, out); + gdPutWord(fmt, out); + gdPutWord(cx, out); + gdPutWord(cy, out); +} + +static void _gdImageGd2 (gdImagePtr im, gdIOCtx * out, int cs, int fmt) +{ + int ncx, ncy, cx, cy; + int x, y, ylo, yhi, xlo, xhi; + int chunkLen; + int chunkNum = 0; + char *chunkData = NULL; /* So we can gdFree it with impunity. */ + char *compData = NULL; /* So we can gdFree it with impunity. */ + uLongf compLen; + int idxPos = 0; + int idxSize; + t_chunk_info *chunkIdx = NULL; /* So we can gdFree it with impunity. */ + int posSave; + int bytesPerPixel = im->trueColor ? 4 : 1; + int compMax = 0; + + /* Force fmt to a valid value since we don't return anything. */ + if ((fmt != GD2_FMT_RAW) && (fmt != GD2_FMT_COMPRESSED)) { + fmt = im->trueColor ? GD2_FMT_TRUECOLOR_COMPRESSED : GD2_FMT_COMPRESSED; + } + if (im->trueColor) { + fmt += 2; + } + /* Make sure chunk size is valid. These are arbitrary values; 64 because it seems + * a little silly to expect performance improvements on a 64x64 bit scale, and + * 4096 because we buffer one chunk, and a 16MB buffer seems a little large - it may be + * OK for one user, but for another to read it, they require the buffer. + */ + if (cs == 0) { + cs = GD2_CHUNKSIZE; + } else if (cs < GD2_CHUNKSIZE_MIN) { + cs = GD2_CHUNKSIZE_MIN; + } else if (cs > GD2_CHUNKSIZE_MAX) { + cs = GD2_CHUNKSIZE_MAX; + } + + /* Work out number of chunks. */ + ncx = im->sx / cs + 1; + ncy = im->sy / cs + 1; + + /* Write the standard header. */ + _gd2PutHeader (im, out, cs, fmt, ncx, ncy); + + if (gd2_compressed(fmt)) { + /* Work out size of buffer for compressed data, If CHUNKSIZE is large, + * then these will be large! + */ + + /* The zlib notes say output buffer size should be (input size) * 1.01 * 12 + * - we'll use 1.02 to be paranoid. + */ + compMax = (int)(cs * bytesPerPixel * cs * 1.02f) + 12; + + /* Allocate the buffers. */ + chunkData = gdCalloc(cs * bytesPerPixel * cs, 1); + compData = gdCalloc(compMax, 1); + + /* Save the file position of chunk index, and allocate enough space for + * each chunk_info block . + */ + idxPos = gdTell(out); + idxSize = ncx * ncy * sizeof(t_chunk_info); + GD2_DBG(php_gd_error("Index size is %d\n", idxSize)); + gdSeek(out, idxPos + idxSize); + + chunkIdx = gdCalloc(idxSize * sizeof(t_chunk_info), 1); + } + + _gdPutColors (im, out); + + GD2_DBG(php_gd_error("Size: %dx%d\n", im->sx, im->sy)); + GD2_DBG(php_gd_error("Chunks: %dx%d\n", ncx, ncy)); + + for (cy = 0; (cy < ncy); cy++) { + for (cx = 0; (cx < ncx); cx++) { + ylo = cy * cs; + yhi = ylo + cs; + if (yhi > im->sy) { + yhi = im->sy; + } + + GD2_DBG(php_gd_error("Processing Chunk (%dx%d), y from %d to %d\n", cx, cy, ylo, yhi)); + chunkLen = 0; + for (y = ylo; (y < yhi); y++) { + GD2_DBG(php_gd_error("y=%d: ",y)); + xlo = cx * cs; + xhi = xlo + cs; + if (xhi > im->sx) { + xhi = im->sx; + } + + if (gd2_compressed(fmt)) { + for (x = xlo; x < xhi; x++) { + GD2_DBG(php_gd_error("%d...",x)); + if (im->trueColor) { + int p = im->tpixels[y][x]; + chunkData[chunkLen++] = gdTrueColorGetAlpha(p); + chunkData[chunkLen++] = gdTrueColorGetRed(p); + chunkData[chunkLen++] = gdTrueColorGetGreen(p); + chunkData[chunkLen++] = gdTrueColorGetBlue(p); + } else { + chunkData[chunkLen++] = im->pixels[y][x]; + } + } + } else { + for (x = xlo; x < xhi; x++) { + GD2_DBG(php_gd_error("%d, ",x)); + + if (im->trueColor) { + gdPutInt(im->tpixels[y][x], out); + } else { + gdPutC((unsigned char) im->pixels[y][x], out); + } + } + } + GD2_DBG(php_gd_error("y=%d done.\n",y)); + } + + if (gd2_compressed(fmt)) { + compLen = compMax; + if (compress((unsigned char *) &compData[0], &compLen, (unsigned char *) &chunkData[0], chunkLen) != Z_OK) { + php_gd_error("Error from compressing\n"); + } else { + chunkIdx[chunkNum].offset = gdTell(out); + chunkIdx[chunkNum++].size = compLen; + GD2_DBG(php_gd_error("Chunk %d size %d offset %d\n", chunkNum, chunkIdx[chunkNum - 1].size, chunkIdx[chunkNum - 1].offset)); + + if (gdPutBuf (compData, compLen, out) <= 0) { + /* Any alternate suggestions for handling this? */ + php_gd_error_ex(E_WARNING, "Error %d on write\n", errno); + } + } } - }; } - else - { - for (x = xlo; x < xhi; x++) - { - /*GD2_DBG(printf("%d, ",x)); */ - - if (im->trueColor) - { - gdPutInt (im->tpixels[y][x], out); - } - else - { - gdPutC ((unsigned char) im->pixels[y][x], out); - } - }; - }; - /*GD2_DBG(printf("y=%d done.\n",y)); */ - }; - if (fmt == GD2_FMT_COMPRESSED) - { - compLen = compMax; - if (compress ((unsigned char *) - &compData[0], &compLen, - (unsigned char *) &chunkData[0], - chunkLen) != Z_OK) - { - printf ("Error from compressing\n"); + } + + if (gd2_compressed(fmt)) { + /* Save the position, write the index, restore position (paranoia). */ + GD2_DBG(php_gd_error("Seeking %d to write index\n", idxPos)); + posSave = gdTell(out); + gdSeek(out, idxPos); + GD2_DBG(php_gd_error("Writing index\n")); + for (x = 0; x < chunkNum; x++) { + GD2_DBG(php_gd_error("Chunk %d size %d offset %d\n", x, chunkIdx[x].size, chunkIdx[x].offset)); + gdPutInt(chunkIdx[x].offset, out); + gdPutInt(chunkIdx[x].size, out); } - else - { - chunkIdx[chunkNum].offset = gdTell (out); - chunkIdx[chunkNum++].size = compLen; - GD2_DBG (printf ("Chunk %d size %d offset %d\n", chunkNum, chunkIdx[chunkNum - 1].size, chunkIdx[chunkNum - 1].offset)); - - if (gdPutBuf (compData, compLen, out) <= 0) - { - /* Any alternate suggestions for handling this? */ - printf ("Error %d on write\n", errno); - }; - }; - }; - }; - }; - if (fmt == GD2_FMT_COMPRESSED) - { - /* Save the position, write the index, restore position (paranoia). */ - GD2_DBG (printf ("Seeking %d to write index\n", idxPos)); - posSave = gdTell (out); - gdSeek (out, idxPos); - GD2_DBG (printf ("Writing index\n")); - for (x = 0; x < chunkNum; x++) - { - GD2_DBG (printf ("Chunk %d size %d offset %d\n", x, chunkIdx[x].size, chunkIdx[x].offset)); - gdPutInt (chunkIdx[x].offset, out); - gdPutInt (chunkIdx[x].size, out); - }; - /* We don't use fwrite for *endian reasons. */ - /*fwrite(chunkIdx, sizeof(int)*2, chunkNum, out); */ - gdSeek (out, posSave); - }; - - GD2_DBG (printf ("Freeing memory\n")); - gdFree (chunkData); - gdFree (compData); - gdFree (chunkIdx); - GD2_DBG (printf ("Done\n")); - - /*printf("Memory block size is %d\n",gdTell(out)); */ + gdSeek(out, posSave); + } + GD2_DBG(php_gd_error("Freeing memory\n")); + if (chunkData) { + gdFree(chunkData); + } + if (compData) { + gdFree(compData); + } + if (chunkIdx) { + gdFree(chunkIdx); + } + GD2_DBG(php_gd_error("Done\n")); } -void -gdImageGd2 (gdImagePtr im, FILE * outFile, int cs, int fmt) -{ - gdIOCtx *out = gdNewFileCtx (outFile); - _gdImageGd2 (im, out, cs, fmt); - out->gd_free (out); -} - -void * -gdImageGd2Ptr (gdImagePtr im, int cs, int fmt, int *size) -{ - void *rv; - gdIOCtx *out = gdNewDynamicCtx (2048, NULL); - _gdImageGd2 (im, out, cs, fmt); - rv = gdDPExtractData (out, size); - out->gd_free (out); - return rv; +void gdImageGd2 (gdImagePtr im, FILE * outFile, int cs, int fmt) +{ + gdIOCtx *out = gdNewFileCtx(outFile); + + _gdImageGd2(im, out, cs, fmt); + + out->gd_free(out); +} + +void *gdImageGd2Ptr (gdImagePtr im, int cs, int fmt, int *size) +{ + void *rv; + gdIOCtx *out = gdNewDynamicCtx(2048, NULL); + + _gdImageGd2(im, out, cs, fmt); + rv = gdDPExtractData(out, size); + out->gd_free(out); + + return rv; } Index: php4/ext/gd/libgd/gd_gif_in.c diff -u php4/ext/gd/libgd/gd_gif_in.c:1.2 php4/ext/gd/libgd/gd_gif_in.c:1.2.2.1 --- php4/ext/gd/libgd/gd_gif_in.c:1.2 Tue Oct 29 18:08:01 2002 +++ php4/ext/gd/libgd/gd_gif_in.c Wed Mar 5 11:04:20 2003 @@ -4,6 +4,8 @@ #include <stdlib.h> #include "gd.h" +#include "php.h" + /* Used only when debugging GIF compression code */ /* #define DEBUGGING_ENVARS */ @@ -290,19 +292,24 @@ static int GetDataBlock(gdIOCtx *fd, unsigned char *buf) { - int rv; - int i; - - rv = GetDataBlock_(fd,buf); - if (VERBOSE) - { printf("[GetDataBlock returning %d",rv); - if (rv > 0) - { printf(":"); - for (i=0;i<rv;i++) printf(" %02x",buf[i]); - } - printf("]\n"); - } - return(rv); + int rv; + int i; + char *tmp = NULL; + + rv = GetDataBlock_(fd,buf); + if (VERBOSE) { + if (rv > 0) { + tmp = emalloc((3*sizeof(char)*rv) + 1); + for (i=0;i<rv;i++) { + sprintf(&tmp[3*sizeof(char)*i], " %02x", buf[i]); + } + } else { + tmp = estrdup(""); + } + php_gd_error_ex(E_NOTICE, "[GetDataBlock returning %d: %s]", rv, tmp); + efree(tmp); + } + return(rv); } static int @@ -352,7 +359,7 @@ int rv; rv = GetCode_(fd,code_size,flag); - if (VERBOSE) printf("[GetCode(,%d,%d) returning %d]\n",code_size,flag,rv); + if (VERBOSE) php_gd_error_ex(E_NOTICE, "[GetCode(,%d,%d) returning %d]\n",code_size,flag,rv); return(rv); } @@ -484,7 +491,7 @@ int rv; rv = LWZReadByte_(fd,flag,input_code_size); - if (VERBOSE) printf("[LWZReadByte(,%d,%d) returning %d]\n",flag,input_code_size,rv); + if (VERBOSE) php_gd_error_ex(E_NOTICE, "[LWZReadByte(,%d,%d) returning %d]\n",flag,input_code_size,rv); return(rv); } Index: php4/ext/gd/libgd/gd_jpeg.c diff -u php4/ext/gd/libgd/gd_jpeg.c:1.4 php4/ext/gd/libgd/gd_jpeg.c:1.4.2.1 --- php4/ext/gd/libgd/gd_jpeg.c:1.4 Tue Oct 29 18:08:01 2002 +++ php4/ext/gd/libgd/gd_jpeg.c Wed Mar 5 11:04:20 2003 @@ -16,6 +16,9 @@ * Modification 4/18/00 TBB: JPEG_DEBUG rather than just DEBUG, * so VC++ builds don't spew to standard output, causing * major CGI brain damage + * + * 2.0.10: more efficient gdImageCreateFromJpegCtx, thanks to + * Christian Aberger */ #include <stdio.h> @@ -29,6 +32,7 @@ /* JCE: arrange HAVE_LIBJPEG so that it can be set in gd.h */ #ifdef HAVE_LIBJPEG #include "gdhelpers.h" +#undef HAVE_STDLIB_H /* 1.8.1: remove dependency on jinclude.h */ #include "jpeglib.h" @@ -37,38 +41,30 @@ static const char *const GD_JPEG_VERSION = "1.0"; typedef struct _jmpbuf_wrapper - { - jmp_buf jmpbuf; - } -jmpbuf_wrapper; +{ + jmp_buf jmpbuf; +} jmpbuf_wrapper; /* Called by the IJG JPEG library upon encountering a fatal error */ static void fatal_jpeg_error (j_common_ptr cinfo) { - jmpbuf_wrapper *jmpbufw; + jmpbuf_wrapper *jmpbufw; + + php_gd_error("gd-jpeg: JPEG library reports unrecoverable error: "); + (*cinfo->err->output_message) (cinfo); - fprintf (stderr, "gd-jpeg: JPEG library reports unrecoverable error: "); - (*cinfo->err->output_message) (cinfo); - fflush (stderr); - - jmpbufw = (jmpbuf_wrapper *) cinfo->client_data; - jpeg_destroy (cinfo); - - if (jmpbufw != 0) - { - longjmp (jmpbufw->jmpbuf, 1); - fprintf (stderr, "gd-jpeg: EXTREMELY fatal error: longjmp" - " returned control; terminating\n"); - } - else - { - fprintf (stderr, "gd-jpeg: EXTREMELY fatal error: jmpbuf" - " unrecoverable; terminating\n"); - } + jmpbufw = (jmpbuf_wrapper *) cinfo->client_data; + jpeg_destroy (cinfo); + + if (jmpbufw != 0) { + longjmp (jmpbufw->jmpbuf, 1); + php_gd_error_ex(E_ERROR, "gd-jpeg: EXTREMELY fatal error: longjmp returned control; terminating"); + } else { + php_gd_error_ex(E_ERROR, "gd-jpeg: EXTREMELY fatal error: jmpbuf unrecoverable; terminating"); + } - fflush (stderr); - exit (99); + exit (99); } /* @@ -77,25 +73,27 @@ * represent higher quality but also larger image size. If QUALITY is * negative, the IJG JPEG library's default quality is used (which * should be near optimal for many applications). See the IJG JPEG - * library documentation for more details. */ + * library documentation for more details. + */ void gdImageJpeg (gdImagePtr im, FILE * outFile, int quality) { - gdIOCtx *out = gdNewFileCtx (outFile); - gdImageJpegCtx (im, out, quality); - out->gd_free (out); + gdIOCtx *out = gdNewFileCtx (outFile); + gdImageJpegCtx (im, out, quality); + out->gd_free (out); } void * gdImageJpegPtr (gdImagePtr im, int *size, int quality) { - void *rv; - gdIOCtx *out = gdNewDynamicCtx (2048, NULL); - gdImageJpegCtx (im, out, quality); - rv = gdDPExtractData (out, size); - out->gd_free (out); - return rv; + void *rv; + gdIOCtx *out = gdNewDynamicCtx (2048, NULL); + gdImageJpegCtx (im, out, quality); + rv = gdDPExtractData (out, size); + out->gd_free (out); + + return rv; } void jpeg_gdIOCtx_dest (j_compress_ptr cinfo, gdIOCtx * outfile); @@ -103,168 +101,127 @@ void gdImageJpegCtx (gdImagePtr im, gdIOCtx * outfile, int quality) { - struct jpeg_compress_struct cinfo; - struct jpeg_error_mgr jerr; - int i, j, jidx; - /* volatile so we can gdFree it on return from longjmp */ - volatile JSAMPROW row = 0; - JSAMPROW rowptr[1]; - jmpbuf_wrapper jmpbufw; - JDIMENSION nlines; - char comment[255]; - -#ifdef JPEG_DEBUG - printf ("gd-jpeg: gd JPEG version %s\n", GD_JPEG_VERSION); - printf ("gd-jpeg: JPEG library version %d, %d-bit sample values\n", - JPEG_LIB_VERSION, BITS_IN_JSAMPLE); - if (!im->trueColor) - { - for (i = 0; i < im->colorsTotal; i++) - { - if (!im->open[i]) - printf ("gd-jpeg: gd colormap index %d: (%d, %d, %d)\n", i, - im->red[i], im->green[i], im->blue[i]); - } - } -#endif /* JPEG_DEBUG */ - - memset (&cinfo, 0, sizeof (cinfo)); - memset (&jerr, 0, sizeof (jerr)); - - cinfo.err = jpeg_std_error (&jerr); - cinfo.client_data = &jmpbufw; - if (setjmp (jmpbufw.jmpbuf) != 0) - { - /* we're here courtesy of longjmp */ - if (row) - gdFree (row); - return; - } + struct jpeg_compress_struct cinfo; + struct jpeg_error_mgr jerr; + int i, j, jidx; + /* volatile so we can gdFree it on return from longjmp */ + volatile JSAMPROW row = 0; + JSAMPROW rowptr[1]; + jmpbuf_wrapper jmpbufw; + JDIMENSION nlines; + char comment[255]; + + memset (&cinfo, 0, sizeof (cinfo)); + memset (&jerr, 0, sizeof (jerr)); + + cinfo.err = jpeg_std_error (&jerr); + cinfo.client_data = &jmpbufw; + if (setjmp (jmpbufw.jmpbuf) != 0) { + /* we're here courtesy of longjmp */ + if (row) { + gdFree (row); + } + return; + } - cinfo.err->error_exit = fatal_jpeg_error; + cinfo.err->error_exit = fatal_jpeg_error; - jpeg_create_compress (&cinfo); + jpeg_create_compress (&cinfo); - cinfo.image_width = im->sx; - cinfo.image_height = im->sy; - cinfo.input_components = 3; /* # of color components per pixel */ - cinfo.in_color_space = JCS_RGB; /* colorspace of input image */ - jpeg_set_defaults (&cinfo); - if (quality >= 0) - jpeg_set_quality (&cinfo, quality, TRUE); - - /* If user requests interlace, translate that to progressive JPEG */ - if (gdImageGetInterlaced (im)) - { -#ifdef JPEG_DEBUG - printf ("gd-jpeg: interlace set, outputting progressive" - " JPEG image\n"); -#endif - jpeg_simple_progression (&cinfo); - } + cinfo.image_width = im->sx; + cinfo.image_height = im->sy; + cinfo.input_components = 3; /* # of color components per pixel */ + cinfo.in_color_space = JCS_RGB; /* colorspace of input image */ + jpeg_set_defaults (&cinfo); + if (quality >= 0) { + jpeg_set_quality (&cinfo, quality, TRUE); + } + + /* If user requests interlace, translate that to progressive JPEG */ + if (gdImageGetInterlaced (im)) { + jpeg_simple_progression (&cinfo); + } - jpeg_gdIOCtx_dest (&cinfo, outfile); + jpeg_gdIOCtx_dest (&cinfo, outfile); + + row = (JSAMPROW) gdCalloc (1, cinfo.image_width * cinfo.input_components * sizeof (JSAMPLE)); + rowptr[0] = row; + + jpeg_start_compress (&cinfo, TRUE); + + if (quality >= 0) { + snprintf(comment, sizeof(comment)-1, "CREATOR: gd-jpeg v%s (using IJG JPEG v%d), quality = %d\n", GD_JPEG_VERSION, JPEG_LIB_VERSION, quality); + } else { + snprintf(comment, sizeof(comment)-1, "CREATOR: gd-jpeg v%s (using IJG JPEG v%d), default quality\n", GD_JPEG_VERSION, JPEG_LIB_VERSION); + } + jpeg_write_marker (&cinfo, JPEG_COM, (unsigned char *) comment, (unsigned int) strlen (comment)); + if (im->trueColor) { - row = (JSAMPROW) gdCalloc (1, cinfo.image_width * cinfo.input_components - * sizeof (JSAMPLE)); - if (row == 0) - { - fprintf (stderr, "gd-jpeg: error: unable to allocate JPEG row " - "structure: gdCalloc returns NULL\n"); - jpeg_destroy_compress (&cinfo); - return; - } - - rowptr[0] = row; - - jpeg_start_compress (&cinfo, TRUE); - - sprintf (comment, "CREATOR: gd-jpeg v%s (using IJG JPEG v%d),", - GD_JPEG_VERSION, JPEG_LIB_VERSION); - if (quality >= 0) - sprintf (comment + strlen (comment), " quality = %d\n", - quality); - else - strcat (comment + strlen (comment), " default quality\n"); - jpeg_write_marker (&cinfo, JPEG_COM, (unsigned char *) comment, - (unsigned int) strlen (comment)); - if (im->trueColor) - { #if BITS_IN_JSAMPLE == 12 - fprintf (stderr, "gd-jpeg: error: jpeg library was compiled for 12-bit\n" - "precision. This is mostly useless, because JPEGs on the web are\n" - "8-bit and such versions of the jpeg library won't read or write\n" - "them. GD doesn't support these unusual images. Edit your\n" - "jmorecfg.h file to specify the correct precision and completely\n" - "'make clean' and 'make install' libjpeg again. Sorry.\n"); - goto error; + php_gd_error("gd-jpeg: error: jpeg library was compiled for 12-bit precision. This is mostly useless, because JPEGs on the web are 8-bit and such versions of the jpeg library won't read or write them. GD doesn't support these unusual images. Edit your jmorecfg.h file to specify the correct precision and completely 'make clean' and 'make install' libjpeg again. Sorry"); + goto error; #endif /* BITS_IN_JSAMPLE == 12 */ - for (i = 0; i < im->sy; i++) - { - for (jidx = 0, j = 0; j < im->sx; j++) - { - int val = im->tpixels[i][j]; - row[jidx++] = gdTrueColorGetRed (val); - row[jidx++] = gdTrueColorGetGreen (val); - row[jidx++] = gdTrueColorGetBlue (val); - } - - nlines = jpeg_write_scanlines (&cinfo, rowptr, 1); - if (nlines != 1) - fprintf (stderr, "gd_jpeg: warning: jpeg_write_scanlines" - " returns %u -- expected 1\n", nlines); - } - } - else - { - for (i = 0; i < im->sy; i++) - { - for (jidx = 0, j = 0; j < im->sx; j++) - { - int idx = im->pixels[i][j]; - - /* - * NB: Although gd RGB values are ints, their max value is - * 255 (see the documentation for gdImageColorAllocate()) - * -- perfect for 8-bit JPEG encoding (which is the norm) - */ + + for (i = 0; i < im->sy; i++) { + for (jidx = 0, j = 0; j < im->sx; j++) { + int val = im->tpixels[i][j]; + + row[jidx++] = gdTrueColorGetRed (val); + row[jidx++] = gdTrueColorGetGreen (val); + row[jidx++] = gdTrueColorGetBlue (val); + } + + nlines = jpeg_write_scanlines (&cinfo, rowptr, 1); + if (nlines != 1) { + php_gd_error_ex(E_WARNING, "gd_jpeg: warning: jpeg_write_scanlines returns %u -- expected 1\n", nlines); + } + } + } else { + for (i = 0; i < im->sy; i++) { + for (jidx = 0, j = 0; j < im->sx; j++) { + int idx = im->pixels[i][j]; + + /* NB: Although gd RGB values are ints, their max value is + * 255 (see the documentation for gdImageColorAllocate()) + * -- perfect for 8-bit JPEG encoding (which is the norm) + */ #if BITS_IN_JSAMPLE == 8 - row[jidx++] = im->red[idx]; - row[jidx++] = im->green[idx]; - row[jidx++] = im->blue[idx]; + row[jidx++] = im->red[idx]; + row[jidx++] = im->green[idx]; + row[jidx++] = im->blue[idx]; #elif BITS_IN_JSAMPLE == 12 - row[jidx++] = im->red[idx] << 4; - row[jidx++] = im->green[idx] << 4; - row[jidx++] = im->blue[idx] << 4; + row[jidx++] = im->red[idx] << 4; + row[jidx++] = im->green[idx] << 4; + row[jidx++] = im->blue[idx] << 4; #else #error IJG JPEG library BITS_IN_JSAMPLE value must be 8 or 12 #endif - } + } + + nlines = jpeg_write_scanlines (&cinfo, rowptr, 1); + if (nlines != 1) { + php_gd_error_ex(E_WARNING, "gd_jpeg: warning: jpeg_write_scanlines returns %u -- expected 1\n", nlines); + } + } + } - nlines = jpeg_write_scanlines (&cinfo, rowptr, 1); - if (nlines != 1) - fprintf (stderr, "gd_jpeg: warning: jpeg_write_scanlines" - " returns %u -- expected 1\n", nlines); - } - } - jpeg_finish_compress (&cinfo); - jpeg_destroy_compress (&cinfo); - gdFree (row); + jpeg_finish_compress (&cinfo); + jpeg_destroy_compress (&cinfo); + gdFree (row); } gdImagePtr gdImageCreateFromJpeg (FILE * inFile) { - gdImagePtr im; - gdIOCtx *in = gdNewFileCtx (inFile); - im = gdImageCreateFromJpegCtx (in); - in->gd_free (in); - return im; + gdImagePtr im; + gdIOCtx *in = gdNewFileCtx (inFile); + im = gdImageCreateFromJpegCtx (in); + in->gd_free (in); + + return im; } -void - jpeg_gdIOCtx_src (j_decompress_ptr cinfo, - gdIOCtx * infile); +void jpeg_gdIOCtx_src (j_decompress_ptr cinfo, gdIOCtx * infile); /* * Create a gd-format image from the JPEG-format INFILE. Returns the @@ -273,197 +230,122 @@ gdImagePtr gdImageCreateFromJpegCtx (gdIOCtx * infile) { - struct jpeg_decompress_struct cinfo; - struct jpeg_error_mgr jerr; - jmpbuf_wrapper jmpbufw; - /* volatile so we can gdFree them after longjmp */ - volatile JSAMPROW row = 0; - volatile gdImagePtr im = 0; - JSAMPROW rowptr[1]; - JDIMENSION i, j; - JDIMENSION nrows; - int retval; - -#ifdef JPEG_DEBUG - printf ("gd-jpeg: gd JPEG version %s\n", GD_JPEG_VERSION); - printf ("gd-jpeg: JPEG library version %d, %d-bit sample values\n", - JPEG_LIB_VERSION, BITS_IN_JSAMPLE); -#endif + struct jpeg_decompress_struct cinfo; + struct jpeg_error_mgr jerr; + jmpbuf_wrapper jmpbufw; + /* volatile so we can gdFree them after longjmp */ + volatile JSAMPROW row = 0; + volatile gdImagePtr im = 0; + JSAMPROW rowptr[1]; + unsigned int i, j; + int retval; + JDIMENSION nrows; + + memset (&cinfo, 0, sizeof (cinfo)); + memset (&jerr, 0, sizeof (jerr)); + + cinfo.err = jpeg_std_error (&jerr); + cinfo.client_data = &jmpbufw; + if (setjmp (jmpbufw.jmpbuf) != 0) { + /* we're here courtesy of longjmp */ + if (row) { + gdFree (row); + } + if (im) { + gdImageDestroy (im); + } + return 0; + } - memset (&cinfo, 0, sizeof (cinfo)); - memset (&jerr, 0, sizeof (jerr)); + cinfo.err->error_exit = fatal_jpeg_error; - cinfo.err = jpeg_std_error (&jerr); - cinfo.client_data = &jmpbufw; - if (setjmp (jmpbufw.jmpbuf) != 0) - { - /* we're here courtesy of longjmp */ - if (row) - gdFree (row); - if (im) - gdImageDestroy (im); - return 0; - } - - cinfo.err->error_exit = fatal_jpeg_error; - - jpeg_create_decompress (&cinfo); - - jpeg_gdIOCtx_src (&cinfo, infile); - - retval = jpeg_read_header (&cinfo, TRUE); - if (retval != JPEG_HEADER_OK) - fprintf (stderr, "gd-jpeg: warning: jpeg_read_header returns" - " %d, expected %d\n", retval, JPEG_HEADER_OK); - - if (cinfo.image_height > INT_MAX) - fprintf (stderr, "gd-jpeg: warning: JPEG image height (%u) is" - " greater than INT_MAX (%d) (and thus greater than" - " gd can handle)", cinfo.image_height, - INT_MAX); - - if (cinfo.image_width > INT_MAX) - fprintf (stderr, "gd-jpeg: warning: JPEG image width (%u) is" - " greater than INT_MAX (%d) (and thus greater than" - " gd can handle)\n", cinfo.image_width, INT_MAX); - - im = gdImageCreateTrueColor ((int) cinfo.image_width, - (int) cinfo.image_height); - if (im == 0) - { - fprintf (stderr, "gd-jpeg error: cannot allocate gdImage" - " struct\n"); - goto error; - } - - /* - * Force the image into RGB colorspace, but don't - * reduce the number of colors anymore (GD 2.0) - */ - cinfo.out_color_space = JCS_RGB; - - if (jpeg_start_decompress (&cinfo) != TRUE) - fprintf (stderr, "gd-jpeg: warning: jpeg_start_decompress" - " reports suspended data source\n"); - -#ifdef JPEG_DEBUG - printf ("gd-jpeg: JPEG image information:"); - if (cinfo.saw_JFIF_marker) - printf (" JFIF version %d.%.2d", - (int) cinfo.JFIF_major_version, - (int) cinfo.JFIF_minor_version); - else if (cinfo.saw_Adobe_marker) - printf (" Adobe format"); - else - printf (" UNKNOWN format"); - - printf (" %ux%u (raw) / %ux%u (scaled) %d-bit", cinfo.image_width, - cinfo.image_height, cinfo.output_width, - cinfo.output_height, cinfo.data_precision); - printf (" %s", (cinfo.progressive_mode ? "progressive" : - "baseline")); - printf (" image, %d quantized colors, ", - cinfo.actual_number_of_colors); - - switch (cinfo.jpeg_color_space) - { - case JCS_GRAYSCALE: - printf ("grayscale"); - break; - - case JCS_RGB: - printf ("RGB"); - break; - - case JCS_YCbCr: - printf ("YCbCr (a.k.a. YUV)"); - break; - - case JCS_CMYK: - printf ("CMYK"); - break; - - case JCS_YCCK: - printf ("YCbCrK"); - break; - - default: - printf ("UNKNOWN (value: %d)", (int) cinfo.jpeg_color_space); - break; - } - printf (" colorspace\n"); - fflush (stdout); -#endif /* JPEG_DEBUG */ - - /* REMOVED by TBB 2/12/01. This field of the structure is - documented as private, and sure enough it's gone in the - latest libjpeg, replaced by something else. Unfortunately - there is still no right way to find out if the file was - progressive or not; just declare your intent before you - write one by calling gdImageInterlace(im, 1) yourself. - After all, we're not really supposed to rework JPEGs and - write them out again anyway. Lossy compression, remember? */ + jpeg_create_decompress (&cinfo); + + jpeg_gdIOCtx_src (&cinfo, infile); + + retval = jpeg_read_header (&cinfo, TRUE); + if (retval != JPEG_HEADER_OK) { + php_gd_error_ex(E_WARNING, "gd-jpeg: warning: jpeg_read_header returned %d, expected %d", retval, JPEG_HEADER_OK); + } + + if (cinfo.image_height > INT_MAX) { + php_gd_error_ex(E_WARNING, "gd-jpeg: warning: JPEG image height (%u) is greater than INT_MAX (%d) (and thus greater than gd can handle)", cinfo.image_height, INT_MAX); + } + + if (cinfo.image_width > INT_MAX) { + php_gd_error_ex(E_WARNING, "gd-jpeg: warning: JPEG image width (%u) is greater than INT_MAX (%d) (and thus greater than gd can handle)", cinfo.image_width, INT_MAX); + } + + im = gdImageCreateTrueColor ((int) cinfo.image_width, (int) cinfo.image_height); + if (im == 0) { + php_gd_error("gd-jpeg error: cannot allocate gdImage struct"); + goto error; + } + + /* Force the image into RGB colorspace, but don't reduce the number of colors anymore (GD 2.0) */ + cinfo.out_color_space = JCS_RGB; + + if (jpeg_start_decompress (&cinfo) != TRUE) { + php_gd_error("gd-jpeg: warning: jpeg_start_decompress reports suspended data source"); + } + + /* REMOVED by TBB 2/12/01. This field of the structure is + * documented as private, and sure enough it's gone in the + * latest libjpeg, replaced by something else. Unfortunately + * there is still no right way to find out if the file was + * progressive or not; just declare your intent before you + * write one by calling gdImageInterlace(im, 1) yourself. + * After all, we're not really supposed to rework JPEGs and + * write them out again anyway. Lossy compression, remember? + */ #if 0 gdImageInterlace (im, cinfo.progressive_mode != 0); #endif - if (cinfo.output_components != 3) - { - fprintf (stderr, "gd-jpeg: error: JPEG color quantization" - " request resulted in output_components == %d" - " (expected 3)\n", cinfo.output_components); - goto error; - } + + if (cinfo.output_components != 3) { + php_gd_error_ex(E_WARNING, "gd-jpeg: error: JPEG color quantization request resulted in output_components == %d (expected 3)", cinfo.output_components); + goto error; + } #if BITS_IN_JSAMPLE == 12 - fprintf (stderr, "gd-jpeg: error: jpeg library was compiled for 12-bit\n" - "precision. This is mostly useless, because JPEGs on the web are\n" - "8-bit and such versions of the jpeg library won't read or write\n" - "them. GD doesn't support these unusual images. Edit your\n" - "jmorecfg.h file to specify the correct precision and completely\n" - "'make clean' and 'make install' libjpeg again. Sorry.\n"); - goto error; + php_gd_error("gd-jpeg: error: jpeg library was compiled for 12-bit precision. This is mostly useless, because JPEGs on the web are 8-bit and such versions of the jpeg library won't read or write them. GD doesn't support these unusual images. Edit your jmorecfg.h file to specify the correct precision and completely 'make clean' and 'make install' libjpeg again. Sorry."); + goto error; #endif /* BITS_IN_JSAMPLE == 12 */ - row = gdCalloc (cinfo.output_width * 3, sizeof (JSAMPLE)); - if (row == 0) - { - fprintf (stderr, "gd-jpeg: error: unable to allocate row for" - " JPEG scanline: gdCalloc returns NULL\n"); - goto error; - } - rowptr[0] = row; - - for (i = 0; i < cinfo.output_height; i++) - { - nrows = jpeg_read_scanlines (&cinfo, rowptr, 1); - if (nrows != 1) - { - fprintf (stderr, "gd-jpeg: error: jpeg_read_scanlines" - " returns %u, expected 1\n", nrows); - goto error; - } - - for (j = 0; j < cinfo.output_width; j++) - im->tpixels[i][j] = gdTrueColor (row[j * 3], row[j * 3 + 1], - row[j * 3 + 2]); - } - - if (jpeg_finish_decompress (&cinfo) != TRUE) - fprintf (stderr, "gd-jpeg: warning: jpeg_finish_decompress" - " reports suspended data source\n"); - - - jpeg_destroy_decompress (&cinfo); - gdFree (row); - return im; + row = gdCalloc (cinfo.output_width * 3, sizeof (JSAMPLE)); + rowptr[0] = row; + + for (i = 0; i < cinfo.output_height; i++) { + register JSAMPROW currow = row; + register int *tpix = im->tpixels[i]; + nrows = jpeg_read_scanlines (&cinfo, rowptr, 1); + if (nrows != 1) { + php_gd_error_ex(E_WARNING, "gd-jpeg: error: jpeg_read_scanlines returns %u, expected 1", nrows); + goto error; + } + for (j = 0; j < cinfo.output_width; j++, currow += 3, tpix++) { + *tpix = gdTrueColor (currow[0], currow[1], currow[2]); + } + } + + if (jpeg_finish_decompress (&cinfo) != TRUE) { + php_gd_error("gd-jpeg: warning: jpeg_finish_decompress reports suspended data source"); + } + + jpeg_destroy_decompress (&cinfo); + gdFree (row); + + return im; error: - jpeg_destroy_decompress (&cinfo); - if (row) - gdFree (row); - if (im) - gdImageDestroy (im); - return 0; + jpeg_destroy_decompress (&cinfo); + if (row) { + gdFree (row); + } + if (im) { + gdImageDestroy (im); + } + return 0; } /* @@ -489,15 +371,13 @@ /* Expanded data source object for gdIOCtx input */ typedef struct - { - struct jpeg_source_mgr pub; /* public fields */ +{ + struct jpeg_source_mgr pub; /* public fields */ - gdIOCtx *infile; /* source stream */ - unsigned char *buffer; /* start of buffer */ - safeboolean start_of_file; /* have we gotten any data yet? */ - - } -my_source_mgr; + gdIOCtx *infile; /* source stream */ + unsigned char *buffer; /* start of buffer */ + safeboolean start_of_file; /* have we gotten any data yet? */ +} my_source_mgr; typedef my_source_mgr *my_src_ptr; @@ -511,13 +391,13 @@ void init_source (j_decompress_ptr cinfo) { - my_src_ptr src = (my_src_ptr) cinfo->src; + my_src_ptr src = (my_src_ptr) cinfo->src; - /* We reset the empty-input-file flag for each image, - * but we don't clear the input buffer. - * This is correct behavior for reading a series of images from one source. - */ - src->start_of_file = TRUE; + /* We reset the empty-input-file flag for each image, + * but we don't clear the input buffer. + * This is correct behavior for reading a series of images from one source. + */ + src->start_of_file = TRUE; } @@ -559,56 +439,42 @@ safeboolean fill_input_buffer (j_decompress_ptr cinfo) { - my_src_ptr src = (my_src_ptr) cinfo->src; - size_t nbytes = 0; + my_src_ptr src = (my_src_ptr) cinfo->src; + size_t nbytes = 0; - /* size_t got; */ - /* char *s; */ - memset (src->buffer, 0, INPUT_BUF_SIZE); + /* size_t got; */ + /* char *s; */ + memset (src->buffer, 0, INPUT_BUF_SIZE); - while (nbytes < INPUT_BUF_SIZE) - { + while (nbytes < INPUT_BUF_SIZE) { + int got = gdGetBuf (src->buffer + nbytes, INPUT_BUF_SIZE - nbytes, src->infile); - int got = gdGetBuf (src->buffer + nbytes, - INPUT_BUF_SIZE - nbytes, - src->infile); - - if ((got == EOF) || (got == 0)) - { - - /* EOF or error. If we got any data, don't worry about it. - If we didn't, then this is unexpected. */ - if (!nbytes) - { - - nbytes = -1; - - } - - break; - + if ((got == EOF) || (got == 0)) { + /* EOF or error. If we got any data, don't worry about it. If we didn't, then this is unexpected. */ + if (!nbytes) { + nbytes = -1; + } + break; + } + nbytes += got; } - - nbytes += got; - - } - if (nbytes <= 0) - { - if (src->start_of_file) /* Treat empty input file as fatal error */ - ERREXIT (cinfo, JERR_INPUT_EMPTY); - WARNMS (cinfo, JWRN_JPEG_EOF); - /* Insert a fake EOI marker */ - src->buffer[0] = (unsigned char) 0xFF; - src->buffer[1] = (unsigned char) JPEG_EOI; - nbytes = 2; - } - - src->pub.next_input_byte = src->buffer; - src->pub.bytes_in_buffer = nbytes; - src->start_of_file = FALSE; + if (nbytes <= 0) { + if (src->start_of_file) { /* Treat empty input file as fatal error */ + ERREXIT (cinfo, JERR_INPUT_EMPTY); + } + WARNMS (cinfo, JWRN_JPEG_EOF); + /* Insert a fake EOI marker */ + src->buffer[0] = (unsigned char) 0xFF; + src->buffer[1] = (unsigned char) JPEG_EOI; + nbytes = 2; + } - return TRUE; + src->pub.next_input_byte = src->buffer; + src->pub.bytes_in_buffer = nbytes; + src->start_of_file = FALSE; + + return TRUE; } @@ -627,24 +493,22 @@ void skip_input_data (j_decompress_ptr cinfo, long num_bytes) { - my_src_ptr src = (my_src_ptr) cinfo->src; + my_src_ptr src = (my_src_ptr) cinfo->src; - /* Just a dumb implementation for now. Not clear that being smart is worth - * any trouble anyway --- large skips are infrequent. - */ - if (num_bytes > 0) - { - while (num_bytes > (long) src->pub.bytes_in_buffer) - { - num_bytes -= (long) src->pub.bytes_in_buffer; - (void) fill_input_buffer (cinfo); - /* note we assume that fill_input_buffer will never return FALSE, - * so suspension need not be handled. - */ - } - src->pub.next_input_byte += (size_t) num_bytes; - src->pub.bytes_in_buffer -= (size_t) num_bytes; - } + /* Just a dumb implementation for now. Not clear that being smart is worth + * any trouble anyway --- large skips are infrequent. + */ + if (num_bytes > 0) { + while (num_bytes > (long) src->pub.bytes_in_buffer) { + num_bytes -= (long) src->pub.bytes_in_buffer; + (void) fill_input_buffer (cinfo); + /* note we assume that fill_input_buffer will never return FALSE, + * so suspension need not be handled. + */ + } + src->pub.next_input_byte += (size_t) num_bytes; + src->pub.bytes_in_buffer -= (size_t) num_bytes; + } } @@ -669,11 +533,9 @@ void term_source (j_decompress_ptr cinfo) { - #if 0 -/* never used */ - my_src_ptr src = (my_src_ptr) cinfo->src; - + * never used */ + my_src_ptr src = (my_src_ptr) cinfo->src; #endif } @@ -685,50 +547,44 @@ */ void -jpeg_gdIOCtx_src (j_decompress_ptr cinfo, - gdIOCtx * infile) +jpeg_gdIOCtx_src (j_decompress_ptr cinfo, gdIOCtx * infile) { - my_src_ptr src; + my_src_ptr src; - /* The source object and input buffer are made permanent so that a series - * of JPEG images can be read from the same file by calling jpeg_gdIOCtx_src - * only before the first one. (If we discarded the buffer at the end of - * one image, we'd likely lose the start of the next one.) - * This makes it unsafe to use this manager and a different source - * manager serially with the same JPEG object. Caveat programmer. - */ - if (cinfo->src == NULL) - { /* first time for this JPEG object? */ - cinfo->src = (struct jpeg_source_mgr *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, - sizeof (my_source_mgr)); - src = (my_src_ptr) cinfo->src; - src->buffer = (unsigned char *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, - INPUT_BUF_SIZE * sizeof (unsigned char)); + /* The source object and input buffer are made permanent so that a series + * of JPEG images can be read from the same file by calling jpeg_gdIOCtx_src + * only before the first one. (If we discarded the buffer at the end of + * one image, we'd likely lose the start of the next one.) + * This makes it unsafe to use this manager and a different source + * manager serially with the same JPEG object. Caveat programmer. + */ + if (cinfo->src == NULL) { /* first time for this JPEG object? */ + cinfo->src = (struct jpeg_source_mgr *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, sizeof (my_source_mgr)); + src = (my_src_ptr) cinfo->src; + src->buffer = (unsigned char *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, INPUT_BUF_SIZE * sizeof (unsigned char)); - } + } - src = (my_src_ptr) cinfo->src; - src->pub.init_source = init_source; - src->pub.fill_input_buffer = fill_input_buffer; - src->pub.skip_input_data = skip_input_data; - src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */ - src->pub.term_source = term_source; - src->infile = infile; - src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */ - src->pub.next_input_byte = NULL; /* until buffer loaded */ + src = (my_src_ptr) cinfo->src; + src->pub.init_source = init_source; + src->pub.fill_input_buffer = fill_input_buffer; + src->pub.skip_input_data = skip_input_data; + src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */ + src->pub.term_source = term_source; + src->infile = infile; + src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */ + src->pub.next_input_byte = NULL; /* until buffer loaded */ } /* Expanded data destination object for stdio output */ typedef struct { - struct jpeg_destination_mgr pub; /* public fields */ - gdIOCtx *outfile; /* target stream */ - unsigned char *buffer; /* start of buffer */ -} -my_destination_mgr; + struct jpeg_destination_mgr pub; /* public fields */ + gdIOCtx *outfile; /* target stream */ + unsigned char *buffer; /* start of buffer */ +} my_destination_mgr; typedef my_destination_mgr *my_dest_ptr; @@ -742,15 +598,13 @@ void init_destination (j_compress_ptr cinfo) { - my_dest_ptr dest = (my_dest_ptr) cinfo->dest; + my_dest_ptr dest = (my_dest_ptr) cinfo->dest; - /* Allocate the output buffer --- it will be released when done with image */ - dest->buffer = (unsigned char *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - OUTPUT_BUF_SIZE * sizeof (unsigned char)); + /* Allocate the output buffer --- it will be released when done with image */ + dest->buffer = (unsigned char *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, OUTPUT_BUF_SIZE * sizeof (unsigned char)); - dest->pub.next_output_byte = dest->buffer; - dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; + dest->pub.next_output_byte = dest->buffer; + dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; } @@ -780,16 +634,16 @@ safeboolean empty_output_buffer (j_compress_ptr cinfo) { - my_dest_ptr dest = (my_dest_ptr) cinfo->dest; + my_dest_ptr dest = (my_dest_ptr) cinfo->dest; - if (gdPutBuf (dest->buffer, OUTPUT_BUF_SIZE, dest->outfile) != - (size_t) OUTPUT_BUF_SIZE) - ERREXIT (cinfo, JERR_FILE_WRITE); + if (gdPutBuf (dest->buffer, OUTPUT_BUF_SIZE, dest->outfile) != (size_t) OUTPUT_BUF_SIZE) { + ERREXIT (cinfo, JERR_FILE_WRITE); + } - dest->pub.next_output_byte = dest->buffer; - dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; + dest->pub.next_output_byte = dest->buffer; + dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; - return TRUE; + return TRUE; } @@ -805,15 +659,13 @@ void term_destination (j_compress_ptr cinfo) { - my_dest_ptr dest = (my_dest_ptr) cinfo->dest; - size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer; + my_dest_ptr dest = (my_dest_ptr) cinfo->dest; + size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer; - /* Write any data remaining in the buffer */ - if (datacount > 0) - { - if ((size_t)gdPutBuf (dest->buffer, datacount, dest->outfile) != datacount) - ERREXIT (cinfo, JERR_FILE_WRITE); - } + /* Write any data remaining in the buffer */ + if (datacount > 0 && ((size_t)gdPutBuf (dest->buffer, datacount, dest->outfile) != datacount)) { + ERREXIT (cinfo, JERR_FILE_WRITE); + } } @@ -826,26 +678,23 @@ void jpeg_gdIOCtx_dest (j_compress_ptr cinfo, gdIOCtx * outfile) { - my_dest_ptr dest; + my_dest_ptr dest; + + /* The destination object is made permanent so that multiple JPEG images + * can be written to the same file without re-executing jpeg_stdio_dest. + * This makes it dangerous to use this manager and a different destination + * manager serially with the same JPEG object, because their private object + * sizes may be different. Caveat programmer. + */ + if (cinfo->dest == NULL) { /* first time for this JPEG object? */ + cinfo->dest = (struct jpeg_destination_mgr *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, sizeof (my_destination_mgr)); + } - /* The destination object is made permanent so that multiple JPEG images - * can be written to the same file without re-executing jpeg_stdio_dest. - * This makes it dangerous to use this manager and a different destination - * manager serially with the same JPEG object, because their private object - * sizes may be different. Caveat programmer. - */ - if (cinfo->dest == NULL) - { /* first time for this JPEG object? */ - cinfo->dest = (struct jpeg_destination_mgr *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, - sizeof (my_destination_mgr)); - } - - dest = (my_dest_ptr) cinfo->dest; - dest->pub.init_destination = init_destination; - dest->pub.empty_output_buffer = empty_output_buffer; - dest->pub.term_destination = term_destination; - dest->outfile = outfile; + dest = (my_dest_ptr) cinfo->dest; + dest->pub.init_destination = init_destination; + dest->pub.empty_output_buffer = empty_output_buffer; + dest->pub.term_destination = term_destination; + dest->outfile = outfile; } #endif /* HAVE_JPEG */ Index: php4/ext/gd/libgd/gd_png.c diff -u php4/ext/gd/libgd/gd_png.c:1.4.2.1 php4/ext/gd/libgd/gd_png.c:1.4.2.2 --- php4/ext/gd/libgd/gd_png.c:1.4.2.1 Wed Dec 4 12:28:55 2002 +++ php4/ext/gd/libgd/gd_png.c Wed Mar 5 11:04:20 2003 @@ -7,8 +7,8 @@ /* JCE: Arrange HAVE_LIBPNG so that it can be set in gd.h */ #ifdef HAVE_LIBPNG -#include "gdhelpers.h" #include "png.h" /* includes zlib.h and setjmp.h */ +#include "gdhelpers.h" #define TRUE 1 #define FALSE 0 @@ -59,15 +59,12 @@ * regardless of whether _BSD_SOURCE or anything else has (or has not) * been defined. */ - fprintf (stderr, "gd-png: fatal libpng error: %s\n", msg); - fflush (stderr); + 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 */ - fprintf (stderr, - "gd-png: EXTREMELY fatal error: jmpbuf unrecoverable; terminating.\n"); - fflush (stderr); + php_gd_error_ex(E_ERROR, "gd-png: EXTREMELY fatal error: jmpbuf unrecoverable; terminating.\n"); exit (99); } @@ -116,7 +113,7 @@ 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; @@ -127,7 +124,6 @@ png_bytepp row_pointers = NULL; gdImagePtr im = NULL; int i, j, *open = NULL; - png_uint_32 ui, uj; volatile int transparent = -1; volatile int palette_allocated = FALSE; @@ -149,14 +145,14 @@ #endif if (png_ptr == NULL) { - fprintf (stderr, "gd-png error: cannot allocate libpng main struct\n"); + 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) { - fprintf (stderr, "gd-png error: cannot allocate libpng info struct\n"); + php_gd_error("gd-png error: cannot allocate libpng info struct\n"); png_destroy_read_struct (&png_ptr, NULL, NULL); return NULL; } @@ -170,7 +166,7 @@ #ifndef PNG_SETJMP_NOT_SUPPORTED if (setjmp (gdPngJmpbufStruct.jmpbuf)) { - fprintf (stderr, "gd-png error: setjmp returns error condition\n"); + php_gd_error("gd-png error: setjmp returns error condition\n"); png_destroy_read_struct (&png_ptr, &info_ptr, NULL); return NULL; } @@ -194,7 +190,7 @@ } if (im == NULL) { - fprintf (stderr, "gd-png error: cannot allocate gdImage struct\n"); + 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); @@ -210,7 +206,7 @@ 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", + 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)) @@ -227,7 +223,7 @@ im->alpha[i] = gdAlphaMax - (trans[i] >> 1); if ((trans[i] == 0) && (firstZero)) { - transparent = i; + transparent = i; firstZero = 0; } } @@ -239,7 +235,7 @@ /* create a fake palette and check for single-shade transparency */ if ((palette = (png_colorp) gdMalloc (256 * sizeof (png_color))) == NULL) { - fprintf (stderr, "gd-png error: cannot allocate gray palette\n"); + php_gd_error("gd-png error: cannot allocate gray palette\n"); png_destroy_read_struct (&png_ptr, &info_ptr, NULL); return NULL; } @@ -307,22 +303,22 @@ rowbytes = png_get_rowbytes (png_ptr, info_ptr); if ((image_data = (png_bytep) gdMalloc (rowbytes * height)) == NULL) { - fprintf (stderr, "gd-png error: cannot allocate image data\n"); + 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) { - fprintf (stderr, "gd-png error: cannot allocate row pointers\n"); + 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; } /* set the individual row_pointers to point at the correct offsets */ - for (uj = 0; uj < height; ++uj) + for (h = 0; h < height; ++h) { - row_pointers[uj] = image_data + uj * rowbytes; + row_pointers[h] = image_data + h * rowbytes; } png_read_image (png_ptr, row_pointers); /* read whole image... */ @@ -353,44 +349,44 @@ switch (color_type) { case PNG_COLOR_TYPE_RGB: - for (uj = 0; uj < height; uj++) + for (h = 0; h < height; h++) { int boffset = 0; - for (ui = 0; ui < width; ui++) + for (w = 0; w < width; w++) { - register png_byte r = row_pointers[uj][boffset++]; - register png_byte g = row_pointers[uj][boffset++]; - register png_byte b = row_pointers[uj][boffset++]; - im->tpixels[uj][ui] = gdTrueColor (r, g, b); + 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 (uj = 0; uj < height; uj++) + for (h = 0; h < height; h++) { int boffset = 0; - for (ui = 0; ui < width; ui++) + for (w = 0; w < width; w++) { - register png_byte r = row_pointers[uj][boffset++]; - register png_byte g = row_pointers[uj][boffset++]; - register png_byte b = row_pointers[uj][boffset++]; + 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[uj][boffset++] >> 1); - im->tpixels[uj][ui] = gdTrueColorAlpha (r, g, b, a); + (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 (uj = 0; uj < height; ++uj) + for (h = 0; h < height; ++h) { - for (ui = 0; ui < width; ++ui) + for (w = 0; w < width; ++w) { - register png_byte idx = row_pointers[uj][ui]; - im->pixels[uj][ui] = idx; + register png_byte idx = row_pointers[h][w]; + im->pixels[h][w] = idx; open[idx] = 0; } } @@ -402,7 +398,7 @@ { if (!open[i]) { - fprintf (stderr, "gd-png warning: image data references out-of-range" + php_gd_error("gd-png warning: image data references out-of-range" " color index (%d)\n", i); } } @@ -467,14 +463,14 @@ #endif if (png_ptr == NULL) { - fprintf (stderr, "gd-png error: cannot allocate libpng main struct\n"); + 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) { - fprintf (stderr, "gd-png error: cannot allocate libpng info struct\n"); + php_gd_error("gd-png error: cannot allocate libpng info struct\n"); png_destroy_write_struct (&png_ptr, (png_infopp) NULL); return; } @@ -482,7 +478,7 @@ #ifndef PNG_SETJMP_NOT_SUPPORTED if (setjmp (gdPngJmpbufStruct.jmpbuf)) { - fprintf (stderr, "gd-png error: setjmp returns error condition\n"); + php_gd_error("gd-png error: setjmp returns error condition\n"); png_destroy_write_struct (&png_ptr, &info_ptr); return; } @@ -565,9 +561,10 @@ } if (im->trueColor && (!im->saveAlphaFlag) && (transparent >= 0)) { - trans_rgb_value.red = gdTrueColorGetRed (im->trueColor); - trans_rgb_value.green = gdTrueColorGetGreen (im->trueColor); - trans_rgb_value.blue = gdTrueColorGetBlue (im->trueColor); + /* 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) @@ -596,7 +593,7 @@ { trans_values[i] = 255 - ((im->alpha[i] << 1) + - (im->alpha[i] >> 7)); + (im->alpha[i] >> 6)); } png_set_tRNS (png_ptr, info_ptr, trans_values, 256, NULL); #endif @@ -615,9 +612,10 @@ { 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] >> 7)); + (im->alpha[i] >> 6)); mapping[i] = j++; } else @@ -670,20 +668,10 @@ /* Our little 7-bit alpha channel trick costs us a bit here. */ png_bytep *row_pointers; row_pointers = gdMalloc (sizeof (png_bytep) * height); - if (row_pointers == NULL) - { - fprintf (stderr, "gd-png error: unable to allocate row_pointers\n"); - } for (j = 0; j < height; ++j) { int bo = 0; - if ((row_pointers[j] = (png_bytep) gdMalloc (width * channels)) == NULL) - { - fprintf (stderr, "gd-png error: unable to allocate rows\n"); - for (i = 0; i < j; ++i) - gdFree (row_pointers[i]); - return; - } + row_pointers[j] = (png_bytep) gdMalloc (width * channels); for (i = 0; i < width; ++i) { unsigned char a; @@ -698,7 +686,8 @@ 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]); - row_pointers[j][bo++] = 255 - ((a << 1) + (a >> 7)); + /* Andrew Hull: >> 6, not >> 7! (gd 2.0.5) */ + row_pointers[j][bo++] = 255 - ((a << 1) + (a >> 6)); } } } Index: php4/ext/gd/libgd/gd_ss.c diff -u php4/ext/gd/libgd/gd_ss.c:1.2 php4/ext/gd/libgd/gd_ss.c:1.2.2.1 --- php4/ext/gd/libgd/gd_ss.c:1.2 Tue Oct 29 18:08:01 2002 +++ php4/ext/gd/libgd/gd_ss.c Wed Mar 5 11:04:20 2003 @@ -41,12 +41,12 @@ void gdImagePngToSink (gdImagePtr im, gdSinkPtr outSink) { - fprintf(stderr,"PNG support is not available\n"); + php_gd_error("PNG support is not available\n"); } gdImagePtr gdImageCreateFromPngSource (gdSourcePtr inSource) { - fprintf(stderr,"PNG support is not available\n"); + php_gd_error("PNG support is not available\n"); return NULL; } #endif /* HAVE_LIBPNG */ Index: php4/ext/gd/libgd/gd_topal.c diff -u php4/ext/gd/libgd/gd_topal.c:1.8.2.1 php4/ext/gd/libgd/gd_topal.c:1.8.2.2 --- php4/ext/gd/libgd/gd_topal.c:1.8.2.1 Wed Dec 4 12:28:55 2002 +++ php4/ext/gd/libgd/gd_topal.c Wed Mar 5 11:04:20 2003 @@ -1626,7 +1626,7 @@ return -3; /* the images are meant to be the same dimensions */ } - buf = (unsigned long *)malloc( sizeof(unsigned long) * 5 * im2->colorsTotal ); + buf = (unsigned long *)gdMalloc( sizeof(unsigned long) * 5 * im2->colorsTotal ); memset( buf, 0, sizeof(unsigned long) * 5 * im2->colorsTotal ); for( x=0; x<im1->sx; x++ ) { @@ -1653,6 +1653,6 @@ bp += 4; } } - free(buf); + gdFree(buf); return 0; } Index: php4/ext/gd/libgd/gd_wbmp.c diff -u php4/ext/gd/libgd/gd_wbmp.c:1.3 php4/ext/gd/libgd/gd_wbmp.c:1.3.2.1 --- php4/ext/gd/libgd/gd_wbmp.c:1.3 Tue Oct 29 18:08:01 2002 +++ php4/ext/gd/libgd/gd_wbmp.c Wed Mar 5 11:04:20 2003 @@ -70,7 +70,7 @@ void gd_putout (int i, void *out) { - gdPutC ((unsigned char)i, (gdIOCtx *) out); + gdPutC (i, (gdIOCtx *) out); } @@ -105,7 +105,7 @@ /* create the WBMP */ if ((wbmp = createwbmp (gdImageSX (image), gdImageSY (image), WBMP_WHITE)) == NULL) - fprintf (stderr, "Could not create WBMP\n"); + php_gd_error("Could not create WBMP\n"); /* fill up the WBMP structure */ pos = 0; @@ -123,7 +123,7 @@ /* write the WBMP to a gd file descriptor */ if (writewbmp (wbmp, &gd_putout, out)) - fprintf (stderr, "Could not save WBMP\n"); + php_gd_error("Could not save WBMP\n"); /* des submitted this bugfix: gdFree the memory. */ freewbmp (wbmp); } Index: php4/ext/gd/libgd/gdcache.c diff -u php4/ext/gd/libgd/gdcache.c:1.1 php4/ext/gd/libgd/gdcache.c:1.1.4.1 --- php4/ext/gd/libgd/gdcache.c:1.1 Fri Apr 12 22:03:08 2002 +++ php4/ext/gd/libgd/gdcache.c Wed Mar 5 11:04:20 2003 @@ -66,7 +66,7 @@ { gdCache_head_t *head; - head = (gdCache_head_t *) gdMalloc (sizeof (gdCache_head_t)); + head = (gdCache_head_t *) gdPMalloc(sizeof (gdCache_head_t)); head->mru = NULL; head->size = size; head->gdCacheTest = gdCacheTest; @@ -86,9 +86,9 @@ (*(head->gdCacheRelease)) (elem->userdata); prev = elem; elem = elem->next; - gdFree ((char *) prev); + gdPFree ((char *) prev); } - gdFree ((char *) head); + gdPFree ((char *) head); } void * @@ -125,7 +125,7 @@ } if (i < head->size) { /* cache still growing - add new elem */ - elem = (gdCache_element_t *) gdMalloc (sizeof (gdCache_element_t)); + elem = (gdCache_element_t *) gdPMalloc(sizeof (gdCache_element_t)); } else { /* cache full - replace least-recently-used */ Index: php4/ext/gd/libgd/gdft.c diff -u php4/ext/gd/libgd/gdft.c:1.11.2.4 php4/ext/gd/libgd/gdft.c:1.11.2.5 --- php4/ext/gd/libgd/gdft.c:1.11.2.4 Sun Jan 5 19:47:47 2003 +++ php4/ext/gd/libgd/gdft.c Wed Mar 5 11:04:20 2003 @@ -19,25 +19,38 @@ #endif #ifdef WIN32 -extern int access(const char *pathname, int mode); +#define access _access #ifndef R_OK #define R_OK 2 #endif #endif /* number of antialised colors for indexed bitmaps */ +/* overwrite Windows GDI define in case of windows build */ +#ifdef NUMCOLORS +#undef NUMCOLORS +#endif #define NUMCOLORS 8 char * gdImageStringTTF (gdImage * im, int *brect, int fg, char *fontlist, double ptsize, double angle, int x, int y, char *string) { + /* 2.0.6: valid return */ return gdImageStringFT (im, brect, fg, fontlist, ptsize, angle, x, y, string); } #ifndef HAVE_LIBFREETYPE char * +gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist, + double ptsize, double angle, int x, int y, char *string, + gdFTStringExtraPtr strex) +{ + return "libgd was not built with FreeType font support\n"; +} + +char * gdImageStringFT (gdImage * im, int *brect, int fg, char *fontlist, double ptsize, double angle, int x, int y, char *string) { @@ -86,8 +99,13 @@ #define TRUE !FALSE #endif +#ifndef MAX #define MAX(a,b) ((a)>(b)?(a):(b)) +#endif + +#ifndef MIN #define MIN(a,b) ((a)<(b)?(a):(b)) +#endif typedef struct { @@ -330,159 +348,161 @@ return (strcmp (a->fontlist, b->fontlist) == 0); } -static void * -fontFetch (char **error, void *key) +static void *fontFetch (char **error, void *key) { - font_t *a; - fontkey_t *b = (fontkey_t *) key; - int n; - int font_found = 0; - unsigned short platform, encoding; - char *fontsearchpath, *fontlist; - char *fullname = NULL; - char *name, *path, *dir; - char *strtok_ptr; - FT_Error err; - FT_CharMap found = 0; - FT_CharMap charmap; - - a = (font_t *) gdMalloc (sizeof (font_t)); - a->fontlist = strdup (b->fontlist); - a->library = b->library; - - /* - * Search the pathlist for any of a list of font names. - */ - fontsearchpath = getenv ("GDFONTPATH"); - if (!fontsearchpath) - fontsearchpath = DEFAULT_FONTPATH; - fontlist = strdup (a->fontlist); - - /* - * Must use gd_strtok_r else pointer corrupted by strtok in nested loop. - */ - for (name = gd_strtok_r (fontlist, LISTSEPARATOR, &strtok_ptr); name; - name = gd_strtok_r (0, LISTSEPARATOR, &strtok_ptr)) - { - - /* make a fresh copy each time - strtok corrupts it. */ - path = strdup (fontsearchpath); - /* - * Allocate an oversized buffer that is guaranteed to be - * big enough for all paths to be tested. - */ - fullname = gdRealloc (fullname, - strlen (fontsearchpath) + strlen (name) + 6); - /* if name is an absolute filename then test directly */ - if (*name == '/' || (name[0] != 0 && name[1] == ':' && (name[2] == '/' || name[2] == '\\'))) - { - sprintf (fullname, "%s", name); - if (access (fullname, R_OK) == 0) - { - font_found++; - break; - } - } - for (dir = strtok (path, PATHSEPARATOR); dir; - dir = strtok (0, PATHSEPARATOR)) - { - sprintf (fullname, "%s/%s", dir, name); - if (access (fullname, R_OK) == 0) - { - font_found++; - break; - } - sprintf (fullname, "%s/%s.ttf", dir, name); - if (access (fullname, R_OK) == 0) - { - font_found++; - break; - } - sprintf (fullname, "%s/%s.pfa", dir, name); - if (access (fullname, R_OK) == 0) - { - font_found++; - break; - } - sprintf (fullname, "%s/%s.pfb", dir, name); - if (access (fullname, R_OK) == 0) - { - font_found++; - break; - } + font_t *a; + fontkey_t *b = (fontkey_t *) key; + int n; + int font_found = 0; + unsigned short platform, encoding; + char *fontsearchpath, *fontlist; + char *fullname = NULL; + char *name, *path=NULL, *dir; + char *strtok_ptr; + FT_Error err; + FT_CharMap found = 0; + FT_CharMap charmap; + + a = (font_t *) gdPMalloc(sizeof(font_t)); + a->fontlist = gdPEstrdup(b->fontlist); + a->library = b->library; + + /* + * Search the pathlist for any of a list of font names. + */ + fontsearchpath = getenv ("GDFONTPATH"); + if (!fontsearchpath) { + fontsearchpath = DEFAULT_FONTPATH; + } + fontlist = gdEstrdup(a->fontlist); + + /* + * Must use gd_strtok_r else pointer corrupted by strtok in nested loop. + */ + for (name = gd_strtok_r (fontlist, LISTSEPARATOR, &strtok_ptr); name; name = gd_strtok_r (0, LISTSEPARATOR, &strtok_ptr)) { + /* make a fresh copy each time - strtok corrupts it. */ + path = gdEstrdup (fontsearchpath); + + /* + * Allocate an oversized buffer that is guaranteed to be + * big enough for all paths to be tested. + */ + fullname = gdRealloc (fullname, strlen (fontsearchpath) + strlen (name) + 6); + + /* if name is an absolute filename then test directly */ + if (*name == '/' || (name[0] != 0 && name[1] == ':' && (name[2] == '/' || name[2] == '\\'))) { + sprintf(fullname, "%s", name); + if (access(fullname, R_OK) == 0) { + font_found++; + break; + } + } + for (dir = strtok (path, PATHSEPARATOR); dir; dir = strtok (0, PATHSEPARATOR)) { + sprintf(fullname, "%s/%s", dir, name); + if (access (fullname, R_OK) == 0) { + font_found++; + break; + } + sprintf(fullname, "%s/%s.ttf", dir, name); + if (access (fullname, R_OK) == 0) { + font_found++; + break; + } + sprintf(fullname, "%s/%s.pfa", dir, name); + if (access(fullname, R_OK) == 0) { + font_found++; + break; + } + sprintf (fullname, "%s/%s.pfb", dir, name); + if (access(fullname, R_OK) == 0) { + font_found++; + break; + } + } + gdFree(path); + path = NULL; + if (font_found) { + break; + } + } + + if (path) { + gdFree(path); + } + + gdFree(fontlist); + + if (!font_found) { + gdPFree(a->fontlist); + gdPFree(a); + if (fullname) { + gdFree(fullname); + } + *error = "Could not find/open font"; + return NULL; } - gdFree (path); - if (font_found) - break; - } - gdFree (fontlist); - if (!font_found) - { - *error = "Could not find/open font"; - return NULL; - } - err = FT_New_Face (*b->library, fullname, 0, &a->face); - if (err) - { - *error = "Could not read font"; - return NULL; - } - gdFree (fullname); + err = FT_New_Face (*b->library, fullname, 0, &a->face); + if (err) { + gdPFree(a->fontlist); + gdPFree(a); + if (fullname) { + gdFree(fullname); + } + *error = "Could not read font"; + return NULL; + } + gdFree(fullname); -/* FIXME - This mapping stuff is imcomplete - where is the spec? */ + /* FIXME - This mapping stuff is imcomplete - where is the spec? */ - a->have_char_map_unicode = 0; - a->have_char_map_big5 = 0; - a->have_char_map_sjis = 0; - a->have_char_map_apple_roman = 0; - for (n = 0; n < a->face->num_charmaps; n++) - { - charmap = a->face->charmaps[n]; - platform = charmap->platform_id; - encoding = charmap->encoding_id; - if ((platform == 3 && encoding == 1) /* Windows Unicode */ - || (platform == 3 && encoding == 0) /* Windows Symbol */ - || (platform == 2 && encoding == 1) /* ISO Unicode */ - || (platform == 0)) - { /* Apple Unicode */ - a->have_char_map_unicode = 1; - found = charmap; - } - else if (platform == 3 && encoding == 4) - { /* Windows Big5 */ - a->have_char_map_big5 = 1; - found = charmap; - } - else if (platform == 3 && encoding == 2) - { /* Windows Sjis */ - a->have_char_map_sjis = 1; - found = charmap; + a->have_char_map_unicode = 0; + a->have_char_map_big5 = 0; + a->have_char_map_sjis = 0; + a->have_char_map_apple_roman = 0; + for (n = 0; n < a->face->num_charmaps; n++) { + charmap = a->face->charmaps[n]; + platform = charmap->platform_id; + encoding = charmap->encoding_id; + if ((platform == 3 && encoding == 1) /* Windows Unicode */ + || (platform == 3 && encoding == 0) /* Windows Symbol */ + || (platform == 2 && encoding == 1) /* ISO Unicode */ + || (platform == 0)) + { /* Apple Unicode */ + a->have_char_map_unicode = 1; + found = charmap; + } else if (platform == 3 && encoding == 4) { /* Windows Big5 */ + a->have_char_map_big5 = 1; + found = charmap; + } else if (platform == 3 && encoding == 2) { /* Windows Sjis */ + a->have_char_map_sjis = 1; + found = charmap; + } else if ((platform == 1 && encoding == 0) /* Apple Roman */ + || (platform == 2 && encoding == 0)) + { /* ISO ASCII */ + a->have_char_map_apple_roman = 1; + found = charmap; + } } - else if ((platform == 1 && encoding == 0) /* Apple Roman */ - || (platform == 2 && encoding == 0)) - { /* ISO ASCII */ - a->have_char_map_apple_roman = 1; - found = charmap; + if (!found) { + gdPFree(a->fontlist); + gdPFree(a); + *error = "Unable to find a CharMap that I can handle"; + return NULL; } - } - if (!found) - { - *error = "Unable to find a CharMap that I can handle"; - return NULL; - } - return (void *) a; + /* 2.0.5: we should actually return this */ + a->face->charmap = found; + return (void *) a; } -static void -fontRelease (void *element) +static void fontRelease (void *element) { - font_t *a = (font_t *) element; + font_t *a = (font_t *) element; - FT_Done_Face (a->face); - gdFree (a->fontlist); - gdFree ((char *) element); + FT_Done_Face (a->face); + gdPFree(a->fontlist); + gdPFree((char *) element); } /********************************************************************/ @@ -570,7 +590,7 @@ { unsigned char *pixel = NULL; int *tpixel = NULL; - int x, y, row, col, pc; + int x, y, row, col, pc, pcr; tweencolor_t *tc_elem; tweencolorkey_t tc_key; @@ -584,6 +604,7 @@ for (row = 0; row < bitmap.rows; row++) { pc = row * bitmap.pitch; + pcr = pc; y = pen_y + row; /* clip if out of bounds */ if (y >= im->sy || y < 0) @@ -602,17 +623,20 @@ } else if (bitmap.pixel_mode == ft_pixel_mode_mono) { - level = ((bitmap.buffer[pc / 8] - << (pc % 8)) & 128) ? gdAlphaOpaque : - gdAlphaTransparent; + /* 2.0.5: mode_mono fix from Giuliano Pochini */ + level = ((bitmap.buffer[(col>>3)+pcr]) & (1<<(~col&0x07))) + ? gdAlphaTransparent : + gdAlphaOpaque; } else { return "Unsupported ft_pixel_mode"; } - if (fg >= 0) { + if ((fg >= 0) && (im->trueColor)) { /* Consider alpha in the foreground color itself to be an - upper bound on how opaque things get */ + upper bound on how opaque things get, when truecolor is + available. Without truecolor this results in far too many + color indexes. */ level = level * (gdAlphaMax - gdTrueColorGetAlpha(fg)) / gdAlphaMax; } level = gdAlphaMax - level; @@ -640,7 +664,9 @@ /* Non-truecolor case, restored to its more or less original form */ for (row = 0; row < bitmap.rows; row++) { + int pcr; pc = row * bitmap.pitch; + pcr = pc; if(bitmap.pixel_mode==ft_pixel_mode_mono) pc *= 8; /* pc is measured in bits for monochrome images */ @@ -667,6 +693,9 @@ { tc_key.pixel = ((bitmap.buffer[pc / 8] << (pc % 8)) & 128) ? NUMCOLORS : 0; + /* 2.0.5: mode_mono fix from Giuliano Pochini */ + tc_key.pixel = ((bitmap.buffer[(col>>3)+pcr]) & (1<<(~col&0x07))) + ? NUMCOLORS : 0; } else { @@ -729,17 +758,19 @@ /********************************************************************/ /* gdImageStringFT - render a utf8 string onto a gd image */ + char * gdImageStringFT (gdImage * im, int *brect, int fg, char *fontlist, - double ptsize, double angle, int x, int y, char *string) + double ptsize, double angle, int x, int y, char *string) { - return gdImageStringFTEx(im, brect, fg, fontlist, ptsize, angle, x, y, string, NULL); + return gdImageStringFTEx(im, brect, fg, fontlist, + ptsize, angle, x, y, string, 0); } char * gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist, double ptsize, double angle, int x, int y, char *string, - gdFTStringExtra * strex) + gdFTStringExtraPtr strex) { FT_BBox bbox, glyph_bbox; FT_Matrix matrix; @@ -761,10 +792,9 @@ int render = (im && (im->trueColor || (fg <= 255 && fg >= -255))); FT_BitmapGlyph bm; int render_mode = FT_LOAD_RENDER | FT_LOAD_FORCE_AUTOHINT; - - /* fine tuning */ + /* Now tuneable thanks to Wez Furlong */ double linespace = LINESPACE; - + /* 2.0.6: put this declaration with the other declarations! */ /* * make a new tweenColorCache on every call * because caching colormappings between calls @@ -774,6 +804,11 @@ */ gdCache_head_t *tc_cache; + if (strex) { + if ((strex->flags & gdFTEX_LINESPACE) == gdFTEX_LINESPACE) { + linespace = strex->linespacing; + } + } tc_cache = gdCacheCreate( TWEENCOLORCACHESIZE, tweenColorTest, tweenColorFetch, tweenColorRelease ); @@ -810,12 +845,6 @@ return "Could not set character size"; } - /* pull in supplied extended settings */ - if (strex) { - if ((strex->flags & gdFTEX_LINESPACE) == gdFTEX_LINESPACE) - linespace = strex->linespacing; - } - matrix.xx = (FT_Fixed) (cos_a * (1 << 16)); matrix.yx = (FT_Fixed) (sin_a * (1 << 16)); matrix.xy = -matrix.yx; @@ -860,8 +889,8 @@ if (ch == '\r') { penf.x = 0; - x1 = (int)((penf.x * cos_a - penf.y * sin_a + 32.0) / 64.0); - y1 = (int)((penf.x * sin_a + penf.y * cos_a + 32.0) / 64.0); + x1 = (int)(penf.x * cos_a - penf.y * sin_a + 32) / 64; + y1 = (int)(penf.x * sin_a + penf.y * cos_a + 32) / 64; pen.x = pen.y = 0; previous = 0; /* clear kerning flag */ next++; @@ -870,10 +899,10 @@ /* newlines */ if (ch == '\n') { - penf.y = penf.y - (int)(face->size->metrics.height * LINESPACE); + penf.y -= (long)(face->size->metrics.height * linespace); penf.y = (penf.y - 32) & -64; /* round to next pixel row */ - x1 = (int)((penf.x * cos_a - penf.y * sin_a + 32.0) / 64.0); - y1 = (int)((penf.x * sin_a + penf.y * cos_a + 32.0) / 64.0); + x1 = (int)(penf.x * cos_a - penf.y * sin_a + 32) / 64; + y1 = (int)(penf.x * sin_a + penf.y * cos_a + 32) / 64; pen.x = pen.y = 0; previous = 0; /* clear kerning flag */ next++; @@ -936,10 +965,8 @@ next++; } } - /* set rotation transform */ FT_Set_Transform(face, &matrix, NULL); - /* Convert character code to glyph index */ glyph_index = FT_Get_Char_Index (face, ch); Index: php4/ext/gd/libgd/gdhelpers.c diff -u php4/ext/gd/libgd/gdhelpers.c:1.3.2.2 php4/ext/gd/libgd/gdhelpers.c:1.3.2.3 --- php4/ext/gd/libgd/gdhelpers.c:1.3.2.2 Mon Nov 18 08:00:52 2002 +++ php4/ext/gd/libgd/gdhelpers.c Wed Mar 5 11:04:20 2003 @@ -2,8 +2,6 @@ #include "config.h" #endif -#include "php.h" - #include "gd.h" #include "gdhelpers.h" #include <stdlib.h> @@ -75,28 +73,4 @@ /* 5. Return token */ *state = s; return result; -} - -void * -gdCalloc (size_t nmemb, size_t size) -{ - return calloc (nmemb, size); -} - -void * -gdMalloc (size_t size) -{ - return malloc (size); -} - -void * -gdRealloc (void *ptr, size_t size) -{ - return realloc (ptr, size); -} - -void -gdFree (void *ptr) -{ - free (ptr); } Index: php4/ext/gd/libgd/gdhelpers.h diff -u php4/ext/gd/libgd/gdhelpers.h:1.2.2.1 php4/ext/gd/libgd/gdhelpers.h:1.2.2.2 --- php4/ext/gd/libgd/gdhelpers.h:1.2.2.1 Sun Nov 17 14:40:38 2002 +++ php4/ext/gd/libgd/gdhelpers.h Wed Mar 5 11:04:20 2003 @@ -2,6 +2,7 @@ #define GDHELPERS_H 1 #include <sys/types.h> +#include "php.h" /* TBB: strtok_r is not universal; provide an implementation of it. */ @@ -11,10 +12,14 @@ in gd.h, where callers can utilize it to correctly free memory allocated by these functions with the right version of free(). */ -void *gdCalloc(size_t nmemb, size_t size); -void *gdMalloc(size_t size); -void *gdRealloc(void *ptr, size_t size); -char *gdEstrdup(const char *ptr); +#define gdCalloc(nmemb, size) ecalloc(nmemb, size) +#define gdMalloc(size) emalloc(size) +#define gdRealloc(ptr, size) erealloc(ptr, size) +#define gdEstrdup(ptr) estrdup(ptr) +#define gdFree(ptr) efree(ptr) +#define gdPMalloc(ptr) pemalloc(ptr, 1) +#define gdPFree(ptr) pefree(ptr, 1) +#define gdPEstrdup(ptr) pestrdup(ptr, 1) #endif /* GDHELPERS_H */ Index: php4/ext/gd/libgd/gdkanji.c diff -u php4/ext/gd/libgd/gdkanji.c:1.2 php4/ext/gd/libgd/gdkanji.c:1.2.2.1 --- php4/ext/gd/libgd/gdkanji.c:1.2 Tue Oct 29 18:08:01 2002 +++ php4/ext/gd/libgd/gdkanji.c Wed Mar 5 11:04:20 2003 @@ -72,13 +72,15 @@ static void error (const char *format,...) { - va_list args; - - va_start (args, format); - fprintf (stderr, "%s: ", LIBNAME); - vfprintf (stderr, format, args); - fprintf (stderr, "\n"); - va_end (args); + va_list args; + char *tmp; + TSRMLS_FETCH(); + + va_start(args, format); + vspprintf(&tmp, 0, format, args); + va_end(args); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s: %s", LIBNAME, tmp); + efree(tmp); } /* DetectKanjiCode() derived from DetectCodeType() by Ken Lunde. */ Index: php4/ext/gd/libgd/gdxpm.c diff -u php4/ext/gd/libgd/gdxpm.c:1.2.2.1 php4/ext/gd/libgd/gdxpm.c:1.2.2.2 --- php4/ext/gd/libgd/gdxpm.c:1.2.2.1 Mon Nov 25 18:12:15 2002 +++ php4/ext/gd/libgd/gdxpm.c Wed Mar 5 11:04:20 2003 @@ -7,21 +7,13 @@ */ #include <stdio.h> #include <stdlib.h> +#include <string.h> #include "gd.h" #include "gdhelpers.h" -#ifndef HAVE_XPM -gdImagePtr -gdImageCreateFromXpm (char *filename) -{ - fprintf (stderr, "libgd was not built with xpm support\n"); - return (NULL); -} - -#else +#ifdef HAVE_XPM #include <X11/xpm.h> -#include <string.h> gdImagePtr gdImageCreateFromXpm (char *filename) @@ -46,8 +38,6 @@ number = image.ncolors; colors = (int *) gdMalloc (sizeof (int) * number); - if (colors == NULL) - return (0); for (i = 0; i < number; i++) { switch (strlen (image.colorTable[i].c_color)) @@ -125,15 +115,13 @@ colors[i] = gdImageColorResolve (im, red, green, blue); if (colors[i] == -1) - fprintf (stderr, "ARRRGH\n"); + php_gd_error("ARRRGH\n"); } apixel = (char *) gdMalloc (image.cpp + 1); - if (apixel == NULL) - return (0); apixel[image.cpp] = '\0'; - pointer = image.data; + pointer = (int *) image.data; for (i = 0; i < image.height; i++) { for (j = 0; j < image.width; j++)
Index: php4/ext/gd/gd.c diff -u php4/ext/gd/gd.c:1.221.2.13 php4/ext/gd/gd.c:1.221.2.14 --- php4/ext/gd/gd.c:1.221.2.13 Fri Feb 28 20:15:32 2003 +++ php4/ext/gd/gd.c Wed Mar 5 11:04:20 2003 @@ -18,7 +18,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: gd.c,v 1.221.2.13 2003/03/01 01:15:32 pajoye Exp $ */ +/* $Id: gd.c,v 1.221.2.14 2003/03/05 16:04:20 iliaa Exp $ */ /* gd 1.2 is copyright 1994, 1995, Quest Protein Database Center, Cold Spring Harbor Labs. */ @@ -122,12 +122,12 @@ PHP_FE(imageellipse, NULL) PHP_FE(imagechar, NULL) PHP_FE(imagecharup, NULL) + PHP_FE(imagecolorat, NULL) PHP_FE(imagecolorallocate, NULL) #if HAVE_LIBGD15 PHP_FE(imagepalettecopy, NULL) PHP_FE(imagecreatefromstring, NULL) #endif - PHP_FE(imagecolorat, NULL) PHP_FE(imagecolorclosest, NULL) #if HAVE_COLORCLOSESTHWB PHP_FE(imagecolorclosesthwb, NULL) @@ -148,13 +148,14 @@ PHP_FE(imagecreate, NULL) #if HAVE_LIBGD20 PHP_FE(imagecreatetruecolor, NULL) - PHP_FE(imageistruecolor, NULL) + PHP_FE(imageistruecolor, NULL) PHP_FE(imagetruecolortopalette, NULL) PHP_FE(imagesetthickness, NULL) PHP_FE(imagefilledarc, NULL) PHP_FE(imagefilledellipse, NULL) PHP_FE(imagealphablending, NULL) - PHP_FE(imagesavealpha, NULL) + PHP_FE(imagesavealpha, NULL) + PHP_FE(imagecolorallocatealpha, NULL) PHP_FE(imagecolorresolvealpha, NULL) PHP_FE(imagecolorclosestalpha, NULL) PHP_FE(imagecolorexactalpha, NULL) @@ -163,6 +164,7 @@ #ifdef HAVE_GD_BUNDLED PHP_FE(imagerotate, NULL) + PHP_FE(imageantialias, NULL) #endif #if HAVE_GD_IMAGESETTILE @@ -282,7 +284,7 @@ PHP_MINIT(gd), NULL, NULL, - NULL, + PHP_RSHUTDOWN(gd), PHP_MINFO(gd), NO_VERSION_YET, STANDARD_MODULE_PROPERTIES @@ -361,6 +363,17 @@ } /* }}} */ +/* {{{ PHP_RSHUTDOWN_FUNCTION + */ +PHP_RSHUTDOWN_FUNCTION(gd) +{ +#if HAVE_LIBGD20 && HAVE_GD_STRINGFT + gdFreeFontCache(); +#endif + return SUCCESS; +} +/* }}} */ + /* {{{ PHP_MINFO_FUNCTION */ PHP_MINFO_FUNCTION(gd) @@ -430,10 +443,8 @@ RETURN_FALSE; } - if (array_init(return_value) == FAILURE) { - php_error_docref(NULL TSRMLS_CC, E_ERROR, "Unable to initialize array"); - RETURN_FALSE; - } + array_init(return_value); + #if HAVE_GD_BUNDLED add_assoc_string(return_value, "GD Version", "bundled (2.0 compatible)", 1); #elif HAVE_LIBGD20 @@ -563,7 +574,7 @@ /* {{{ proto int imageloadfont(string filename) Load a new font */ -PHP_FUNCTION(imageloadfont) +PHP_FUNCTION(imageloadfont) { zval **file; int hdr_size = sizeof(gdFont) - sizeof(char *); @@ -591,7 +602,7 @@ * byte 8-11: (int) pixel width of each character * byte 12-15: (int) pixel height of each character * bytes 16-: (char) array with character data, one byte per pixel - * in each character, for a total of + * in each character, for a total of * (nchars*width*height) bytes. */ font = (gdFontPtr)emalloc(sizeof(gdFont)); @@ -673,7 +684,7 @@ stylearr = emalloc(sizeof(int) * zend_hash_num_elements(HASH_OF(*styles))); zend_hash_internal_pointer_reset_ex(HASH_OF(*styles), &pos); - + for (index=0;; zend_hash_move_forward_ex(HASH_OF(*styles), &pos)) { zval ** item; @@ -714,7 +725,7 @@ /* }}} */ /* {{{ proto int imageistruecolor(int im) - * return true if the image uses truecolor */ + return true if the image uses truecolor */ PHP_FUNCTION(imageistruecolor) { zval **IM; @@ -724,7 +735,7 @@ ZEND_WRONG_PARAM_COUNT(); } - ZEND_FETCH_RESOURCE(im, gdImagePtr, IM, -1, "Image", le_gd); + ZEND_FETCH_RESOURCE(im, gdImagePtr, IM, -1, "Image", le_gd); RETURN_BOOL(im->trueColor); } @@ -744,7 +755,7 @@ ZEND_FETCH_RESOURCE(im, gdImagePtr, IM, -1, "Image", le_gd); convert_to_boolean_ex(dither); convert_to_long_ex(ncolors); - + gdImageTrueColorToPalette(im, Z_LVAL_PP(dither), Z_LVAL_PP(ncolors)); RETURN_TRUE; @@ -802,7 +813,7 @@ ZEND_FETCH_RESOURCE(im, gdImagePtr, IM, -1, "Image", le_gd); convert_to_long_ex(thick); - + gdImageSetThickness(im, Z_LVAL_PP(thick)); RETURN_TRUE; @@ -819,7 +830,7 @@ if (ZEND_NUM_ARGS() != 6 || zend_get_parameters_ex(6, &IM, &cx, &cy, &w, &h, &color) == FAILURE) { ZEND_WRONG_PARAM_COUNT(); } - + ZEND_FETCH_RESOURCE(im, gdImagePtr, IM, -1, "Image", le_gd); convert_to_long_ex(cx); @@ -866,7 +877,7 @@ gdImageFilledArc(im, Z_LVAL_PP(cx), Z_LVAL_PP(cy), Z_LVAL_PP(w), Z_LVAL_PP(h), st, e, Z_LVAL_PP(col), Z_LVAL_PP(style)); RETURN_TRUE; } -/* }}} */ +/* }}} */ /* {{{ proto void imagealphablending(resource im, bool on) Turn alpha blending mode on or off for the given image */ @@ -881,7 +892,7 @@ ZEND_FETCH_RESOURCE(im, gdImagePtr, IM, -1, "Image", le_gd); convert_to_boolean_ex(blend); - + gdImageAlphaBlending(im, Z_LVAL_PP(blend)); RETURN_TRUE; @@ -890,22 +901,22 @@ #if HAVE_LIBGD20 /* {{{ proto void imagesavealpha(resource im, bool on) - * Include alpha channel to a saved image */ + Include alpha channel to a saved image */ PHP_FUNCTION(imagesavealpha) { - zval **IM, **save; - gdImagePtr im; + zval **IM, **save; + gdImagePtr im; - if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &IM, &save) == FAILURE) { - ZEND_WRONG_PARAM_COUNT(); - } + if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &IM, &save) == FAILURE) { + ZEND_WRONG_PARAM_COUNT(); + } - ZEND_FETCH_RESOURCE(im, gdImagePtr, IM, -1, "Image", le_gd); - convert_to_boolean_ex(save); + ZEND_FETCH_RESOURCE(im, gdImagePtr, IM, -1, "Image", le_gd); + convert_to_boolean_ex(save); - gdImageSaveAlpha(im, Z_LVAL_PP(save)); + gdImageSaveAlpha(im, Z_LVAL_PP(save)); - RETURN_TRUE; + RETURN_TRUE; } #endif @@ -931,6 +942,24 @@ /* }}} */ #endif +/* {{{ proto int imagecolorallocatealpha(resource im, int red, int green, int blue, int alpha) + Allocate a color with an alpha level. Works for true color and palette based images */ +PHP_FUNCTION(imagecolorallocatealpha) +{ + zval *IM; + int red, green, blue, alpha; + gdImagePtr im; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zllll", &IM, &red, &green, &blue, &alpha) == FAILURE) { + RETURN_FALSE; + } + + ZEND_FETCH_RESOURCE(im, gdImagePtr, &IM, -1, "Image", le_gd); + + RETURN_LONG(gdImageColorAllocateAlpha(im, red, green, blue, alpha)); +} +/* }}} */ + /* {{{ proto int imagecolorresolvealpha(resource im, int red, int green, int blue, int alpha) Resolve/Allocate a colour with an alpha level. Works for true colour and palette based images */ PHP_FUNCTION(imagecolorresolvealpha) @@ -941,7 +970,7 @@ if (ZEND_NUM_ARGS() != 5 || zend_get_parameters_ex(5, &IM, &red, &green, &blue, &alpha) == FAILURE) { ZEND_WRONG_PARAM_COUNT(); } - + ZEND_FETCH_RESOURCE(im, gdImagePtr, IM, -1, "Image", le_gd); convert_to_long_ex(red); @@ -963,7 +992,7 @@ if (ZEND_NUM_ARGS() != 5 || zend_get_parameters_ex(5, &IM, &red, &green, &blue, &alpha) == FAILURE) { ZEND_WRONG_PARAM_COUNT(); } - + ZEND_FETCH_RESOURCE(im, gdImagePtr, IM, -1, "Image", le_gd); convert_to_long_ex(red); @@ -985,14 +1014,14 @@ if (ZEND_NUM_ARGS() != 5 || zend_get_parameters_ex(5, &IM, &red, &green, &blue, &alpha) == FAILURE) { ZEND_WRONG_PARAM_COUNT(); } - + ZEND_FETCH_RESOURCE(im, gdImagePtr, IM, -1, "Image", le_gd); convert_to_long_ex(red); convert_to_long_ex(green); convert_to_long_ex(blue); convert_to_long_ex(alpha); - + RETURN_LONG(gdImageColorExactAlpha(im, Z_LVAL_PP(red), Z_LVAL_PP(green), Z_LVAL_PP(blue), Z_LVAL_PP(alpha))); } /* }}} */ @@ -1138,7 +1167,7 @@ Return the types of images supported in a bitfield - 1=GIF, 2=JPEG, 4=PNG, 8=WBMP, 16=XPM */ PHP_FUNCTION(imagetypes) { - int ret=0; + int ret=0; #ifdef HAVE_GD_GIF_CREATE ret = 1; #endif @@ -1151,7 +1180,7 @@ #ifdef HAVE_GD_WBMP ret |= 8; #endif -#ifdef HAVE_GD_XPM +#if defined(HAVE_GD_XPM) && defined(HAVE_GD_BUNDLED) ret |= 16; #endif if (ZEND_NUM_ARGS() != 0) { @@ -1194,15 +1223,15 @@ io_ctx->gd_free(io_ctx); #else io_ctx->free(io_ctx); -#endif +#endif return PHP_GDIMG_TYPE_WBM; } else { #if HAVE_LIBGD204 io_ctx->gd_free(io_ctx); #else io_ctx->free(io_ctx); -#endif - } +#endif + } } } #endif @@ -1211,7 +1240,7 @@ } /* }}} */ -#ifdef HAVE_LIBGD15 +#ifdef HAVE_LIBGD15 /* {{{ _php_image_create_from_string */ gdImagePtr _php_image_create_from_string(zval **data, char *tn, gdImagePtr (*ioctx_func_p)() TSRMLS_DC) @@ -1234,7 +1263,7 @@ io_ctx->gd_free(io_ctx); #else io_ctx->free(io_ctx); -#endif +#endif return im; } /* }}} */ @@ -1251,7 +1280,7 @@ if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &data) == FAILURE) { ZEND_WRONG_PARAM_COUNT(); } - + convert_to_string_ex(data); memcpy(sig, Z_STRVAL_PP(data), 8); @@ -1275,7 +1304,7 @@ RETURN_FALSE; #endif break; - + case PHP_GDIMG_TYPE_GIF: #ifdef HAVE_GD_GIF_READ im = _php_image_create_from_string (data, "GIF", gdImageCreateFromGifCtx TSRMLS_CC); @@ -1320,7 +1349,7 @@ /* {{{ _php_image_create_from */ -static void _php_image_create_from(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn, gdImagePtr (*func_p)(), gdImagePtr (*ioctx_func_p)()) +static void _php_image_create_from(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn, gdImagePtr (*func_p)(), gdImagePtr (*ioctx_func_p)()) { zval **file, **srcx, **srcy, **width, **height; gdImagePtr im = NULL; @@ -1328,19 +1357,19 @@ php_stream *stream; FILE * fp = NULL; int argc=ZEND_NUM_ARGS(); - + if ((image_type == PHP_GDIMG_TYPE_GD2PART && argc != 5) || - (image_type != PHP_GDIMG_TYPE_GD2PART && argc != 1) || + (image_type != PHP_GDIMG_TYPE_GD2PART && argc != 1) || zend_get_parameters_ex(argc, &file, &srcx, &srcy, &width, &height) == FAILURE) { ZEND_WRONG_PARAM_COUNT(); } - + convert_to_string_ex(file); if (argc == 5 && image_type == PHP_GDIMG_TYPE_GD2PART) { multi_convert_to_long_ex(4, srcx, srcy, width, height); } - + fn = Z_STRVAL_PP(file); stream = php_stream_open_wrapper(fn, "rb", REPORT_ERRORS|IGNORE_PATH|IGNORE_URL_WIN, NULL); @@ -1372,7 +1401,7 @@ php_error_docref(NULL TSRMLS_CC, E_WARNING,"Cannot read image data"); goto out_err; } - + io_ctx = gdNewDynamicCtx(buff_size, buff); if(!io_ctx) { php_error_docref(NULL TSRMLS_CC, E_WARNING,"Cannot allocate GD IO context"); @@ -1387,16 +1416,16 @@ io_ctx->gd_free(io_ctx); #else io_ctx->free(io_ctx); -#endif +#endif -#endif +#endif } else { /* try and force the stream to be FILE* */ if (FAILURE == php_stream_cast(stream, PHP_STREAM_AS_STDIO | PHP_STREAM_CAST_TRY_HARD, (void**)&fp, REPORT_ERRORS)) goto out_err; } - + if (!im && fp) { switch (image_type) { case PHP_GDIMG_TYPE_GD2PART: @@ -1517,19 +1546,20 @@ /* {{{ _php_image_output */ -static void _php_image_output(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn, void (*func_p)()) +static void _php_image_output(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn, void (*func_p)()) { - zval **imgind, **file, **quality; + zval **imgind, **file, **quality, **type; gdImagePtr im; char *fn = NULL; FILE *fp; int argc = ZEND_NUM_ARGS(); - int q = -1, i; + int q = -1, i, t = 1; /* The quality parameter for Wbmp stands for the threshold when called from image2wbmp() */ /* When called from imagewbmp() the quality parameter stands for the foreground color. Default: black. */ + /* The quality parameter for gd2 stands for chunk size */ - if (argc < 1 || argc > 3 || zend_get_parameters_ex(argc, &imgind, &file, &quality) == FAILURE) { + if (argc < 1 || argc > 4 || zend_get_parameters_ex(argc, &imgind, &file, &quality, &type) == FAILURE) { ZEND_WRONG_PARAM_COUNT(); } @@ -1542,6 +1572,10 @@ convert_to_long_ex(quality); q = Z_LVAL_PP(quality); } + if (argc == 4) { + convert_to_long_ex(type); + t = Z_LVAL_PP(type); + } } if ((argc == 2) || (argc == 3 && Z_STRLEN_PP(file))) { @@ -1555,7 +1589,7 @@ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to open '%s' for writing", fn); RETURN_FALSE; } - + switch(image_type) { case PHP_GDIMG_CONVERT_WBM: if(q<0||q>255) { @@ -1577,9 +1611,12 @@ } (*func_p)(im, fp); break; -#endif +#endif default: - (*func_p)(im, fp); + if (q == -1) { + q = 128; + } + (*func_p)(im, fp, q, t); break; } fflush(fp); @@ -1616,7 +1653,7 @@ } (*func_p)(im, tmp); break; -#endif +#endif default: (*func_p)(im, tmp); break; @@ -1706,7 +1743,7 @@ /* }}} */ #ifdef HAVE_GD_GD2 -/* {{{ proto int imagegd2(int im [, string filename]) +/* {{{ proto int imagegd2(int im [, string filename, [, int chunk_size, [, int type]]]) Output GD2 image to browser or file */ PHP_FUNCTION(imagegd2) { @@ -1734,6 +1771,7 @@ } /* }}} */ + /* {{{ proto int imagecolorallocate(int im, int red, int green, int blue) Allocate a color for an image */ PHP_FUNCTION(imagecolorallocate) @@ -1744,13 +1782,13 @@ if (ZEND_NUM_ARGS() != 4 || zend_get_parameters_ex(4, &IM, &red, &green, &blue) == FAILURE) { ZEND_WRONG_PARAM_COUNT(); } - + ZEND_FETCH_RESOURCE(im, gdImagePtr, IM, -1, "Image", le_gd); convert_to_long_ex(red); convert_to_long_ex(green); convert_to_long_ex(blue); - + RETURN_LONG(gdImageColorAllocate(im, Z_LVAL_PP(red), Z_LVAL_PP(green), Z_LVAL_PP(blue))); } /* }}} */ @@ -1766,7 +1804,7 @@ if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &dstim, &srcim) == FAILURE) { ZEND_WRONG_PARAM_COUNT(); } - + ZEND_FETCH_RESOURCE(dst, gdImagePtr, dstim, -1, "Image", le_gd); ZEND_FETCH_RESOURCE(src, gdImagePtr, srcim, -1, "Image", le_gd); @@ -1785,7 +1823,7 @@ if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &IM, &x, &y) == FAILURE) { ZEND_WRONG_PARAM_COUNT(); } - + ZEND_FETCH_RESOURCE(im, gdImagePtr, IM, -1, "Image", le_gd); convert_to_long_ex(x); @@ -1827,13 +1865,13 @@ if (ZEND_NUM_ARGS() != 4 || zend_get_parameters_ex(4, &IM, &red, &green, &blue) == FAILURE) { ZEND_WRONG_PARAM_COUNT(); } - + ZEND_FETCH_RESOURCE(im, gdImagePtr, IM, -1, "Image", le_gd); convert_to_long_ex(red); convert_to_long_ex(green); convert_to_long_ex(blue); - + RETURN_LONG(gdImageColorClosest(im, Z_LVAL_PP(red), Z_LVAL_PP(green), Z_LVAL_PP(blue))); } /* }}} */ @@ -1845,13 +1883,13 @@ { zval **IM, **red, **green, **blue; gdImagePtr im; - + if (ZEND_NUM_ARGS() != 4 || zend_get_parameters_ex(4, &IM, &red, &green, &blue) == FAILURE) { ZEND_WRONG_PARAM_COUNT(); } ZEND_FETCH_RESOURCE(im, gdImagePtr, IM, -1, "Image", le_gd); - + convert_to_long_ex(red); convert_to_long_ex(green); convert_to_long_ex(blue); @@ -1881,6 +1919,7 @@ RETURN_TRUE; } #endif + convert_to_long_ex(index); col = Z_LVAL_PP(index); @@ -1904,13 +1943,13 @@ if (ZEND_NUM_ARGS() != 4 || zend_get_parameters_ex(4, &IM, &red, &green, &blue) == FAILURE) { ZEND_WRONG_PARAM_COUNT(); } - + ZEND_FETCH_RESOURCE(im, gdImagePtr, IM, -1, "Image", le_gd); convert_to_long_ex(red); convert_to_long_ex(green); convert_to_long_ex(blue); - + RETURN_LONG(gdImageColorResolve(im, Z_LVAL_PP(red), Z_LVAL_PP(green), Z_LVAL_PP(blue))); } /* }}} */ @@ -1925,13 +1964,13 @@ if (ZEND_NUM_ARGS() != 4 || zend_get_parameters_ex(4, &IM, &red, &green, &blue) == FAILURE) { ZEND_WRONG_PARAM_COUNT(); } - + ZEND_FETCH_RESOURCE(im, gdImagePtr, IM, -1, "Image", le_gd); convert_to_long_ex(red); convert_to_long_ex(green); convert_to_long_ex(blue); - + RETURN_LONG(gdImageColorExact(im, Z_LVAL_PP(red), Z_LVAL_PP(green), Z_LVAL_PP(blue))); } /* }}} */ @@ -1947,16 +1986,16 @@ if (ZEND_NUM_ARGS() != 5 || zend_get_parameters_ex(5, &IM, &color, &red, &green, &blue) == FAILURE) { ZEND_WRONG_PARAM_COUNT(); } - + ZEND_FETCH_RESOURCE(im, gdImagePtr, IM, -1, "Image", le_gd); convert_to_long_ex(color); convert_to_long_ex(red); convert_to_long_ex(green); convert_to_long_ex(blue); - + col = Z_LVAL_PP(color); - + if (col >= 0 && col < gdImageColorsTotal(im)) { im->red[col] = Z_LVAL_PP(red); im->green[col] = Z_LVAL_PP(green); @@ -1978,26 +2017,24 @@ if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &IM, &index) == FAILURE) { ZEND_WRONG_PARAM_COUNT(); } - + ZEND_FETCH_RESOURCE(im, gdImagePtr, IM, -1, "Image", le_gd); convert_to_long_ex(index); col = Z_LVAL_PP(index); #if HAVE_LIBGD20 if ((col >= 0 && gdImageTrueColor(im)) || (!gdImageTrueColor(im) && col >= 0 && col < gdImageColorsTotal(im))) { - if (array_init(return_value) == FAILURE) { - RETURN_FALSE; - } + array_init(return_value); + add_assoc_long(return_value,"red", gdImageRed(im,col)); add_assoc_long(return_value,"green", gdImageGreen(im,col)); add_assoc_long(return_value,"blue", gdImageBlue(im,col)); add_assoc_long(return_value,"alpha", gdImageAlpha(im,col)); - } + } #else if (col >= 0 && col < gdImageColorsTotal(im)) { - if (array_init(return_value) == FAILURE) { - RETURN_FALSE; - } + array_init(return_value); + add_assoc_long(return_value,"red", im->red[col]); add_assoc_long(return_value,"green", im->green[col]); add_assoc_long(return_value,"blue", im->blue[col]); @@ -2038,7 +2075,7 @@ for (y = 0; y < gdImageSY(im); y++) { for (x = 0; x < gdImageSX(im); x++) { c = gdImageGetPixel(im, x, y); - gdImageSetPixel(im, x, y, + gdImageSetPixel(im, x, y, gdTrueColor( (int)((pow((pow((gdTrueColorGetRed(c) / 255.0), input)), 1.0 / output) * 255)+.5), (int)((pow((pow((gdTrueColorGetGreen(c) / 255.0), input)), 1.0 / output) * 255)+.5), @@ -2081,7 +2118,7 @@ RETURN_TRUE; } -/* }}} */ +/* }}} */ /* {{{ proto int imageline(int im, int x1, int y1, int x2, int y2, int col) Draw a line */ @@ -2102,10 +2139,15 @@ convert_to_long_ex(y2); convert_to_long_ex(col); - gdImageLine(im, Z_LVAL_PP(x1), Z_LVAL_PP(y1), Z_LVAL_PP(x2), Z_LVAL_PP(y2), Z_LVAL_PP(col)); +#ifdef HAVE_GD_BUNDLED + if (im->antialias) + gdImageAALine(im, Z_LVAL_PP(x1), Z_LVAL_PP(y1), Z_LVAL_PP(x2), Z_LVAL_PP(y2), Z_LVAL_PP(col)); + else +#endif + gdImageLine(im, Z_LVAL_PP(x1), Z_LVAL_PP(y1), Z_LVAL_PP(x2), Z_LVAL_PP(y2), Z_LVAL_PP(col)); RETURN_TRUE; } -/* }}} */ +/* }}} */ /* {{{ proto int imagedashedline(int im, int x1, int y1, int x2, int y2, int col) Draw a dashed line */ @@ -2153,7 +2195,7 @@ gdImageRectangle(im, Z_LVAL_PP(x1), Z_LVAL_PP(y1), Z_LVAL_PP(x2), Z_LVAL_PP(y2), Z_LVAL_PP(col)); RETURN_TRUE; } -/* }}} */ +/* }}} */ /* {{{ proto int imagefilledrectangle(int im, int x1, int y1, int x2, int y2, int col) Draw a filled rectangle */ @@ -2177,7 +2219,7 @@ gdImageFilledRectangle(im, Z_LVAL_PP(x1), Z_LVAL_PP(y1), Z_LVAL_PP(x2), Z_LVAL_PP(y2), Z_LVAL_PP(col)); RETURN_TRUE; } -/* }}} */ +/* }}} */ /* {{{ proto int imagearc(int im, int cx, int cy, int w, int h, int s, int e, int col) Draw a partial ellipse */ @@ -2210,7 +2252,7 @@ gdImageArc(im, Z_LVAL_PP(cx), Z_LVAL_PP(cy), Z_LVAL_PP(w), Z_LVAL_PP(h), st, e, Z_LVAL_PP(col)); RETURN_TRUE; } -/* }}} */ +/* }}} */ /* {{{ proto void imageellipse(resource im, int cx, int cy, int w, int h, int color) Draw an ellipse */ @@ -2222,7 +2264,7 @@ if (ZEND_NUM_ARGS() != 6 || zend_get_parameters_ex(6, &IM, &cx, &cy, &w, &h, &color) == FAILURE) { ZEND_WRONG_PARAM_COUNT(); } - + ZEND_FETCH_RESOURCE(im, gdImagePtr, IM, -1, "Image", le_gd); convert_to_long_ex(cx); @@ -2262,7 +2304,7 @@ gdImageFillToBorder(im, Z_LVAL_PP(x), Z_LVAL_PP(y), Z_LVAL_PP(border), Z_LVAL_PP(col)); RETURN_TRUE; } -/* }}} */ +/* }}} */ /* {{{ proto int imagefill(int im, int x, int y, int col) Flood fill */ @@ -2284,7 +2326,7 @@ gdImageFill(im, Z_LVAL_PP(x), Z_LVAL_PP(y), Z_LVAL_PP(col)); RETURN_TRUE; } -/* }}} */ +/* }}} */ /* {{{ proto int imagecolorstotal(int im) Find out the number of colors in an image's palette */ @@ -2301,7 +2343,7 @@ RETURN_LONG(gdImageColorsTotal(im)); } -/* }}} */ +/* }}} */ /* {{{ proto int imagecolortransparent(int im [, int col]) Define a color as transparent */ @@ -2334,7 +2376,7 @@ RETURN_LONG(gdImageGetTransparent(im)); } -/* }}} */ +/* }}} */ /* {{{ proto int imageinterlace(int im [, int interlace]) Enable or disable interlace */ @@ -2367,18 +2409,18 @@ RETURN_LONG(gdImageGetInterlaced(im)); } -/* }}} */ +/* }}} */ /* {{{ php_imagepolygon arg = 0 normal polygon arg = 1 filled polygon */ /* im, points, num_points, col */ -static void php_imagepolygon(INTERNAL_FUNCTION_PARAMETERS, int filled) +static void php_imagepolygon(INTERNAL_FUNCTION_PARAMETERS, int filled) { zval **IM, **POINTS, **NPOINTS, **COL; pval **var = NULL; gdImagePtr im; - gdPointPtr points; + gdPointPtr points; int npoints, col, nelem, i; if (ZEND_NUM_ARGS() != 4 || zend_get_parameters_ex(4, &IM, &POINTS, &NPOINTS, &COL) == FAILURE) { @@ -2458,7 +2500,7 @@ gdFontPtr font; int ind_type; TSRMLS_FETCH(); - + switch (size) { case 1: font = gdFontTiny; @@ -2503,7 +2545,7 @@ if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &SIZE) == FAILURE) { ZEND_WRONG_PARAM_COUNT(); } - + convert_to_long_ex(SIZE); font = php_find_gd_font(Z_LVAL_PP(SIZE)); @@ -2541,7 +2583,7 @@ for (py = y; (py > (y - f->w)); py--) { for (px = x; (px < (x + f->h)); px++) { if (f->data[fline + cy * f->w + cx]) { - gdImageSetPixel(im, px, py, color); + gdImageSetPixel(im, px, py, color); } cy++; } @@ -2557,7 +2599,7 @@ * arg = 2 ImageString * arg = 3 ImageStringUp */ -static void php_imagechar(INTERNAL_FUNCTION_PARAMETERS, int mode) +static void php_imagechar(INTERNAL_FUNCTION_PARAMETERS, int mode) { zval **IM, **SIZE, **X, **Y, **C, **COL; gdImagePtr im; @@ -2623,8 +2665,8 @@ /* }}} */ /* {{{ proto int imagechar(int im, int font, int x, int y, string c, int col) - Draw a character */ -PHP_FUNCTION(imagechar) + Draw a character */ +PHP_FUNCTION(imagechar) { php_imagechar(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); } @@ -2632,7 +2674,7 @@ /* {{{ proto int imagecharup(int im, int font, int x, int y, string c, int col) Draw a character rotated 90 degrees counter-clockwise */ -PHP_FUNCTION(imagecharup) +PHP_FUNCTION(imagecharup) { php_imagechar(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); } @@ -2640,7 +2682,7 @@ /* {{{ proto int imagestring(int im, int font, int x, int y, string str, int col) Draw a string horizontally */ -PHP_FUNCTION(imagestring) +PHP_FUNCTION(imagestring) { php_imagechar(INTERNAL_FUNCTION_PARAM_PASSTHRU, 2); } @@ -2648,21 +2690,21 @@ /* {{{ proto int imagestringup(int im, int font, int x, int y, string str, int col) Draw a string vertically - rotated 90 degrees counter-clockwise */ -PHP_FUNCTION(imagestringup) +PHP_FUNCTION(imagestringup) { php_imagechar(INTERNAL_FUNCTION_PARAM_PASSTHRU, 3); } /* }}} */ /* {{{ proto int imagecopy(int dst_im, int src_im, int dst_x, int dst_y, int src_x, int src_y, int src_w, int src_h) - Copy part of an image */ + Copy part of an image */ PHP_FUNCTION(imagecopy) { zval **SIM, **DIM, **SX, **SY, **SW, **SH, **DX, **DY; gdImagePtr im_dst, im_src; int srcH, srcW, srcY, srcX, dstY, dstX; - if (ZEND_NUM_ARGS() != 8 || + if (ZEND_NUM_ARGS() != 8 || zend_get_parameters_ex(8, &DIM, &SIM, &DX, &DY, &SX, &SY, &SW, &SH) == FAILURE) { ZEND_WRONG_PARAM_COUNT(); } @@ -2802,7 +2844,7 @@ gdImageCopyResized(im_dst, im_src, dstX, dstY, srcX, srcY, dstW, dstH, srcW, srcH); RETURN_TRUE; } -/* }}} */ +/* }}} */ /* {{{ proto int imagesx(int im) Get image width */ @@ -2861,7 +2903,7 @@ php_imagettftext_common(INTERNAL_FUNCTION_PARAM_PASSTHRU, TTFTEXT_DRAW, 1); } /* }}} */ -#endif +#endif /* {{{ proto array imagettfbbox(int size, int angle, string font_file, string text) @@ -2898,7 +2940,7 @@ #if !HAVE_GD_STRINGFTEX assert(!extended); #endif - + argc = ZEND_NUM_ARGS(); if (mode == TTFTEXT_BBOX) { @@ -2933,12 +2975,12 @@ #if HAVE_GD_STRINGFTEX if (EXT) { /* parse extended info */ - + HashPosition pos; - + convert_to_array_ex(EXT); memset(&strex, 0, sizeof(strex)); - + /* walk the assoc array */ zend_hash_internal_pointer_reset_ex(HASH_OF(*EXT), &pos); do { @@ -2950,17 +2992,17 @@ if (zend_hash_get_current_data_ex(HASH_OF(*EXT), (void**)&item, &pos) == FAILURE) continue; - + if (strcmp("linespacing", key) == 0) { convert_to_double_ex(item); strex.flags |= gdFTEX_LINESPACE; strex.linespacing = Z_DVAL_PP(item); } - + } while(zend_hash_move_forward_ex(HASH_OF(*EXT), &pos) == SUCCESS); } #endif - + } ptsize = Z_DVAL_PP(PTSIZE); @@ -3001,10 +3043,8 @@ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", error); RETURN_FALSE; } - - if (array_init(return_value) == FAILURE) { - RETURN_FALSE; - } + + array_init(return_value); /* return array with the text's bounding box */ for (i = 0; i < 8; i++) { @@ -3249,15 +3289,15 @@ GLYPH *str_img; T1_OUTLINE *char_path, *str_path; T1_TMATRIX *transform = NULL; - char *_str; - int _str_len; + char *str; + int str_len; int argc = ZEND_NUM_ARGS(); - + if (argc != 8 && argc != 12) { ZEND_WRONG_PARAM_COUNT(); } - - if (zend_parse_parameters(ZEND_NUM_ARGS(), "rsrlllll|lldl", &img, &_str, &_str_len, &fnt, &size, &_fg, &_bg, &x, &y, &space, &width, &angle, &aa_steps) == FAILURE) { + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsrlllll|lldl", &img, &str, &str_len, &fnt, &size, &_fg, &_bg, &x, &y, &space, &width, &angle, &aa_steps) == FAILURE) { return; } @@ -3269,7 +3309,7 @@ if (_fg < 0 || (!gdImageTrueColor(bg_img) && _fg > gdImageColorsTotal(bg_img))) { #else if (_fg < 0 || _fg > gdImageColorsTotal(bg_img)) { -#endif +#endif php_error_docref(NULL TSRMLS_CC, E_WARNING, "Foreground color index %d out of range", _fg); RETURN_FALSE; } @@ -3278,11 +3318,11 @@ if (_bg < 0 || (!gdImageTrueColor(bg_img) && _fg > gdImageColorsTotal(bg_img))) { #else if (_bg < 0 || _bg > gdImageColorsTotal(bg_img)) { -#endif +#endif php_error_docref(NULL TSRMLS_CC, E_WARNING, "Background color index %d out of range", _bg); RETURN_FALSE; } - + fg_rd = gdImageRed (bg_img, _fg); fg_gr = gdImageGreen(bg_img, _fg); fg_bl = gdImageBlue (bg_img, _fg); @@ -3331,24 +3371,24 @@ } extend = T1_GetExtend(*f_ind); - str_path = T1_GetCharOutline(*f_ind, _str[0], size, transform); + str_path = T1_GetCharOutline(*f_ind, str[0], size, transform); if (!str_path) { if (T1_errno) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "libt1 returned error %d", T1_errno); - } + } RETURN_FALSE; } - for (i = 1; i < _str_len; i++) { - amount_kern = (int) T1_GetKerning(*f_ind, _str[i-1], _str[i]); - amount_kern += _str[i-1] == ' ' ? space : 0; + for (i = 1; i < str_len; i++) { + amount_kern = (int) T1_GetKerning(*f_ind, str[i-1], str[i]); + amount_kern += str[i-1] == ' ' ? space : 0; add_width = (int) (amount_kern+width)/extend; char_path = T1_GetMoveOutline(*f_ind, add_width, 0, 0, size, transform); str_path = T1_ConcatOutlines(str_path, char_path); - char_path = T1_GetCharOutline(*f_ind, _str[i], size, transform); + char_path = T1_GetCharOutline(*f_ind, str[i], size, transform); str_path = T1_ConcatOutlines(str_path, char_path); } str_img = T1_AAFillOutline(str_path, 0); @@ -3374,10 +3414,7 @@ } } - if (array_init(return_value) == FAILURE) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Couldn't initialize array for returning bounding box"); - RETURN_FALSE; - } + array_init(return_value); add_next_index_long(return_value, str_img->metrics.leftSideBearing); add_next_index_long(return_value, str_img->metrics.descent); @@ -3479,10 +3516,8 @@ str_bbox = T1_GetStringBBox(*f_ind, Z_STRVAL_PP(str), Z_STRLEN_PP(str), space, T1_KERNING); } if (T1_errno) RETURN_FALSE; - - if (array_init(return_value) == FAILURE) { - RETURN_FALSE; - } + + array_init(return_value); /* printf("%d %d %d %d\n", str_bbox.llx, str_bbox.lly, str_bbox.urx, str_bbox.ury); */ @@ -3492,7 +3527,7 @@ add_next_index_long(return_value, (int) ceil(((double) str_bbox.ury)*Z_LVAL_PP(sz)/1000)); } /* }}} */ -#endif +#endif #ifdef HAVE_GD_WBMP /* {{{ proto int image2wbmp(int im [, string filename [, int threshold]]) @@ -3527,7 +3562,7 @@ #ifdef HAVE_GD_WBMP /* {{{ _php_image_bw_convert * It converts a gd Image to bw using a threshold value */ -static void _php_image_bw_convert( gdImagePtr im_org, gdIOCtx *out, int threshold) +static void _php_image_bw_convert( gdImagePtr im_org, gdIOCtx *out, int threshold) { gdImagePtr im_dest; int white, black; @@ -3536,7 +3571,7 @@ int dest_width = gdImageSX (im_org); int x, y; TSRMLS_FETCH(); - + im_dest = gdImageCreate (dest_width, dest_height); if (im_dest == NULL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to allocate temporary buffer"); @@ -3578,7 +3613,7 @@ /* {{{ _php_image_convert * _php_image_convert converts jpeg/png images to wbmp and resizes them as needed */ -static void _php_image_convert(INTERNAL_FUNCTION_PARAMETERS, int image_type ) +static void _php_image_convert(INTERNAL_FUNCTION_PARAMETERS, int image_type ) { zval **f_org, **f_dest, **height, **width, **threshold; gdImagePtr im_org, im_dest, im_tmp; @@ -3769,6 +3804,25 @@ } /* }}} */ #endif /* HAVE_GD_WBMP */ + +#ifdef HAVE_GD_BUNDLED +/* {{{ proto imagesetantialias(int im, bool on) + Should antialiased functions used or not*/ +PHP_FUNCTION(imageantialias) +{ + zval **IM, **alias; + gdImagePtr im; + + if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &IM, &alias) == FAILURE) { + ZEND_WRONG_PARAM_COUNT(); + } + ZEND_FETCH_RESOURCE(im, gdImagePtr, IM, -1, "Image", le_gd); + convert_to_boolean_ex(alias); + gdImageAntialias(im, Z_LVAL_PP(alias)); + RETURN_TRUE; +} +/* }}} */ +#endif #endif /* HAVE_LIBGD */ Index: php4/ext/gd/gdcache.c diff -u php4/ext/gd/gdcache.c:1.5 php4/ext/gd/gdcache.c:1.5.2.1 --- php4/ext/gd/gdcache.c:1.5 Thu Oct 24 09:14:35 2002 +++ php4/ext/gd/gdcache.c Wed Mar 5 11:04:20 2003 @@ -1,5 +1,5 @@ /* - * $Id: gdcache.c,v 1.5 2002/10/24 13:14:35 sas Exp $ + * $Id: gdcache.c,v 1.5.2.1 2003/03/05 16:04:20 iliaa Exp $ * * Caches of pointers to user structs in which the least-recently-used * element is replaced in the event of a cache miss after the cache has @@ -36,6 +36,8 @@ * sizes of a few tens of elements. */ +#include "php.h" + /* This just seems unessacary */ #if PHP_WIN32 #define ENABLE_GD_TTF @@ -61,7 +63,7 @@ { gdCache_head_t *head; - head = (gdCache_head_t *)malloc(sizeof(gdCache_head_t)); + head = (gdCache_head_t *)pemalloc(sizeof(gdCache_head_t), 1); head->mru = NULL; head->size = size; head->gdCacheTest = gdCacheTest; @@ -80,9 +82,9 @@ (*(head->gdCacheRelease))(elem->userdata); prev = elem; elem = elem->next; - free((char *)prev); + pefree((char *)prev, 1); } - free((char *)head); + pefree((char *)head, 1); } void * @@ -114,7 +116,7 @@ return NULL; } if (i < head->size) { /* cache still growing - add new elem */ - elem = (gdCache_element_t *)malloc(sizeof(gdCache_element_t)); + elem = (gdCache_element_t *)pemalloc(sizeof(gdCache_element_t), 1); } else { /* cache full - replace least-recently-used */ /* preveprev becomes new end of list */ Index: php4/ext/gd/gdcache.h diff -u php4/ext/gd/gdcache.h:1.2.14.1 php4/ext/gd/gdcache.h:1.2.14.2 --- php4/ext/gd/gdcache.h:1.2.14.1 Fri Nov 29 06:15:43 2002 +++ php4/ext/gd/gdcache.h Wed Mar 5 11:04:20 2003 @@ -1,5 +1,5 @@ /* - * $Id: gdcache.h,v 1.2.14.1 2002/11/29 11:15:43 martin Exp $ + * $Id: gdcache.h,v 1.2.14.2 2003/03/05 16:04:20 iliaa Exp $ * * Caches of pointers to user structs in which the least-recently-used * element is replaced in the event of a cache miss after the cache has Index: php4/ext/gd/gdttf.c diff -u php4/ext/gd/gdttf.c:1.16 php4/ext/gd/gdttf.c:1.16.10.1 --- php4/ext/gd/gdttf.c:1.16 Sat Aug 11 12:38:30 2001 +++ php4/ext/gd/gdttf.c Wed Mar 5 11:04:20 2003 @@ -2,7 +2,7 @@ /* */ /* John Ellson ellson@lucent.com */ -/* $Id: gdttf.c,v 1.16 2001/08/11 16:38:30 zeev Exp $ */ +/* $Id: gdttf.c,v 1.16.10.1 2003/03/05 16:04:20 iliaa Exp $ */ #include "php.h" @@ -334,15 +334,16 @@ short platform, encoding; TSRMLS_FETCH(); - a = (font_t *)malloc(sizeof(font_t)); + a = (font_t *)pemalloc(sizeof(font_t), 1); #ifdef VIRTUAL_DIR /* a->fontname will be freed in fontRelease() later on */ if (virtual_filepath(b->fontname, &a->fontname TSRMLS_CC)) { *error = "Could not find/open font"; + pefree(a, 1); return NULL; } #else - a->fontname = (char *)malloc(strlen(b->fontname) + 1); + a->fontname = (char *)pemalloc(strlen(b->fontname) + 1, 1); strcpy(a->fontname, b->fontname); #endif a->ptsize = b->ptsize; @@ -357,6 +358,7 @@ else { *error = "Could not read font"; } + pefree(a, 1); return NULL; } /* get face properties and allocate preload arrays */ @@ -365,20 +367,19 @@ /* create instance */ if (TT_New_Instance(a->face, &a->instance)) { *error = "Could not create face instance"; + pefree(a, 1); return NULL; } if (TT_Set_Instance_Resolutions(a->instance, RESOLUTION, RESOLUTION)) { *error = "Could not set device resolutions"; + pefree(a, 1); return NULL; -map_found = 0; -a->have_char_map_Unicode = 0; -a->have_char_map_Big5 = 0; -a->have_char_map_Roman = 0; } if (TT_Set_Instance_CharSize(a->instance, (TT_F26Dot6)(a->ptsize*64))) { *error = "Could not set character size"; + pefree(a, 1); return NULL; } @@ -403,13 +404,14 @@ TT_Get_CharMap(a->face, i, &a->char_map_Roman); a->have_char_map_Roman = 1; map_found++; - } + } } if (! map_found) { *error = "Unable to find a CharMap that I can handle"; - return NULL; - } + pefree(a, 1); + return NULL; + } a->matrix.xx = (TT_Fixed) (a->cos_a * (1<<16)); a->matrix.yx = (TT_Fixed) (a->sin_a * (1<<16)); @@ -430,8 +432,8 @@ gdCacheDelete(a->glyphCache); TT_Done_Instance(a->instance); TT_Close_Face(a->face); - free(a->fontname); - free( (char *)element ); + pefree(a->fontname, 1); + pefree((char *)element, 1); } /********************************************************************/ @@ -458,7 +460,7 @@ int crect[8], xmin, xmax, ymin, ymax; double cos_a, sin_a; - a = (glyph_t *)malloc(sizeof(glyph_t)); + a = (glyph_t *)pemalloc(sizeof(glyph_t), 1); a->character = b->character; a->hinting = b->hinting; a->gray_render = b->gray_render; @@ -467,6 +469,7 @@ /* create glyph container */ if ((TT_New_Glyph(b->font->face, &a->glyph))) { *error = "Could not create glyph container"; + pefree(a, 1); return NULL; } @@ -483,6 +486,7 @@ } if ((err=TT_Load_Glyph(b->font->instance, a->glyph, glyph_code, flags))) { *error = "TT_Load_Glyph problem"; + pefree(a, 1); return NULL; } @@ -540,7 +544,7 @@ gdCacheDelete(a->bitmapCache); TT_Done_Glyph( a->glyph ); - free( (char *)element ); + pefree ((char *)element, 1); } /********************************************************************/ @@ -565,11 +569,11 @@ bitmap_t *a; bitmapkey_t *b=(bitmapkey_t *)key; - a = (bitmap_t *)malloc(sizeof(bitmap_t)); + a = (bitmap_t *)pemalloc(sizeof(bitmap_t), 1); a->xoffset = b->xoffset; a->yoffset = b->yoffset; - b->glyph->Bit.bitmap = a->bitmap = (char *)malloc(b->glyph->Bit.size); + b->glyph->Bit.bitmap = a->bitmap = (char *)pemalloc(b->glyph->Bit.size, 1); memset(a->bitmap, 0, b->glyph->Bit.size); /* render glyph */ if (b->glyph->gray_render) { @@ -588,8 +592,8 @@ { bitmap_t *a=(bitmap_t *)element; - free( a->bitmap ); - free( (char *)element ); + pefree (a->bitmap, 1); + pefree ((char *)element, 1); } /********************************************************************/ @@ -615,7 +619,7 @@ int pixel, npixel, bg, fg; gdImagePtr im; - a = (tweencolor_t *)malloc(sizeof(tweencolor_t)); + a = (tweencolor_t *)pemalloc(sizeof(tweencolor_t), 1); pixel = a->pixel = b->pixel; bg = a->bgcolor = b->bgcolor; fg = a->fgcolor = b->fgcolor; @@ -638,7 +642,7 @@ static void tweenColorRelease(void *element) { - free((char *)element); + pefree((char *)element, 1); } /********************************************************************/ Index: php4/ext/gd/php_gd.h diff -u php4/ext/gd/php_gd.h:1.44.2.3 php4/ext/gd/php_gd.h:1.44.2.4 --- php4/ext/gd/php_gd.h:1.44.2.3 Fri Feb 28 20:15:47 2003 +++ php4/ext/gd/php_gd.h Wed Mar 5 11:04:20 2003 @@ -1,4 +1,4 @@ -/* +/* +----------------------------------------------------------------------+ | PHP Version 4 | +----------------------------------------------------------------------+ @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_gd.h,v 1.44.2.3 2003/03/01 01:15:47 pajoye Exp $ */ +/* $Id: php_gd.h,v 1.44.2.4 2003/03/05 16:04:20 iliaa Exp $ */ #ifndef PHP_GD_H #define PHP_GD_H @@ -58,11 +58,14 @@ PHP_MINFO_FUNCTION(gd); PHP_MINIT_FUNCTION(gd); PHP_MSHUTDOWN_FUNCTION(gd); +PHP_RSHUTDOWN_FUNCTION(gd); PHP_FUNCTION(gd_info); PHP_FUNCTION(imagearc); +PHP_FUNCTION(imageellipse); PHP_FUNCTION(imagechar); PHP_FUNCTION(imagecharup); +PHP_FUNCTION(imageistruecolor); PHP_FUNCTION(imagecolorallocate); PHP_FUNCTION(imagepalettecopy); PHP_FUNCTION(imagecolorat); @@ -83,26 +86,27 @@ PHP_FUNCTION(imageftbbox); PHP_FUNCTION(imagefttext); +#ifdef HAVE_LIBGD20 PHP_FUNCTION(imagecreatetruecolor); -PHP_FUNCTION(imageistruecolor); PHP_FUNCTION(imagetruecolortopalette); PHP_FUNCTION(imagesetthickness); -PHP_FUNCTION(imageellipse); PHP_FUNCTION(imagefilledellipse); PHP_FUNCTION(imagefilledarc); PHP_FUNCTION(imagealphablending); PHP_FUNCTION(imagesavealpha); +PHP_FUNCTION(imagecolorallocatealpha); PHP_FUNCTION(imagecolorresolvealpha); PHP_FUNCTION(imagecolorclosestalpha); PHP_FUNCTION(imagecolorexactalpha); PHP_FUNCTION(imagecopyresampled); +#endif #ifdef HAVE_GD_BUNDLED PHP_FUNCTION(imagerotate); +PHP_FUNCTION(imageantialias); #endif PHP_FUNCTION(imagesetthickness); -PHP_FUNCTION(imagesettile); PHP_FUNCTION(imagecopymergegray); PHP_FUNCTION(imagesetbrush); PHP_FUNCTION(imagesettile); @@ -168,6 +172,7 @@ #if HAVE_GD_BUNDLED PHP_FUNCTION(imagelayereffect); PHP_FUNCTION(imagecolormatch); +PHP_FUNCTION(imagefilter); #endif PHP_GD_API int phpi_get_le_gd(void); Index: php4/ext/gd/libgd/gd.c diff -u php4/ext/gd/libgd/gd.c:1.24.2.4 php4/ext/gd/libgd/gd.c:1.24.2.5 --- php4/ext/gd/libgd/gd.c:1.24.2.4 Mon Feb 24 22:53:22 2003 +++ php4/ext/gd/libgd/gd.c Wed Mar 5 11:04:20 2003 @@ -81,6 +81,9 @@ }; #endif /*CHARSET_EBCDIC */ +/* 2.0.10: cast instead of floor() yields 35% performance improvement. Thanks to John Buckman. */ +#define floor_cast(exp) ((long) exp) + extern int gdCosT[]; extern int gdSinT[]; @@ -92,6 +95,28 @@ static int gdAlphaOverlayColor(int src, int dst, int max); static int gdImageGetTrueColorPixel(gdImagePtr im, int x, int y); +void php_gd_error_ex(int type, const char *format, ...) +{ + va_list args; + + TSRMLS_FETCH(); + + va_start(args, format); + php_verror(NULL, "", type, format, args TSRMLS_CC); + va_end(args); +} + +void php_gd_error(const char *format, ...) +{ + va_list args; + + TSRMLS_FETCH(); + + va_start(args, format); + php_verror(NULL, "", E_WARNING, format, args TSRMLS_CC); + va_end(args); +} + gdImagePtr gdImageCreate (int sx, int sy) { @@ -319,7 +344,7 @@ } else { - diff = fabsf (HWB1.H - HWB2.H); + diff = fabsf(HWB1.H - HWB2.H); if (diff > 3.0f) { diff = 6.0f - diff; /* Remember, it's a colour circle */ @@ -375,8 +400,9 @@ } return RGB; + } -#endif /* 0 */ +#endif int gdImageColorClosestHWB (gdImagePtr im, int r, int g, int b) @@ -516,12 +542,12 @@ op = c; /* Save open slot */ continue; /* Color not in use */ } - if (c == im->transparent) - { - /* don't ever resolve to the color that has - * been designated as the transparent color */ - continue; - } + if (c == im->transparent) + { + /* don't ever resolve to the color that has + * been designated as the transparent color */ + continue; + } rd = (long) (im->red[c] - r); gd = (long) (im->green[c] - g); bd = (long) (im->blue[c] - b); @@ -572,7 +598,7 @@ if (im->transparent != -1) { im->alpha[im->transparent] = gdAlphaOpaque; } - if (color > -1 && color <= gdMaxColors) { + if (color > -1 && color<=gdMaxColors) { im->alpha[color] = gdAlphaTransparent; } else { return; @@ -638,6 +664,76 @@ } +/* 2.0.10: before the drawing routines, some code to clip points that are + * outside the drawing window. Nick Atty (nick@canalplan.org.uk) + * + * This is the Sutherland Hodgman Algorithm, as implemented by + * Duvanenko, Robbins and Gyurcsik - SH(DRG) for short. See Dr Dobb's + * Journal, January 1996, pp107-110 and 116-117 + * + * Given the end points of a line, and a bounding rectangle (which we + * know to be from (0,0) to (SX,SY)), adjust the endpoints to be on + * the edges of the rectangle if the line should be drawn at all, + * otherwise return a failure code + */ + +/* this does "one-dimensional" clipping: note that the second time it + * is called, all the x parameters refer to height and the y to width + * - the comments ignore this (if you can understand it when it's + * looking at the X parameters, it should become clear what happens on + * the second call!) The code is simplified from that in the article, + * as we know that gd images always start at (0,0) + */ + +static int clip_1d(int *x0, int *y0, int *x1, int *y1, int maxdim) { + double m; /* gradient of line */ + + if (*x0 < 0) { /* start of line is left of window */ + if(*x1 < 0) { /* as is the end, so the line never cuts the window */ + return 0; + } + m = (*y1 - *y0)/(double)(*x1 - *x0); /* calculate the slope of the line */ + /* adjust x0 to be on the left boundary (ie to be zero), and y0 to match */ + *y0 -= (int)(m * *x0); + *x0 = 0; + /* now, perhaps, adjust the far end of the line as well */ + if (*x1 > maxdim) { + *y1 += (int)(m * (maxdim - *x1)); + *x1 = maxdim; + } + return 1; + } + if (*x0 > maxdim) { /* start of line is right of window - complement of above */ + if (*x1 > maxdim) { /* as is the end, so the line misses the window */ + return 0; + } + m = (*y1 - *y0)/(double)(*x1 - *x0); /* calculate the slope of the line */ + *y0 += (int)(m * (maxdim - *x0)); /* adjust so point is on the right boundary */ + *x0 = maxdim; + /* now, perhaps, adjust the end of the line */ + if (*x1 < 0) { + *y1 -= (int)(m * *x1); + *x1 = 0; + } + return 1; + } + /* the final case - the start of the line is inside the window */ + if (*x1 > maxdim) { /* other end is outside to the right */ + m = (*y1 - *y0)/(double)(*x1 - *x0); /* calculate the slope of the line */ + *y1 += (int)(m * (maxdim - *x1)); + *x1 = maxdim; + return 1; + } + if (*x1 < 0) { /* other end is outside to the left */ + m = (*y1 - *y0)/(double)(*x1 - *x0); /* calculate the slope of the line */ + *y1 -= (int)(m * *x1); + *x1 = 0; + return 1; + } + /* only get here if both points are inside the window */ + return 1; +} + void gdImageSetPixel (gdImagePtr im, int x, int y, int color) { @@ -725,74 +821,60 @@ static void gdImageBrushApply (gdImagePtr im, int x, int y) { - int lx, ly; - int hy; - int hx; - int x1, y1, x2, y2; - int srcx, srcy; - if (!im->brush) - { - return; - } - hy = gdImageSY (im->brush) / 2; - y1 = y - hy; - y2 = y1 + gdImageSY (im->brush); - hx = gdImageSX (im->brush) / 2; - x1 = x - hx; - x2 = x1 + gdImageSX (im->brush); - srcy = 0; - if (im->trueColor) - { - for (ly = y1; (ly < y2); ly++) - { - srcx = 0; - for (lx = x1; (lx < x2); lx++) - { - int p; - p = gdImageGetTrueColorPixel ( - im->brush, srcx, srcy); - gdImageSetPixel (im, lx, ly, - p); - srcx++; - } - srcy++; - } - } - else - { - for (ly = y1; (ly < y2); ly++) - { - srcx = 0; - for (lx = x1; (lx < x2); lx++) - { - int p; - p = gdImageGetPixel (im->brush, srcx, srcy); - /* Allow for non-square brushes! */ - if (p != gdImageGetTransparent (im->brush)) - { - /* Truecolor brush. Very slow - on a palette destination. */ - if (im->brush->trueColor) - { - gdImageSetPixel (im, lx, ly, - gdImageColorResolveAlpha ( - im, - gdTrueColorGetRed (p), - gdTrueColorGetGreen (p), - gdTrueColorGetBlue (p), - gdTrueColorGetAlpha (p))); - } - else - { - gdImageSetPixel (im, lx, ly, - im->brushColorMap[p]); - } + int lx, ly; + int hy, hx; + int x1, y1, x2, y2; + int srcx, srcy; + + if (!im->brush) { + return; + } + + hy = gdImageSY (im->brush) / 2; + y1 = y - hy; + y2 = y1 + gdImageSY (im->brush); + hx = gdImageSX (im->brush) / 2; + x1 = x - hx; + x2 = x1 + gdImageSX (im->brush); + srcy = 0; + + if (im->trueColor) { + for (ly = y1; (ly < y2); ly++) { + srcx = 0; + for (lx = x1; (lx < x2); lx++) { + int p; + p = gdImageGetTrueColorPixel (im->brush, srcx, srcy); + /* 2.0.9, Thomas Winzig: apply simple full transparency */ + if (p != gdImageGetTransparent (im->brush)) { + gdImageSetPixel (im, lx, ly, p); + } + srcx++; + } + srcy++; + } + } else { + for (ly = y1; (ly < y2); ly++) { + srcx = 0; + for (lx = x1; (lx < x2); lx++) { + int p; + p = gdImageGetPixel (im->brush, srcx, srcy); + /* Allow for non-square brushes! */ + if (p != gdImageGetTransparent (im->brush)) { + /* Truecolor brush. Very slow on a palette destination. */ + if (im->brush->trueColor) { + gdImageSetPixel(im, lx, ly, gdImageColorResolveAlpha(im, gdTrueColorGetRed(p), + gdTrueColorGetGreen(p), + gdTrueColorGetBlue(p), + gdTrueColorGetAlpha(p))); + } else { + gdImageSetPixel(im, lx, ly, im->brushColorMap[p]); + } + } + srcx++; + } + srcy++; } - srcx++; - } - srcy++; } - } } static void @@ -862,151 +944,272 @@ void gdImageLine (gdImagePtr im, int x1, int y1, int x2, int y2, int color) { - int dx, dy, incr1, incr2, d, x, y, xend, yend, xdirflag, ydirflag; - int wid; - int w, wstart; - int thick = im->thick; - dx = abs (x2 - x1); - dy = abs (y2 - y1); - if (dy <= dx) - { - /* More-or-less horizontal. use wid for vertical stroke */ - wid = (int)(thick * cos (atan2 (dy, dx))); - if (wid == 0) - wid = 1; - - d = 2 * dy - dx; - incr1 = 2 * dy; - incr2 = 2 * (dy - dx); - if (x1 > x2) - { - x = x2; - y = y2; - ydirflag = (-1); - xend = x1; - } - else - { - x = x1; - y = y1; - ydirflag = 1; - xend = x2; + int dx, dy, incr1, incr2, d, x, y, xend, yend, xdirflag, ydirflag; + int wid; + int w, wstart; + int thick = im->thick; + + /* 2.0.10: Nick Atty: clip to edges of drawing rectangle, return if no points need to be drawn */ + if (!clip_1d(&x1,&y1,&x2,&y2,gdImageSX(im)) || !clip_1d(&y1,&x1,&y2,&x2,gdImageSY(im))) { + return; } - - /* Set up line thickness */ - wstart = y - wid / 2; - for (w = wstart; w < wstart + wid; w++) - gdImageSetPixel (im, x, w, color); - - if (((y2 - y1) * ydirflag) > 0) - { - while (x < xend) - { - x++; - if (d < 0) - { - d += incr1; + + dx = abs(x2 - x1); + dy = abs(y2 - y1); + if (dy <= dx) { + /* More-or-less horizontal. use wid for vertical stroke */ + /* Doug Claar: watch out for NaN in atan2 (2.0.5) */ + if ((dx == 0) && (dy == 0)) { + wid = 1; + } else { + wid = (int)(thick * cos (atan2 (dy, dx))); + if (wid == 0) { + wid = 1; + } } - else - { - y++; - d += incr2; + d = 2 * dy - dx; + incr1 = 2 * dy; + incr2 = 2 * (dy - dx); + if (x1 > x2) { + x = x2; + y = y2; + ydirflag = (-1); + xend = x1; + } else { + x = x1; + y = y1; + ydirflag = 1; + xend = x2; + } + + /* Set up line thickness */ + wstart = y - wid / 2; + for (w = wstart; w < wstart + wid; w++) { + gdImageSetPixel(im, x, w, color); + } + + if (((y2 - y1) * ydirflag) > 0) { + while (x < xend) { + x++; + if (d < 0) { + d += incr1; + } else { + y++; + d += incr2; + } + wstart = y - wid / 2; + for (w = wstart; w < wstart + wid; w++) { + gdImageSetPixel (im, x, w, color); + } + } + } else { + while (x < xend) { + x++; + if (d < 0) { + d += incr1; + } else { + y--; + d += incr2; + } + wstart = y - wid / 2; + for (w = wstart; w < wstart + wid; w++) { + gdImageSetPixel (im, x, w, color); + } + } } - wstart = y - wid / 2; - for (w = wstart; w < wstart + wid; w++) - gdImageSetPixel (im, x, w, color); - } - } - else - { - while (x < xend) - { - x++; - if (d < 0) - { - d += incr1; + } else { + /* More-or-less vertical. use wid for horizontal stroke */ + wid = (int)(thick * sin (atan2 (dy, dx))); + if (wid == 0) { + wid = 1; } - else - { - y--; - d += incr2; + + d = 2 * dx - dy; + incr1 = 2 * dx; + incr2 = 2 * (dx - dy); + if (y1 > y2) { + y = y2; + x = x2; + yend = y1; + xdirflag = (-1); + } else { + y = y1; + x = x1; + yend = y2; + xdirflag = 1; + } + + /* Set up line thickness */ + wstart = x - wid / 2; + for (w = wstart; w < wstart + wid; w++) { + gdImageSetPixel (im, w, y, color); + } + + if (((x2 - x1) * xdirflag) > 0) { + while (y < yend) { + y++; + if (d < 0) { + d += incr1; + } else { + x++; + d += incr2; + } + wstart = x - wid / 2; + for (w = wstart; w < wstart + wid; w++) { + gdImageSetPixel (im, w, y, color); + } + } + } else { + while (y < yend) { + y++; + if (d < 0) { + d += incr1; + } else { + x--; + d += incr2; + } + wstart = x - wid / 2; + for (w = wstart; w < wstart + wid; w++) { + gdImageSetPixel (im, w, y, color); + } + } } - wstart = y - wid / 2; - for (w = wstart; w < wstart + wid; w++) - gdImageSetPixel (im, x, w, color); - } } - } - else - { - /* More-or-less vertical. use wid for horizontal stroke */ - wid = (int)(thick * sin (atan2 (dy, dx))); - if (wid == 0) - wid = 1; +} - d = 2 * dx - dy; - incr1 = 2 * dx; - incr2 = 2 * (dx - dy); - if (y1 > y2) - { - y = y2; - x = x2; - yend = y1; - xdirflag = (-1); - } - else - { - y = y1; - x = x1; - yend = y2; - xdirflag = 1; - } - /* Set up line thickness */ - wstart = x - wid / 2; - for (w = wstart; w < wstart + wid; w++) - gdImageSetPixel (im, w, y, color); +/* + * Added on 2003/12 by Pierre-Alain Joye (pajoye@pearfr.org) + * */ +#define BLEND_COLOR(a, nc, c, cc) \ +nc = (cc) + (((((c) - (cc)) * (a)) + ((((c) - (cc)) * (a)) >> 8) + 0x80) >> 8); + +inline static void gdImageSetAAPixelColor(gdImagePtr im, int x, int y, int color, int t) +{ + int dr,dg,db,p,r,g,b; + dr = gdTrueColorGetRed(color); + dg = gdTrueColorGetGreen(color); + db = gdTrueColorGetBlue(color); + + p = gdImageGetPixel(im,x,y); + r = gdTrueColorGetRed(p); + g = gdTrueColorGetGreen(p); + b = gdTrueColorGetBlue(p); + + BLEND_COLOR(t, dr, r, dr); + BLEND_COLOR(t, dg, g, dg); + BLEND_COLOR(t, db, b, db); + im->tpixels[y][x]=gdTrueColorAlpha(dr, dg, db, gdAlphaOpaque); +} - if (((x2 - x1) * xdirflag) > 0) - { - while (y < yend) - { - y++; - if (d < 0) - { - d += incr1; - } - else - { - x++; - d += incr2; - } - wstart = x - wid / 2; - for (w = wstart; w < wstart + wid; w++) - gdImageSetPixel (im, w, y, color); - } - } - else - { - while (y < yend) - { - y++; - if (d < 0) - { - d += incr1; +/* + * Added on 2003/12 by Pierre-Alain Joye (pajoye@pearfr.org) + **/ +void gdImageAALine (gdImagePtr im, int x1, int y1, int x2, int y2, int col) +{ + /* keep them as 32bits */ + long x, y, inc; + long dx, dy,tmp; + + if (y1 < 0 && y2 < 0) { + return; + } + if (y1 < 0) { + x1 += (y1 * (x1 - x2)) / (y2 - y1); + y1 = 0; + } + if (y2 < 0) { + x2 += (y2 * (x1 - x2)) / (y2 - y1); + y2 = 0; + } + + /* bottom edge */ + if (y1 >= im->sy && y2 >= im->sy) { + return; + } + if (y1 >= im->sy) { + x1 -= ((im->sy - y1) * (x1 - x2)) / (y2 - y1); + y1 = im->sy - 1; + } + if (y2 >= im->sy) { + x2 -= ((im->sy - y2) * (x1 - x2)) / (y2 - y1); + y2 = im->sy - 1; + } + + /* left edge */ + if (x1 < 0 && x2 < 0) { + return; + } + if (x1 < 0) { + y1 += (x1 * (y1 - y2)) / (x2 - x1); + x1 = 0; + } + if (x2 < 0) { + y2 += (x2 * (y1 - y2)) / (x2 - x1); + x2 = 0; + } + /* right edge */ + if (x1 >= im->sx && x2 >= im->sx) { + return; + } + if (x1 >= im->sx) { + y1 -= ((im->sx - x1) * (y1 - y2)) / (x2 - x1); + x1 = im->sx - 1; + } + if (x2 >= im->sx) { + y2 -= ((im->sx - x2) * (y1 - y2)) / (x2 - x1); + x2 = im->sx - 1; + } + + dx = x2 - x1; + dy = y2 - y1; + + if (dx == 0 && dy == 0) { + return; + } + if (abs(dx) > abs(dy)) { + if (dx < 0) { + tmp = x1; + x1 = x2; + x2 = tmp; + tmp = y1; + y1 = y2; + y2 = tmp; + dx = x2 - x1; + dy = y2 - y1; + } + x = x1 << 16; + y = y1 << 16; + inc = (dy * 65536) / dx; + while ((x >> 16) < x2) { + gdImageSetAAPixelColor(im, x >> 16, y >> 16, col, (y >> 8) & 0xFF); + gdImageSetAAPixelColor(im, x >> 16, (y >> 16) + 1,col, (~y >> 8) & 0xFF); + x += (1 << 16); + y += inc; } - else - { - x--; - d += incr2; + } else { + if (dy < 0) { + tmp = x1; + x1 = x2; + x2 = tmp; + tmp = y1; + y1 = y2; + y2 = tmp; + dx = x2 - x1; + dy = y2 - y1; + } + x = x1 << 16; + y = y1 << 16; + inc = (dx * 65536) / dy; + while ((y>>16) < y2) { + gdImageSetAAPixelColor(im, x >> 16, y >> 16, col, (x >> 8) & 0xFF); + gdImageSetAAPixelColor(im, (x >> 16) + 1, (y >> 16),col, (~x >> 8) & 0xFF); + x += inc; + y += (1<<16); } - wstart = x - wid / 2; - for (w = wstart; w < wstart + wid; w++) - gdImageSetPixel (im, w, y, color); - } } - } } + static void dashedSet (gdImagePtr im, int x, int y, int color, int *onP, int *dashStepP, int wid, int vert); @@ -1175,13 +1378,6 @@ *onP = on; } -int -gdImageBoundsSafe (gdImagePtr im, int x, int y) -{ - return (!(((y < 0) || (y >= im->sy)) || - ((x < 0) || (x >= im->sx)))); -} - void gdImageChar (gdImagePtr im, gdFontPtr f, int x, int y, int c, int color) @@ -1428,6 +1624,7 @@ } } + /** * Integer Ellipse functions (gdImageEllipse and gdImageFilledEllipse) * Function added by Pierre-Alain Joye 02/08/2003 (paj@pearfr.org) @@ -1785,136 +1982,127 @@ void gdImageFilledRectangle (gdImagePtr im, int x1, int y1, int x2, int y2, int color) { - int x, y; - for (y = y1; (y <= y2); y++) - { - for (x = x1; (x <= x2); x++) - { - gdImageSetPixel (im, x, y, color); + int x, y; + + /* Nick Atty: limit the points at the edge. Note that this also + * nicely kills any plotting for rectangles completely outside the + * window as it makes the tests in the for loops fail + */ + if (x1 < 0) { + x1 = 0; + } + if (x1 > gdImageSX(im)) { + x1 = gdImageSX(im); + } + if(y1 < 0) { + y1 = 0; + } + if (y1 > gdImageSY(im)) { + y1 = gdImageSY(im); + } + + for (y = y1; (y <= y2); y++) { + for (x = x1; (x <= x2); x++) { + gdImageSetPixel (im, x, y, color); + } } - } } void gdImageCopy (gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int srcX, int srcY, int w, int h) { - int c; - int x, y; - int tox, toy; - int i; - int colorMap[gdMaxColors]; - if (dst->trueColor) - { - /* 2.0: much easier when the destination is truecolor. */ + int c; + int x, y; + int tox, toy; + int i; + int colorMap[gdMaxColors]; + if (dst->trueColor) { + /* 2.0: much easier when the destination is truecolor. */ + /* 2.0.10: needs a transparent-index check that is still valid if + * the source is not truecolor. Thanks to Frank Warmerdam. + */ - if (src->trueColor) { - for (y = 0; (y < h); y++) - { - for (x = 0; (x < w); x++) - { - int c = gdImageGetTrueColorPixel (src, srcX + x, - srcY + y); - gdImageSetPixel (dst, - dstX + x, - dstY + y, - c); + if (src->trueColor) { + for (y = 0; (y < h); y++) { + for (x = 0; (x < w); x++) { + int c = gdImageGetTrueColorPixel (src, srcX + x, srcY + y); + gdImageSetPixel (dst, dstX + x, dstY + y, c); } } - - } - else { + } else { /* source is palette based */ - for (y = 0; (y < h); y++) - { - for (x = 0; (x < w); x++) - { - int c = gdImageGetPixel (src, srcX + x, - srcY + y); - if (c != src->transparent) - { - gdImageSetPixel (dst, - dstX + x, - dstY + y, - gdTrueColor(src->red[c], src->green[c], src->blue[c])); + for (y = 0; (y < h); y++) { + for (x = 0; (x < w); x++) { + int c = gdImageGetPixel (src, srcX + x, srcY + y); + if (c != src->transparent) { + gdImageSetPixel (dst, dstX + x, dstY + y, gdTrueColor(src->red[c], src->green[c], src->blue[c])); } + } + } } - } + return; } - return; - } - - /* Destination is palette based */ - if (src->trueColor) { /* But source is truecolor (Ouch!) */ - toy = dstY; - for (y = srcY; (y < (srcY + h)); y++) - { - tox = dstX; - for (x = srcX; (x < (srcX + w)); x++) - { - int nc; - c = gdImageGetPixel (src, x, y); - - /* Get best match possible. */ - nc = gdImageColorResolveAlpha ( - dst, - gdTrueColorGetRed(c), - gdTrueColorGetGreen(c), - gdTrueColorGetBlue(c), - gdTrueColorGetAlpha(c)); - - gdImageSetPixel (dst, tox, toy, nc); - tox++; - } - toy++; - } - return; - } + /* Destination is palette based */ + if (src->trueColor) { /* But source is truecolor (Ouch!) */ + toy = dstY; + for (y = srcY; (y < (srcY + h)); y++) { + tox = dstX; + for (x = srcX; (x < (srcX + w)); x++) { + int nc; + c = gdImageGetPixel (src, x, y); - /* Palette based to palette based */ + /* Get best match possible. */ + nc = gdImageColorResolveAlpha (dst, gdTrueColorGetRed(c), gdTrueColorGetGreen(c), gdTrueColorGetBlue(c), gdTrueColorGetAlpha(c)); - for (i = 0; (i < gdMaxColors); i++) - { - colorMap[i] = (-1); - } - toy = dstY; - for (y = srcY; (y < (srcY + h)); y++) - { - tox = dstX; - for (x = srcX; (x < (srcX + w)); x++) - { - int nc; - c = gdImageGetPixel (src, x, y); - /* Added 7/24/95: support transparent copies */ - if (gdImageGetTransparent (src) == c) - { - tox++; - continue; - } - /* Have we established a mapping for this color? */ - if (colorMap[c] == (-1)) - { - /* If it's the same image, mapping is trivial */ - if (dst == src) - { - nc = c; + gdImageSetPixel (dst, tox, toy, nc); + tox++; + } + toy++; } - else - { - /* Get best match possible. This - function never returns error. */ - nc = gdImageColorResolveAlpha ( - dst, - src->red[c], src->green[c], - src->blue[c], src->alpha[c]); + return; + } + + /* Palette based to palette based */ + for (i = 0; (i < gdMaxColors); i++) { + colorMap[i] = (-1); + } + toy = dstY; + for (y = srcY; (y < (srcY + h)); y++) { + tox = dstX; + for (x = srcX; (x < (srcX + w)); x++) { + int nc; + int mapTo; + c = gdImageGetPixel (src, x, y); + /* Added 7/24/95: support transparent copies */ + if (gdImageGetTransparent (src) == c) { + tox++; + continue; + } + /* Have we established a mapping for this color? */ + if (src->trueColor) { + /* 2.05: remap to the palette available in the destination image. This is slow and + * works badly, but it beats crashing! Thanks to Padhrig McCarthy. + */ + mapTo = gdImageColorResolveAlpha (dst, gdTrueColorGetRed (c), gdTrueColorGetGreen (c), gdTrueColorGetBlue (c), gdTrueColorGetAlpha (c)); + } else if (colorMap[c] == (-1)) { + /* If it's the same image, mapping is trivial */ + if (dst == src) { + nc = c; + } else { + /* Get best match possible. This function never returns error. */ + nc = gdImageColorResolveAlpha (dst, src->red[c], src->green[c], src->blue[c], src->alpha[c]); + } + colorMap[c] = nc; + mapTo = colorMap[c]; + } else { + mapTo = colorMap[c]; + } + gdImageSetPixel (dst, tox, toy, mapTo); + tox++; } - colorMap[c] = nc; - } - gdImageSetPixel (dst, tox, toy, colorMap[c]); - tox++; + toy++; } - toy++; - } } /* This function is a substitute for real alpha channel operations, @@ -1950,12 +2138,12 @@ { dc = gdImageGetPixel (dst, tox, toy); - ncR = (int)( gdImageRed (src, c) * (pct / 100.0f) - + gdImageRed (dst, dc) * ((100 - pct) / 100.0f)); - ncG = (int)( gdImageGreen (src, c) * (pct / 100.0f) - + gdImageGreen (dst, dc) * ((100 - pct) / 100.0f)); - ncB = (int)( gdImageBlue (src, c) * (pct / 100.0f) - + gdImageBlue (dst, dc) * ((100 - pct) / 100.0f)); + ncR = (int)(gdImageRed (src, c) * (pct / 100.0f) + + gdImageRed (dst, dc) * ((100 - pct) / 100.0f)); + ncG = (int)(gdImageGreen (src, c) * (pct / 100.0f) + + gdImageGreen (dst, dc) * ((100 - pct) / 100.0f)); + ncB = (int)(gdImageBlue (src, c) * (pct / 100.0f) + + gdImageBlue (dst, dc) * ((100 - pct) / 100.0f)); /* Find a reasonable color */ nc = gdImageColorResolve (dst, ncR, ncG, ncB); @@ -1972,185 +2160,157 @@ void gdImageCopyMergeGray (gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int srcX, int srcY, int w, int h, int pct) { - - int c, dc; - int x, y; - int tox, toy; - int ncR, ncG, ncB; - float g; - toy = dstY; - for (y = srcY; (y < (srcY + h)); y++) - { - tox = dstX; - for (x = srcX; (x < (srcX + w)); x++) - { - int nc; - c = gdImageGetPixel (src, x, y); - /* Added 7/24/95: support transparent copies */ - if (gdImageGetTransparent (src) == c) - { - tox++; - continue; - } - /* If it's the same image, mapping is trivial */ - if (dst == src) - { - nc = c; - } - else - { - dc = gdImageGetPixel (dst, tox, toy); - g = (0.29900f * gdImageRed(dst, dc)) + (0.58700f * gdImageGreen(dst, dc)) + (0.11400f * gdImageBlue(dst, dc)); - - ncR = (int)( gdImageRed (src, c) * (pct / 100.0f) - + gdImageRed (dst, dc) * g * ((100 - pct) / 100.0f)); - - ncG = (int)( gdImageGreen (src, c) * (pct / 100.0f) - + gdImageGreen (dst, dc) * g * ((100 - pct) / 100.0f)); - - ncB = (int)( gdImageBlue (src, c) * (pct / 100.0f) - + gdImageBlue (dst, dc) * g * ((100 - pct) / 100.0f)); - - - /* First look for an exact match */ - nc = gdImageColorExact (dst, ncR, ncG, ncB); - if (nc == (-1)) - { - /* No, so try to allocate it */ - nc = gdImageColorAllocate (dst, ncR, ncG, ncB); - /* If we're out of colors, go for the - closest color */ - if (nc == (-1)) - { - nc = gdImageColorClosest (dst, ncR, ncG, ncB); - } + int c, dc; + int x, y; + int tox, toy; + int ncR, ncG, ncB; + float g; + toy = dstY; + + for (y = srcY; (y < (srcY + h)); y++) { + tox = dstX; + for (x = srcX; (x < (srcX + w)); x++) { + int nc; + c = gdImageGetPixel (src, x, y); + /* Added 7/24/95: support transparent copies */ + if (gdImageGetTransparent(src) == c) { + tox++; + continue; + } + /* If it's the same image, mapping is trivial */ + if (dst == src) { + nc = c; + } else { + dc = gdImageGetPixel(dst, tox, toy); + g = (0.29900f * gdImageRed(dst, dc)) + (0.58700f * gdImageGreen(dst, dc)) + (0.11400f * gdImageBlue(dst, dc)); + + ncR = (int)(gdImageRed (src, c) * (pct / 100.0f) + gdImageRed(dst, dc) * g * ((100 - pct) / 100.0f)); + ncG = (int)(gdImageGreen (src, c) * (pct / 100.0f) + gdImageGreen(dst, dc) * g * ((100 - pct) / 100.0f)); + ncB = (int)(gdImageBlue (src, c) * (pct / 100.0f) + gdImageBlue(dst, dc) * g * ((100 - pct) / 100.0f)); + + /* First look for an exact match */ + nc = gdImageColorExact(dst, ncR, ncG, ncB); + if (nc == (-1)) { + /* No, so try to allocate it */ + nc = gdImageColorAllocate(dst, ncR, ncG, ncB); + /* If we're out of colors, go for the closest color */ + if (nc == (-1)) { + nc = gdImageColorClosest(dst, ncR, ncG, ncB); + } + } + } + gdImageSetPixel(dst, tox, toy, nc); + tox++; } - } - gdImageSetPixel (dst, tox, toy, nc); - tox++; + toy++; } - toy++; - } } void gdImageCopyResized (gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int srcX, int srcY, int dstW, int dstH, int srcW, int srcH) { - int c; - int x, y; - int tox, toy; - int ydest; - int i; - int colorMap[gdMaxColors]; - /* Stretch vectors */ - int *stx; - int *sty; - /* We only need to use floating point to determine the correct - stretch vector for one line's worth. */ - double accum; - stx = (int *) gdMalloc (sizeof (int) * srcW); - sty = (int *) gdMalloc (sizeof (int) * srcH); - accum = 0; - for (i = 0; (i < srcW); i++) - { - int got; - accum += (double) dstW / (double) srcW; - got = (int) floor (accum); - stx[i] = got; - accum -= got; - } - accum = 0; - for (i = 0; (i < srcH); i++) - { - int got; - accum += (double) dstH / (double) srcH; - got = (int) floor (accum); - sty[i] = got; - accum -= got; - } - for (i = 0; (i < gdMaxColors); i++) - { - colorMap[i] = (-1); - } - toy = dstY; - for (y = srcY; (y < (srcY + srcH)); y++) - { - for (ydest = 0; (ydest < sty[y - srcY]); ydest++) - { - tox = dstX; - for (x = srcX; (x < (srcX + srcW)); x++) - { - int nc = 0; - int mapTo; - if (!stx[x - srcX]) - { - continue; - } - if (dst->trueColor) - { - mapTo = gdImageGetTrueColorPixel (src, x, y); - /* Added 7/24/95: support transparent copies */ - if (gdImageGetTransparent (src) == mapTo) - { - tox++; - continue; - } - } - else - { - c = gdImageGetPixel (src, x, y); - /* Added 7/24/95: support transparent copies */ - if (gdImageGetTransparent (src) == c) - { - tox += stx[x - srcX]; - continue; - } - if (src->trueColor) - { - /* Remap to the palette available in the - destination image. This is slow and - works badly. */ - mapTo = gdImageColorResolveAlpha (dst, - gdTrueColorGetRed (c), - gdTrueColorGetGreen (c), - gdTrueColorGetBlue (c), - gdTrueColorGetAlpha (c)); - } - else - { - /* Have we established a mapping for this color? */ - if (colorMap[c] == (-1)) - { - /* If it's the same image, mapping is trivial */ - if (dst == src) - { - nc = c; - } - else - { - /* Find or create the best match */ - mapTo = gdImageColorResolveAlpha (dst, - gdTrueColorGetRed (c), - gdTrueColorGetGreen (c), - gdTrueColorGetBlue (c), - gdTrueColorGetAlpha (c)); - } - colorMap[c] = nc; + int c; + int x, y; + int tox, toy; + int ydest; + int i; + int colorMap[gdMaxColors]; + /* Stretch vectors */ + int *stx, *sty; + /* We only need to use floating point to determine the correct stretch vector for one line's worth. */ + double accum; + stx = (int *) gdMalloc (sizeof (int) * srcW); + sty = (int *) gdMalloc (sizeof (int) * srcH); + accum = 0; + + for (i = 0; (i < srcW); i++) { + int got; + accum += (double) dstW / (double) srcW; + got = (int) floor (accum); + stx[i] = got; + accum -= got; + } + accum = 0; + for (i = 0; (i < srcH); i++) { + int got; + accum += (double) dstH / (double) srcH; + got = (int) floor (accum); + sty[i] = got; + accum -= got; + } + for (i = 0; (i < gdMaxColors); i++) { + colorMap[i] = (-1); + } + toy = dstY; + for (y = srcY; (y < (srcY + srcH)); y++) { + for (ydest = 0; (ydest < sty[y - srcY]); ydest++) { + tox = dstX; + for (x = srcX; (x < (srcX + srcW)); x++) { + int nc = 0; + int mapTo; + if (!stx[x - srcX]) { + continue; + } + if (dst->trueColor) { + /* 2.0.9: Thorben Kundinger: Maybe the source image is not a truecolor image */ + if (!src->trueColor) { + int tmp = gdImageGetPixel (src, x, y); + mapTo = gdImageGetTrueColorPixel (src, x, y); + if (gdImageGetTransparent (src) == tmp) { + tox++; + continue; + } + } else { + /* TK: old code follows */ + mapTo = gdImageGetTrueColorPixel (src, x, y); + /* Added 7/24/95: support transparent copies */ + if (gdImageGetTransparent (src) == mapTo) { + tox++; + continue; + } + } + } else { + c = gdImageGetPixel (src, x, y); + /* Added 7/24/95: support transparent copies */ + if (gdImageGetTransparent (src) == c) { + tox += stx[x - srcX]; + continue; + } + if (src->trueColor) { + /* Remap to the palette available in the destination image. This is slow and works badly. */ + mapTo = gdImageColorResolveAlpha(dst, gdTrueColorGetRed(c), + gdTrueColorGetGreen(c), + gdTrueColorGetBlue(c), + gdTrueColorGetAlpha (c)); + } else { + /* Have we established a mapping for this color? */ + if (colorMap[c] == (-1)) { + /* If it's the same image, mapping is trivial */ + if (dst == src) { + nc = c; + } else { + /* Find or create the best match */ + /* 2.0.5: can't use gdTrueColorGetRed, etc with palette */ + nc = gdImageColorResolveAlpha(dst, gdImageRed(src, c), + gdImageGreen(src, c), + gdImageBlue(src, c), + gdImageAlpha(src, c)); + } + colorMap[c] = nc; + } + mapTo = colorMap[c]; + } + } + for (i = 0; (i < stx[x - srcX]); i++) { + gdImageSetPixel (dst, tox, toy, mapTo); + tox++; + } } - mapTo = colorMap[c]; - } - } - for (i = 0; (i < stx[x - srcX]); i++) - { - gdImageSetPixel (dst, tox, toy, mapTo); - tox++; + toy++; } - } - toy++; } - } - gdFree (stx); - gdFree (sty); + gdFree (stx); + gdFree (sty); } /* When gd 1.x was first created, floating point was to be avoided. @@ -2158,144 +2318,112 @@ arithmetic. The routine below is shamelessly, gloriously floating point. TBB */ -void -gdImageCopyResampled (gdImagePtr dst, - gdImagePtr src, - int dstX, int dstY, - int srcX, int srcY, - int dstW, int dstH, - int srcW, int srcH) +void gdImageCopyResampled (gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int srcX, int srcY, int dstW, int dstH, int srcW, int srcH) { - int x, y; - if (!dst->trueColor) - { - gdImageCopyResized ( - dst, src, dstX, dstY, srcX, srcY, dstW, dstH, - srcW, srcH); - return; - } - for (y = dstY; (y < dstY + dstH); y++) - { - for (x = dstX; (x < dstX + dstW); x++) - { - float sy1, sy2, sx1, sx2; - float sx, sy; - float spixels = 0.0f; - float red = 0.0f, green = 0.0f, blue = 0.0f, alpha = 0.0f; - float alpha_factor, alpha_sum = 0.0f, contrib_sum = 0.0f; - sy1 = ((float)(y - dstY)) * (float)srcH / - (float)dstH; - sy2 = ((float)(y + 1 - dstY)) * (float) srcH / - (float) dstH; - sy = sy1; - do - { - float yportion; - if (floorf(sy) == floorf(sy1)) - { - yportion = 1.0f - (sy - floorf(sy)); - if (yportion > sy2 - sy1) - { - yportion = sy2 - sy1; - } - sy = floorf(sy); - } - else if (sy == floorf(sy2)) - { - yportion = sy2 - floorf(sy2); - } - else - { - yportion = 1.0f; - } - sx1 = ((float)(x - dstX)) * (float) srcW / - dstW; - sx2 = ((float)(x + 1 - dstX)) * (float) srcW / - dstW; - sx = sx1; - do - { - float xportion; - float pcontribution; - int p; - if (floorf(sx) == floorf(sx1)) - { - xportion = 1.0f - (sx - floorf(sx)); - if (xportion > sx2 - sx1) - { - xportion = sx2 - sx1; + int x, y; + if (!dst->trueColor) { + gdImageCopyResized (dst, src, dstX, dstY, srcX, srcY, dstW, dstH, srcW, srcH); + return; + } + for (y = dstY; (y < dstY + dstH); y++) { + for (x = dstX; (x < dstX + dstW); x++) { + float sy1, sy2, sx1, sx2; + float sx, sy; + float spixels = 0.0f; + float red = 0.0f, green = 0.0f, blue = 0.0f, alpha = 0.0f; + float alpha_factor, alpha_sum = 0.0f, contrib_sum = 0.0f; + sy1 = ((float)(y - dstY)) * (float)srcH / (float)dstH; + sy2 = ((float)(y + 1 - dstY)) * (float) srcH / (float) dstH; + sy = sy1; + do { + float yportion; + if (floor_cast(sy) == floor_cast(sy1)) { + yportion = 1.0f - (sy - floor_cast(sy)); + if (yportion > sy2 - sy1) { + yportion = sy2 - sy1; + } + sy = floor_cast(sy); + } else if (sy == floorf(sy2)) { + yportion = sy2 - floor_cast(sy2); + } else { + yportion = 1.0f; + } + sx1 = ((float)(x - dstX)) * (float) srcW / dstW; + sx2 = ((float)(x + 1 - dstX)) * (float) srcW / dstW; + sx = sx1; + do { + float xportion; + float pcontribution; + int p; + if (floorf(sx) == floor_cast(sx1)) { + xportion = 1.0f - (sx - floor_cast(sx)); + if (xportion > sx2 - sx1) { + xportion = sx2 - sx1; + } + sx = floor_cast(sx); + } else if (sx == floorf(sx2)) { + xportion = sx2 - floor_cast(sx2); + } else { + xportion = 1.0f; + } + pcontribution = xportion * yportion; + p = gdImageGetTrueColorPixel(src, (int) sx + srcX, (int) sy + srcY); + + alpha_factor = ((gdAlphaMax - gdTrueColorGetAlpha(p))) * pcontribution; + red += gdTrueColorGetRed (p) * alpha_factor; + green += gdTrueColorGetGreen (p) * alpha_factor; + blue += gdTrueColorGetBlue (p) * alpha_factor; + alpha += gdTrueColorGetAlpha (p) * pcontribution; + alpha_sum += alpha_factor; + contrib_sum += pcontribution; + spixels += xportion * yportion; + sx += 1.0f; + } + while (sx < sx2); + + sy += 1.0f; } - sx = floorf(sx); - } - else if (sx == floorf(sx2)) - { - xportion = sx2 - floorf(sx2); - } - else - { - xportion = 1.0f; - } - pcontribution = xportion * yportion; - p = gdImageGetTrueColorPixel ( - src, - (int) sx + srcX, - (int) sy + srcY); - alpha_factor = ((gdAlphaMax - gdTrueColorGetAlpha(p))) * pcontribution; - red += gdTrueColorGetRed (p) * alpha_factor; - green += gdTrueColorGetGreen (p) * alpha_factor; - blue += gdTrueColorGetBlue (p) * alpha_factor; - alpha += gdTrueColorGetAlpha (p) * pcontribution; - alpha_sum += alpha_factor; - contrib_sum += pcontribution; - spixels += xportion * yportion; - sx += 1.0f; - } - while (sx < sx2); - sy += 1.0f; - } - while (sy < sy2); - if (spixels != 0.0f) - { - red /= spixels; - green /= spixels; - blue /= spixels; - alpha /= spixels; - } - if ( alpha_sum != 0.0f) - { - if( contrib_sum != 0.0f ) alpha_sum /= contrib_sum; - red /= alpha_sum; - green /= alpha_sum; - blue /= alpha_sum; - } - /* Clamping to allow for rounding errors above */ - if (red > 255.0f) - { - red = 255.0f; - } - if (green > 255.0f) - { - green = 255.0f; - } - if (blue > 255.0f) - { - blue = 255.0f; - } - if (alpha > gdAlphaMax) - { - alpha = gdAlphaMax; - } - gdImageSetPixel (dst, - x, y, - gdTrueColorAlpha ((int) red, - (int) green, - (int) blue, - (int) alpha)); + + while (sy < sy2); + + if (spixels != 0.0f) { + red /= spixels; + green /= spixels; + blue /= spixels; + alpha /= spixels; + } + if ( alpha_sum != 0.0f) { + if( contrib_sum != 0.0f) { + alpha_sum /= contrib_sum; + } + red /= alpha_sum; + green /= alpha_sum; + blue /= alpha_sum; + } + /* Clamping to allow for rounding errors above */ + if (red > 255.0f) { + red = 255.0f; + } + if (green > 255.0f) { + green = 255.0f; + } + if (blue > 255.0f) { + blue = 255.0f; + } + if (alpha > gdAlphaMax) { + alpha = gdAlphaMax; + } + gdImageSetPixel(dst, x, y, gdTrueColorAlpha ((int) red, (int) green, (int) blue, (int) alpha)); + } } - } } +/* + * Rotate function Added on 2003/12 + * by Pierre-Alain Joye (pajoye@pearfr.org) + **/ +/* Begin rotate function */ #ifdef ROTATE_PI #undef ROTATE_PI #endif /* ROTATE_PI */ @@ -2307,7 +2435,7 @@ int i, r, g, b, a; FuncPtr f; - int pxlOldLeft, pxlLeft, pxlSrc; + int pxlOldLeft, pxlLeft=0, pxlSrc; if (src->trueColor) { f = gdImageGetTrueColorPixel; @@ -2393,7 +2521,7 @@ typedef int (*FuncPtr)(gdImagePtr, int, int); int i, iYPos=0, r, g, b, a; FuncPtr f; - int pxlOldLeft, pxlLeft, pxlSrc; + int pxlOldLeft, pxlLeft=0, pxlSrc; if (src->trueColor) { f = gdImageGetTrueColorPixel; @@ -2477,10 +2605,10 @@ FuncPtr f; if (src->trueColor) { - dst = gdImageCreateTrueColor ( src->sx,src->sy); + dst = gdImageCreateTrueColor(src->sy, src->sx); f = gdImageGetTrueColorPixel; } else { - dst = gdImageCreate (src->sx, src->sy); + dst = gdImageCreate (src->sy, src->sx); f = gdImageGetPixel; } @@ -2508,10 +2636,10 @@ FuncPtr f; if (src->trueColor) { - dst = gdImageCreateTrueColor(src->sy, src->sx); + dst = gdImageCreateTrueColor ( src->sx,src->sy); f = gdImageGetTrueColorPixel; } else { - dst = gdImageCreate (src->sy, src->sx); + dst = gdImageCreate (src->sx, src->sy); f = gdImageGetPixel; } @@ -2727,7 +2855,9 @@ return rotatedImg; } +/* End Rotate function */ +#if MBO_0 gdImagePtr gdImageCreateFromXbm (FILE * fd) { @@ -2801,7 +2931,7 @@ for (i = 0; (i < bytes); i++) { char h[3]; - int b; + unsigned int b; /* Skip spaces, commas, CRs, 0x */ while (1) { @@ -2847,32 +2977,39 @@ } } /* Shouldn't happen */ - fprintf (stderr, "Error: bug in gdImageCreateFromXbm!\n"); + php_gd_error("Error: bug in gdImageCreateFromXbm\n"); return 0; fail: gdImageDestroy (im); return 0; } +#endif /* MBO_0 */ void gdImagePolygon (gdImagePtr im, gdPointPtr p, int n, int c) { - int i; - int lx, ly; - if (!n) - { - return; - } - lx = p->x; - ly = p->y; - gdImageLine (im, lx, ly, p[n - 1].x, p[n - 1].y, c); - for (i = 1; (i < n); i++) - { - p++; - gdImageLine (im, lx, ly, p->x, p->y, c); - lx = p->x; - ly = p->y; - } + int i; + int lx, ly; + typedef void (*image_line)(gdImagePtr im, int x1, int y1, int x2, int y2, int color); + image_line draw_line; + + if (!n) { + return; + } + if ( im->antialias) { + draw_line = gdImageAALine; + } else { + draw_line = gdImageLine; + } + lx = p->x; + ly = p->y; + draw_line(im, lx, ly, p[n - 1].x, p[n - 1].y, c); + for (i = 1; (i < n); i++) { + p++; + draw_line(im, lx, ly, p->x, p->y, c); + lx = p->x; + ly = p->y; + } } int gdCompareInt (const void *a, const void *b); @@ -3161,6 +3298,14 @@ gdImageAlphaBlending (gdImagePtr im, int alphaBlendingArg) { im->alphaBlendingFlag = alphaBlendingArg; +} + +void +gdImageAntialias (gdImagePtr im, int antialias) +{ + if (im->trueColor){ + im->antialias = antialias; + } } void Index: php4/ext/gd/libgd/gd.h diff -u php4/ext/gd/libgd/gd.h:1.7.2.3 php4/ext/gd/libgd/gd.h:1.7.2.4 --- php4/ext/gd/libgd/gd.h:1.7.2.3 Sat Feb 8 03:54:11 2003 +++ php4/ext/gd/libgd/gd.h Wed Mar 5 11:04:20 2003 @@ -30,6 +30,11 @@ #include <stdio.h> #include "gd_io.h" +void php_gd_error_ex(int type, const char *format, ...); + +void php_gd_error(const char *format, ...); + + /* The maximum number of palette entries in palette-based images. In the wonderful new world of gd 2.0, you can of course have many more colors when using truecolor mode. */ @@ -136,6 +141,8 @@ To do that, build your image as a truecolor image, then quantize down to 8 bits. */ int alphaBlendingFlag; + /* Should antialias functions be used */ + int antialias; /* Should the alpha channel of the image be saved? This affects PNG at the moment; other future formats may also have that capability. JPEG doesn't. */ @@ -239,6 +246,7 @@ int gdImageGetPixel(gdImagePtr im, int x, int y); void gdImageLine(gdImagePtr im, int x1, int y1, int x2, int y2, int color); +void gdImageAALine(gdImagePtr im, int x1, int y1, int x2, int y2, int color); /* For backwards compatibility only. Use gdImageSetStyle() for much more flexible line drawing. */ @@ -248,7 +256,6 @@ void gdImageRectangle(gdImagePtr im, int x1, int y1, int x2, int y2, int color); /* Solid bar. Upper left corner first, lower right corner second. */ void gdImageFilledRectangle(gdImagePtr im, int x1, int y1, int x2, int y2, int color); -int gdImageBoundsSafe(gdImagePtr im, int x, int y); void gdImageChar(gdImagePtr im, gdFontPtr f, int x, int y, int c, int color); void gdImageCharUp(gdImagePtr im, gdFontPtr f, int x, int y, int c, int color); void gdImageString(gdImagePtr im, gdFontPtr f, int x, int y, unsigned char *s, int color); @@ -300,6 +307,8 @@ beats the exact same color with radically different transparency */ int gdImageColorClosestAlpha(gdImagePtr im, int r, int g, int b, int a); +/* An alternate method */ +int gdImageColorClosestHWB(gdImagePtr im, int r, int g, int b); /* Returns exact, 100% opaque matches only */ int gdImageColorExact(gdImagePtr im, int r, int g, int b); /* Returns an exact match only, including alpha */ @@ -472,6 +481,7 @@ /* On or off (1 or 0) for all three of these. */ void gdImageInterlace(gdImagePtr im, int interlaceArg); void gdImageAlphaBlending(gdImagePtr im, int alphaBlendingArg); +void gdImageAntialias(gdImagePtr im, int antialias); void gdImageSaveAlpha(gdImagePtr im, int saveAlphaArg); /* Macros to access information about images. */ @@ -538,5 +548,7 @@ #ifdef __cplusplus } #endif + +#define gdImageBoundsSafe(im, x, y) (!(y < 0 || y >= (im)->sy || x < 0 || x >= (im)->sx)) #endif /* GD_H */ Index: php4/ext/gd/libgd/gd_arc_f_buggy.c diff -u php4/ext/gd/libgd/gd_arc_f_buggy.c:1.1 php4/ext/gd/libgd/gd_arc_f_buggy.c:1.1.4.1 --- php4/ext/gd/libgd/gd_arc_f_buggy.c:1.1 Fri Apr 12 22:03:08 2002 +++ php4/ext/gd/libgd/gd_arc_f_buggy.c Wed Mar 5 11:04:20 2003 @@ -726,12 +726,12 @@ out = fopen ("test/arctest.png", "wb"); if (!out) { - fprintf (stderr, "Can't create test/arctest.png\n"); + php_gd_error("Can't create test/arctest.png\n"); exit (1); } gdImagePng (im, out); fclose (out); - fprintf (stderr, "Test image written to test/arctest.png\n"); + php_gd_error("Test image written to test/arctest.png\n"); /* Destroy it */ gdImageDestroy (im); Index: php4/ext/gd/libgd/gd_gd2.c diff -u php4/ext/gd/libgd/gd_gd2.c:1.4.2.1 php4/ext/gd/libgd/gd_gd2.c:1.4.2.2 --- php4/ext/gd/libgd/gd_gd2.c:1.4.2.1 Wed Dec 4 12:28:55 2002 +++ php4/ext/gd/libgd/gd_gd2.c Wed Mar 5 11:04:20 2003 @@ -23,273 +23,248 @@ #define TRUE 1 #define FALSE 0 +/* 2.11: not part of the API, as the save routine can figure it out + * from im->trueColor, and the load routine doesn't need to tell + * the end user the saved format. NOTE: adding 2 is assumed + * to result in the correct format value for truecolor! +*/ +#define GD2_FMT_TRUECOLOR_RAW 3 +#define GD2_FMT_TRUECOLOR_COMPRESSED 4 + +#define gd2_compressed(fmt) (((fmt) == GD2_FMT_COMPRESSED) || ((fmt) == GD2_FMT_TRUECOLOR_COMPRESSED)) +#define gd2_truecolor(fmt) (((fmt) == GD2_FMT_TRUECOLOR_RAW) || ((fmt) == GD2_FMT_TRUECOLOR_COMPRESSED)) + /* Use this for commenting out debug-print statements. */ /* Just use the first '#define' to allow all the prints... */ -/*#define GD2_DBG(s) (s) */ +/* #define GD2_DBG(s) (s) */ #define GD2_DBG(s) typedef struct - { - int offset; - int size; - } +{ + int offset; + int size; +} t_chunk_info; -extern int _gdGetColors (gdIOCtx * in, gdImagePtr im, int gd2xFlag); -extern void _gdPutColors (gdImagePtr im, gdIOCtx * out); +extern int _gdGetColors(gdIOCtx * in, gdImagePtr im, int gd2xFlag); +extern void _gdPutColors(gdImagePtr im, gdIOCtx * out); /* */ /* Read the extra info in the gd2 header. */ /* */ -static -int -_gd2GetHeader (gdIOCtxPtr in, int *sx, int *sy, - int *cs, int *vers, int *fmt, int *ncx, int *ncy, t_chunk_info ** chunkIdx) -{ - int i; - int ch; - char id[5]; - t_chunk_info *cidx; - int sidx; - int nc; - - GD2_DBG (printf ("Reading gd2 header info\n")); - - for (i = 0; i < 4; i++) - { - ch = gdGetC (in); - if (ch == EOF) - { - goto fail1; - }; - id[i] = ch; - }; - id[4] = 0; - - GD2_DBG (printf ("Got file code: %s\n", id)); - - /* Equiv. of 'magick'. */ - if (strcmp (id, GD2_ID) != 0) - { - GD2_DBG (printf ("Not a valid gd2 file\n")); - goto fail1; - }; - - /* Version */ - if (gdGetWord (vers, in) != 1) - { - goto fail1; - }; - GD2_DBG (printf ("Version: %d\n", *vers)); - - if ((*vers != 1) && (*vers != 2)) - { - GD2_DBG (printf ("Bad version: %d\n", *vers)); - goto fail1; - }; - - /* Image Size */ - if (!gdGetWord (sx, in)) - { - GD2_DBG (printf ("Could not get x-size\n")); - goto fail1; - } - if (!gdGetWord (sy, in)) - { - GD2_DBG (printf ("Could not get y-size\n")); - goto fail1; - } - GD2_DBG (printf ("Image is %dx%d\n", *sx, *sy)); - - /* Chunk Size (pixels, not bytes!) */ - if (gdGetWord (cs, in) != 1) - { - goto fail1; - }; - GD2_DBG (printf ("ChunkSize: %d\n", *cs)); - - if ((*cs < GD2_CHUNKSIZE_MIN) || (*cs > GD2_CHUNKSIZE_MAX)) - { - GD2_DBG (printf ("Bad chunk size: %d\n", *cs)); - goto fail1; - }; - - /* Data Format */ - if (gdGetWord (fmt, in) != 1) - { - goto fail1; - }; - GD2_DBG (printf ("Format: %d\n", *fmt)); - - if ((*fmt != GD2_FMT_RAW) && (*fmt != GD2_FMT_COMPRESSED)) - { - GD2_DBG (printf ("Bad data format: %d\n", *fmt)); - goto fail1; - }; - - - /* # of chunks wide */ - if (gdGetWord (ncx, in) != 1) - { - goto fail1; - }; - GD2_DBG (printf ("%d Chunks Wide\n", *ncx)); - - /* # of chunks high */ - if (gdGetWord (ncy, in) != 1) - { - goto fail1; - }; - GD2_DBG (printf ("%d Chunks vertically\n", *ncy)); - - if ((*fmt) == GD2_FMT_COMPRESSED) - { - nc = (*ncx) * (*ncy); - GD2_DBG (printf ("Reading %d chunk index entries\n", nc)); - sidx = sizeof (t_chunk_info) * nc; - cidx = gdCalloc (sidx, 1); - for (i = 0; i < nc; i++) - { - if (gdGetInt (&cidx[i].offset, in) != 1) - { - goto fail1; - }; - if (gdGetInt (&cidx[i].size, in) != 1) - { - goto fail1; - }; - }; - *chunkIdx = cidx; - }; +static int _gd2GetHeader(gdIOCtxPtr in, int *sx, int *sy, int *cs, int *vers, int *fmt, int *ncx, int *ncy, t_chunk_info ** chunkIdx) +{ + int i; + int ch; + char id[5]; + t_chunk_info *cidx; + int sidx; + int nc; + + GD2_DBG(php_gd_error("Reading gd2 header info\n")); + + for (i = 0; i < 4; i++) { + ch = gdGetC(in); + if (ch == EOF) { + goto fail1; + } + id[i] = ch; + } + id[4] = 0; - GD2_DBG (printf ("gd2 header complete\n")); + GD2_DBG(php_gd_error("Got file code: %s\n", id)); - return 1; + /* Equiv. of 'magick'. */ + if (strcmp(id, GD2_ID) != 0) { + GD2_DBG(php_gd_error("Not a valid gd2 file\n")); + goto fail1; + } + + /* Version */ + if (gdGetWord(vers, in) != 1) { + goto fail1; + } + GD2_DBG(php_gd_error("Version: %d\n", *vers)); + + if ((*vers != 1) && (*vers != 2)) { + GD2_DBG(php_gd_error("Bad version: %d\n", *vers)); + goto fail1; + } + + /* Image Size */ + if (!gdGetWord(sx, in)) { + GD2_DBG(php_gd_error("Could not get x-size\n")); + goto fail1; + } + if (!gdGetWord(sy, in)) { + GD2_DBG(php_gd_error("Could not get y-size\n")); + goto fail1; + } + GD2_DBG(php_gd_error("Image is %dx%d\n", *sx, *sy)); + + /* Chunk Size (pixels, not bytes!) */ + if (gdGetWord(cs, in) != 1) { + goto fail1; + } + GD2_DBG(php_gd_error("ChunkSize: %d\n", *cs)); + + if ((*cs < GD2_CHUNKSIZE_MIN) || (*cs > GD2_CHUNKSIZE_MAX)) { + GD2_DBG(php_gd_error("Bad chunk size: %d\n", *cs)); + goto fail1; + } + + /* Data Format */ + if (gdGetWord(fmt, in) != 1) { + goto fail1; + } + GD2_DBG(php_gd_error("Format: %d\n", *fmt)); + + if ((*fmt != GD2_FMT_RAW) && (*fmt != GD2_FMT_COMPRESSED) && (*fmt != GD2_FMT_TRUECOLOR_RAW) && (*fmt != GD2_FMT_TRUECOLOR_COMPRESSED)) { + GD2_DBG(php_gd_error("Bad data format: %d\n", *fmt)); + goto fail1; + } + + /* # of chunks wide */ + if (gdGetWord(ncx, in) != 1) { + goto fail1; + } + GD2_DBG(php_gd_error("%d Chunks Wide\n", *ncx)); + + /* # of chunks high */ + if (gdGetWord(ncy, in) != 1) { + goto fail1; + } + GD2_DBG(php_gd_error("%d Chunks vertically\n", *ncy)); + + if (gd2_compressed(*fmt)) { + nc = (*ncx) * (*ncy); + GD2_DBG(php_gd_error("Reading %d chunk index entries\n", nc)); + sidx = sizeof(t_chunk_info) * nc; + cidx = gdCalloc(sidx, 1); + for (i = 0; i < nc; i++) { + if (gdGetInt(&cidx[i].offset, in) != 1) { + goto fail1; + } + if (gdGetInt(&cidx[i].size, in) != 1) { + goto fail1; + } + } + *chunkIdx = cidx; + } + + GD2_DBG(php_gd_error("gd2 header complete\n")); + + return 1; fail1: - return 0; + return 0; } -static - gdImagePtr -_gd2CreateFromFile (gdIOCtxPtr in, int *sx, int *sy, - int *cs, int *vers, int *fmt, - int *ncx, int *ncy, t_chunk_info ** cidx) -{ - gdImagePtr im; - - if (_gd2GetHeader (in, sx, sy, cs, vers, fmt, ncx, ncy, cidx) != 1) - { - GD2_DBG (printf ("Bad GD2 header\n")); - goto fail1; - } - - im = gdImageCreateTrueColor(*sx, *sy); - if (im == NULL) - { - GD2_DBG (printf ("Could not create gdImage\n")); - goto fail1; - }; - - if (!_gdGetColors (in, im, (*vers) == 2)) - { - GD2_DBG (printf ("Could not read color palette\n")); - goto fail2; - } - GD2_DBG (printf ("Image palette completed: %d colours\n", im->colorsTotal)); +static gdImagePtr _gd2CreateFromFile (gdIOCtxPtr in, int *sx, int *sy, int *cs, int *vers, int *fmt, int *ncx, int *ncy, t_chunk_info ** cidx) +{ + gdImagePtr im; + + if (_gd2GetHeader (in, sx, sy, cs, vers, fmt, ncx, ncy, cidx) != 1) { + GD2_DBG(php_gd_error("Bad GD2 header\n")); + goto fail1; + } + + if (gd2_truecolor(*fmt)) { + im = gdImageCreateTrueColor(*sx, *sy); + } else { + im = gdImageCreate(*sx, *sy); + } + if (im == NULL) { + GD2_DBG(php_gd_error("Could not create gdImage\n")); + goto fail1; + } - return im; + if (!_gdGetColors(in, im, (*vers) == 2)) { + GD2_DBG(php_gd_error("Could not read color palette\n")); + goto fail2; + } + GD2_DBG(php_gd_error("Image palette completed: %d colours\n", im->colorsTotal)); + + return im; fail2: - gdImageDestroy (im); - return 0; + gdImageDestroy(im); + return 0; fail1: - return 0; + return 0; +} + +static int _gd2ReadChunk (int offset, char *compBuf, int compSize, char *chunkBuf, uLongf * chunkLen, gdIOCtx * in) +{ + int zerr; + if (gdTell(in) != offset) { + GD2_DBG(php_gd_error("Positioning in file to %d\n", offset)); + gdSeek(in, offset); + } else { + GD2_DBG(php_gd_error("Already Positioned in file to %d\n", offset)); + } + + /* Read and uncompress an entire chunk. */ + GD2_DBG(php_gd_error("Reading file\n")); + if (gdGetBuf(compBuf, compSize, in) != compSize) { + return FALSE; + } + GD2_DBG(php_gd_error("Got %d bytes. Uncompressing into buffer of %d bytes\n", compSize, (int)*chunkLen)); + zerr = uncompress((unsigned char *) chunkBuf, chunkLen, (unsigned char *) compBuf, compSize); + if (zerr != Z_OK) { + GD2_DBG(php_gd_error("Error %d from uncompress\n", zerr)); + return FALSE; + } + GD2_DBG(php_gd_error("Got chunk\n")); + + return TRUE; } -static -int -_gd2ReadChunk (int offset, char *compBuf, int compSize, char *chunkBuf, uLongf * chunkLen, gdIOCtx * in) -{ - int zerr; - - if (gdTell (in) != offset) - { - GD2_DBG (printf ("Positioning in file to %d\n", offset)); - gdSeek (in, offset); - } - else - { - GD2_DBG (printf ("Already Positioned in file to %d\n", offset)); - }; - - /* Read and uncompress an entire chunk. */ - GD2_DBG (printf ("Reading file\n")); - if (gdGetBuf (compBuf, compSize, in) != compSize) - { - return FALSE; - }; - GD2_DBG (printf ("Got %d bytes. Uncompressing into buffer of %d bytes\n", compSize, *chunkLen)); - zerr = uncompress ((unsigned char *) chunkBuf, chunkLen, - (unsigned char *) compBuf, compSize); - if (zerr != Z_OK) - { - GD2_DBG (printf ("Error %d from uncompress\n", zerr)); - return FALSE; - }; - GD2_DBG (printf ("Got chunk\n")); - return TRUE; -} - -gdImagePtr -gdImageCreateFromGd2 (FILE * inFile) -{ - gdIOCtx *in = gdNewFileCtx (inFile); - gdImagePtr im; - - im = gdImageCreateFromGd2Ctx (in); - - in->gd_free (in); - - return im; -} - -gdImagePtr -gdImageCreateFromGd2Ctx (gdIOCtxPtr in) -{ - int sx, sy; - int i; - int ncx, ncy, nc, cs, cx, cy; - int x, y, ylo, yhi, xlo, xhi; - int vers, fmt; - t_chunk_info *chunkIdx = NULL; /* So we can gdFree it with impunity. */ - unsigned char *chunkBuf = NULL; /* So we can gdFree it with impunity. */ - int chunkNum = 0; - int chunkMax = 0; - uLongf chunkLen; - int chunkPos = 0; - int compMax = 0; - int bytesPerPixel; - char *compBuf = NULL; /* So we can gdFree it with impunity. */ - - gdImagePtr im; - - /* Get the header */ - im = _gd2CreateFromFile (in, &sx, &sy, &cs, &vers, &fmt, &ncx, &ncy, &chunkIdx); - - if (im == NULL) - { - return 0; - }; - bytesPerPixel = im->trueColor ? 4 : 1; - nc = ncx * ncy; +gdImagePtr gdImageCreateFromGd2 (FILE * inFile) +{ + gdIOCtx *in = gdNewFileCtx(inFile); + gdImagePtr im; + + im = gdImageCreateFromGd2Ctx(in); + + in->gd_free(in); + + return im; +} - if (fmt == GD2_FMT_COMPRESSED) { +gdImagePtr gdImageCreateFromGd2Ctx (gdIOCtxPtr in) +{ + int sx, sy; + int i; + int ncx, ncy, nc, cs, cx, cy; + int x, y, ylo, yhi, xlo, xhi; + int vers, fmt; + t_chunk_info *chunkIdx = NULL; /* So we can gdFree it with impunity. */ + unsigned char *chunkBuf = NULL; /* So we can gdFree it with impunity. */ + int chunkNum = 0; + int chunkMax = 0; + uLongf chunkLen; + int chunkPos = 0; + int compMax = 0; + int bytesPerPixel; + char *compBuf = NULL; /* So we can gdFree it with impunity. */ + + gdImagePtr im; + + /* Get the header */ + if (!(im = _gd2CreateFromFile(in, &sx, &sy, &cs, &vers, &fmt, &ncx, &ncy, &chunkIdx))) { + return 0; + } + + bytesPerPixel = im->trueColor ? 4 : 1; + nc = ncx * ncy; + + if (gd2_compressed(fmt)) { /* Find the maximum compressed chunk size. */ compMax = 0; - for (i = 0; i < nc; i++) { + for (i = 0; (i < nc); i++) { if (chunkIdx[i].size > compMax) { compMax = chunkIdx[i].size; } @@ -298,47 +273,50 @@ /* Allocate buffers */ chunkMax = cs * bytesPerPixel * cs; - chunkBuf = gdCalloc (chunkMax, 1); - compBuf = gdCalloc (compMax, 1); - GD2_DBG(printf("Largest compressed chunk is %d bytes\n", compMax)); + chunkBuf = gdCalloc(chunkMax, 1); + compBuf = gdCalloc(compMax, 1); + + GD2_DBG(php_gd_error("Largest compressed chunk is %d bytes\n", compMax)); } /* Read the data... */ - for (cy = 0; cy < ncy; cy++) { - for (cx = 0; cx < ncx; cx++) { + for (cy = 0; (cy < ncy); cy++) { + for (cx = 0; (cx < ncx); cx++) { ylo = cy * cs; yhi = ylo + cs; if (yhi > im->sy) { yhi = im->sy; } - GD2_DBG(printf("Processing Chunk %d (%d, %d), y from %d to %d\n", chunkNum, cx, cy, ylo, yhi)); - if (fmt == GD2_FMT_COMPRESSED) { + GD2_DBG(php_gd_error("Processing Chunk %d (%d, %d), y from %d to %d\n", chunkNum, cx, cy, ylo, yhi)); + + if (gd2_compressed(fmt)) { chunkLen = chunkMax; - if (!_gd2ReadChunk (chunkIdx[chunkNum].offset, compBuf, chunkIdx[chunkNum].size, chunkBuf, &chunkLen, in)) { - GD2_DBG(printf("Error reading comproessed chunk\n")); + if (!_gd2ReadChunk(chunkIdx[chunkNum].offset, compBuf, chunkIdx[chunkNum].size, chunkBuf, &chunkLen, in)) { + GD2_DBG(php_gd_error("Error reading comproessed chunk\n")); goto fail2; } + chunkPos = 0; } - for (y = ylo; y < yhi; y++) { + for (y = ylo; (y < yhi); y++) { xlo = cx * cs; xhi = xlo + cs; if (xhi > im->sx) { xhi = im->sx; } - if (fmt == GD2_FMT_RAW) { + if (!gd2_compressed(fmt)) { for (x = xlo; x < xhi; x++) { if (im->trueColor) { - if (!gdGetInt (&im->tpixels[y][x], in)) { + if (!gdGetInt(&im->tpixels[y][x], in)) { im->tpixels[y][x] = 0; } } else { int ch; - if (!gdGetByte (&ch, in)) { + if (!gdGetByte(&ch, in)) { ch = 0; } im->pixels[y][x] = ch; @@ -347,6 +325,7 @@ } else { for (x = xlo; x < xhi; x++) { if (im->trueColor) { + /* 2.0.1: work around a gcc bug by being verbose. TBB */ int a = chunkBuf[chunkPos++] << 24; int r = chunkBuf[chunkPos++] << 16; int g = chunkBuf[chunkPos++] << 8; @@ -362,517 +341,449 @@ } } - GD2_DBG(printf("Freeing memory\n")); + GD2_DBG(php_gd_error("Freeing memory\n")); - gdFree (chunkBuf); - gdFree (compBuf); - gdFree (chunkIdx); + if (chunkBuf) { + gdFree(chunkBuf); + } + if (compBuf) { + gdFree(compBuf); + } + if (chunkIdx) { + gdFree(chunkIdx); + } - GD2_DBG(printf("Done\n")); + GD2_DBG(php_gd_error("Done\n")); return im; fail2: - gdImageDestroy (im); - gdFree (chunkBuf); - gdFree (compBuf); - gdFree (chunkIdx); + gdImageDestroy(im); + if (chunkBuf) { + gdFree(chunkBuf); + } + if (compBuf) { + gdFree(compBuf); + } + if (chunkIdx) { + gdFree(chunkIdx); + } + return 0; } -gdImagePtr -gdImageCreateFromGd2Part (FILE * inFile, int srcx, int srcy, int w, int h) +gdImagePtr gdImageCreateFromGd2Part (FILE * inFile, int srcx, int srcy, int w, int h) +{ + gdImagePtr im; + gdIOCtx *in = gdNewFileCtx(inFile); + + im = gdImageCreateFromGd2PartCtx(in, srcx, srcy, w, h); + + in->gd_free(in); + + return im; +} + +gdImagePtr gdImageCreateFromGd2PartCtx (gdIOCtx * in, int srcx, int srcy, int w, int h) { - gdImagePtr im; - gdIOCtx *in = gdNewFileCtx (inFile); + int scx, scy, ecx, ecy, fsx, fsy; + int nc, ncx, ncy, cs, cx, cy; + int x, y, ylo, yhi, xlo, xhi; + int dstart, dpos; + int i; + int ch, vers, fmt; + t_chunk_info *chunkIdx = NULL; + char *chunkBuf = NULL; + int chunkNum; + int chunkMax = 0; + uLongf chunkLen; + int chunkPos = 0; + int compMax; + char *compBuf = NULL; + + gdImagePtr im; + + /* The next few lines are basically copied from gd2CreateFromFile + * we change the file size, so don't want to use the code directly. + * but we do need to know the file size. + */ + if (_gd2GetHeader(in, &fsx, &fsy, &cs, &vers, &fmt, &ncx, &ncy, &chunkIdx) != 1) { + goto fail1; + } - im = gdImageCreateFromGd2PartCtx (in, srcx, srcy, w, h); + GD2_DBG(php_gd_error("File size is %dx%d\n", fsx, fsy)); + + /* This is the difference - make a file based on size of chunks. */ + if (gd2_truecolor(fmt)) { + im = gdImageCreateTrueColor(w, h); + } else { + im = gdImageCreate(w, h); + } + if (im == NULL) { + goto fail1; + } + + if (!_gdGetColors(in, im, vers == 2)) { + goto fail2; + } + GD2_DBG(php_gd_error("Image palette completed: %d colours\n", im->colorsTotal)); + + /* Process the header info */ + nc = ncx * ncy; + + if (gd2_compressed(fmt)) { + /* Find the maximum compressed chunk size. */ + compMax = 0; + for (i = 0; (i < nc); i++) { + if (chunkIdx[i].size > compMax) { + compMax = chunkIdx[i].size; + } + } + compMax++; - in->gd_free (in); - - return im; -} - -gdImagePtr -gdImageCreateFromGd2PartCtx (gdIOCtx * in, int srcx, int srcy, int w, int h) -{ - int scx, scy, ecx, ecy, fsx, fsy; - int nc, ncx, ncy, cs, cx, cy; - int x, y, ylo, yhi, xlo, xhi; - int dstart, dpos; - int i; - int ch, vers, fmt; - t_chunk_info *chunkIdx = NULL; - char *chunkBuf = NULL; - int chunkNum; - int chunkMax = 0; - uLongf chunkLen; - int chunkPos = 0; - int compMax; - char *compBuf = NULL; - - gdImagePtr im; - - /* */ - /* The next few lines are basically copied from gd2CreateFromFile */ - /* - we change the file size, so don't want to use the code directly. */ - /* but we do need to know the file size. */ - /* */ - if (_gd2GetHeader (in, &fsx, &fsy, &cs, &vers, &fmt, &ncx, &ncy, &chunkIdx) != 1) - { - goto fail1; - } - - GD2_DBG (printf ("File size is %dx%d\n", fsx, fsy)); - - /* This is the difference - make a file based on size of chunks. */ - im = gdImageCreate (w, h); - if (im == NULL) - { - goto fail1; - }; - - if (!_gdGetColors (in, im, vers == 2)) - { - goto fail2; - } - GD2_DBG (printf ("Image palette completed: %d colours\n", im->colorsTotal)); - - /* Process the header info */ - nc = ncx * ncy; - - if (fmt == GD2_FMT_COMPRESSED) - { - /* Find the maximum compressed chunk size. */ - compMax = 0; - for (i = 0; (i < nc); i++) - { - if (chunkIdx[i].size > compMax) - { - compMax = chunkIdx[i].size; - }; - }; - compMax++; - - if (im->trueColor) - { - chunkMax = cs * cs * 4; - } - else - { - chunkMax = cs * cs; - } - chunkBuf = gdCalloc (chunkMax, 1); - compBuf = gdCalloc (compMax, 1); - }; - -/* Don't bother with this... */ -/* if ( (ncx != sx / cs) || (ncy != sy / cs)) { */ -/* goto fail2; */ -/* }; */ - - - /* Work out start/end chunks */ - scx = srcx / cs; - scy = srcy / cs; - if (scx < 0) - { - scx = 0; - }; - if (scy < 0) - { - scy = 0; - }; - - ecx = (srcx + w) / cs; - ecy = (srcy + h) / cs; - if (ecx >= ncx) - { - ecx = ncx - 1; - }; - if (ecy >= ncy) - { - ecy = ncy - 1; - }; - - /* Remember file position of image data. */ - dstart = gdTell (in); - GD2_DBG (printf ("Data starts at %d\n", dstart)); - - /* Loop through the chunks. */ - for (cy = scy; (cy <= ecy); cy++) - { - - ylo = cy * cs; - yhi = ylo + cs; - if (yhi > fsy) - { - yhi = fsy; - }; - - for (cx = scx; (cx <= ecx); cx++) - { - - xlo = cx * cs; - xhi = xlo + cs; - if (xhi > fsx) - { - xhi = fsx; - }; - - GD2_DBG (printf ("Processing Chunk (%d, %d), from %d to %d\n", cx, cy, ylo, yhi)); - - if (fmt == GD2_FMT_RAW) - { - GD2_DBG (printf ("Using raw format data\n")); - if (im->trueColor) - { - dpos = (cy * (cs * fsx) + cx * cs * (yhi - ylo) * 4) + dstart; + if (im->trueColor) { + chunkMax = cs * cs * 4; + } else { + chunkMax = cs * cs; } - else - { - dpos = cy * (cs * fsx) + cx * cs * (yhi - ylo) + dstart; + chunkBuf = gdCalloc(chunkMax, 1); + compBuf = gdCalloc(compMax, 1); + } + + /* Work out start/end chunks */ + scx = srcx / cs; + scy = srcy / cs; + if (scx < 0) { + scx = 0; + } + if (scy < 0) { + scy = 0; + } + + ecx = (srcx + w) / cs; + ecy = (srcy + h) / cs; + if (ecx >= ncx) { + ecx = ncx - 1; + } + if (ecy >= ncy) { + ecy = ncy - 1; + } + + /* Remember file position of image data. */ + dstart = gdTell(in); + GD2_DBG(php_gd_error("Data starts at %d\n", dstart)); + + /* Loop through the chunks. */ + for (cy = scy; (cy <= ecy); cy++) { + ylo = cy * cs; + yhi = ylo + cs; + if (yhi > fsy) { + yhi = fsy; } - if (gdSeek (in, dpos) != 0) - { - printf ("Error from seek: %d\n", errno); - goto fail2; - }; - GD2_DBG (printf ("Reading (%d, %d) from position %d\n", cx, cy, dpos - dstart)); - } - else - { - chunkNum = cx + cy * ncx; - - chunkLen = chunkMax; - if (!_gd2ReadChunk (chunkIdx[chunkNum].offset, - compBuf, - chunkIdx[chunkNum].size, - chunkBuf, &chunkLen, in)) - { - printf ("Error reading comproessed chunk\n"); - goto fail2; - }; - chunkPos = 0; - GD2_DBG (printf ("Reading (%d, %d) from chunk %d\n", cx, cy, chunkNum)); - }; - - GD2_DBG (printf (" into (%d, %d) - (%d, %d)\n", xlo, ylo, xhi, yhi)); - for (y = ylo; (y < yhi); y++) - { - - for (x = xlo; x < xhi; x++) - { - if (fmt == GD2_FMT_RAW) - { - if (im->trueColor) - { - if (!gdGetInt (&ch, in)) - { - ch = 0; - /*printf("EOF while reading file\n"); */ - /*goto fail2; */ - } - } - else - { - ch = gdGetC (in); - if (ch == EOF) - { - ch = 0; - /*printf("EOF while reading file\n"); */ - /*goto fail2; */ - } - } - } - else - { - if (im->trueColor) - { - ch = chunkBuf[chunkPos++]; - ch = (ch << 8) + chunkBuf[chunkPos++]; - ch = (ch << 8) + chunkBuf[chunkPos++]; - ch = (ch << 8) + chunkBuf[chunkPos++]; - } - else - { - ch = chunkBuf[chunkPos++]; - } - }; - - /* Only use a point that is in the image. */ - if ((x >= srcx) && (x < (srcx + w)) && (x < fsx) && (x >= 0) - && (y >= srcy) && (y < (srcy + h)) && (y < fsy) && (y >= 0) - ) - { - im->pixels[y - srcy][x - srcx] = ch; - } - }; - }; - }; - }; - - gdFree (chunkBuf); - gdFree (compBuf); - gdFree (chunkIdx); + for (cx = scx; cx <= ecx; cx++) { - return im; + xlo = cx * cs; + xhi = xlo + cs; + if (xhi > fsx) { + xhi = fsx; + } + + GD2_DBG(php_gd_error("Processing Chunk (%d, %d), from %d to %d\n", cx, cy, ylo, yhi)); + + if (!gd2_compressed(fmt)) { + GD2_DBG(php_gd_error("Using raw format data\n")); + if (im->trueColor) { + dpos = (cy * (cs * fsx) * 4 + cx * cs * (yhi - ylo) * 4) + dstart; + } else { + dpos = cy * (cs * fsx) + cx * cs * (yhi - ylo) + dstart; + } + + /* gd 2.0.11: gdSeek returns TRUE on success, not 0. Longstanding bug. 01/16/03 */ + if (!gdSeek(in, dpos)) { + php_gd_error_ex(E_WARNING, "Error from seek: %d\n", errno); + goto fail2; + } + GD2_DBG(php_gd_error("Reading (%d, %d) from position %d\n", cx, cy, dpos - dstart)); + } else { + chunkNum = cx + cy * ncx; + + chunkLen = chunkMax; + if (!_gd2ReadChunk (chunkIdx[chunkNum].offset, compBuf, chunkIdx[chunkNum].size, chunkBuf, &chunkLen, in)) { + php_gd_error("Error reading comproessed chunk\n"); + goto fail2; + } + chunkPos = 0; + GD2_DBG(php_gd_error("Reading (%d, %d) from chunk %d\n", cx, cy, chunkNum)); + } + + GD2_DBG(php_gd_error(" into (%d, %d) - (%d, %d)\n", xlo, ylo, xhi, yhi)); + + for (y = ylo; (y < yhi); y++) { + for (x = xlo; x < xhi; x++) { + if (!gd2_compressed(fmt)) { + if (im->trueColor) { + if (!gdGetInt(&ch, in)) { + ch = 0; + } + } else { + ch = gdGetC(in); + if (ch == EOF) { + ch = 0; + } + } + } else { + if (im->trueColor) { + ch = chunkBuf[chunkPos++]; + ch = (ch << 8) + chunkBuf[chunkPos++]; + ch = (ch << 8) + chunkBuf[chunkPos++]; + ch = (ch << 8) + chunkBuf[chunkPos++]; + } else { + ch = chunkBuf[chunkPos++]; + } + } + + /* Only use a point that is in the image. */ + if ((x >= srcx) && (x < (srcx + w)) && (x < fsx) && (x >= 0) && (y >= srcy) && (y < (srcy + h)) && (y < fsy) && (y >= 0)) { + if (im->trueColor) { + im->tpixels[y - srcy][x - srcx] = ch; + } else { + im->pixels[y - srcy][x - srcx] = ch; + } + } + } + } + } + } + + if (chunkBuf) { + gdFree(chunkBuf); + } + if (compBuf) { + gdFree(compBuf); + } + if (chunkIdx) { + gdFree(chunkIdx); + } + + return im; fail2: - gdImageDestroy (im); + gdImageDestroy(im); fail1: - gdFree (chunkBuf); - gdFree (compBuf); - gdFree (chunkIdx); - - return 0; - -} - -static -void -_gd2PutHeader (gdImagePtr im, gdIOCtx * out, int cs, int fmt, int cx, int cy) -{ - int i; - - /* Send the gd2 id, to verify file format. */ - for (i = 0; i < 4; i++) - { - gdPutC ((unsigned char) (GD2_ID[i]), out); - }; - - /* */ - /* We put the version info first, so future versions can easily change header info. */ - /* */ - gdPutWord (GD2_VERS, out); - gdPutWord (im->sx, out); - gdPutWord (im->sy, out); - gdPutWord (cs, out); - gdPutWord (fmt, out); - gdPutWord (cx, out); - gdPutWord (cy, out); - -} - -static void -_gdImageGd2 (gdImagePtr im, gdIOCtx * out, int cs, int fmt) -{ - int ncx, ncy, cx, cy; - int x, y, ylo, yhi, xlo, xhi; - int chunkLen; - int chunkNum = 0; - char *chunkData = NULL; /* So we can gdFree it with impunity. */ - char *compData = NULL; /* So we can gdFree it with impunity. */ - uLongf compLen; - int idxPos = 0; - int idxSize; - t_chunk_info *chunkIdx = NULL; - int posSave; - int bytesPerPixel = im->trueColor ? 4 : 1; - int compMax = 0; - - /*printf("Trying to write GD2 file\n"); */ - - /* */ - /* Force fmt to a valid value since we don't return anything. */ - /* */ - if ((fmt == 0) || ((fmt != GD2_FMT_RAW) && (fmt != GD2_FMT_COMPRESSED))) - { - fmt = GD2_FMT_COMPRESSED; - }; - - /* */ - /* Make sure chunk size is valid. These are arbitrary values; 64 because it seems */ - /* a little silly to expect performance improvements on a 64x64 bit scale, and */ - /* 4096 because we buffer one chunk, and a 16MB buffer seems a little largei - it may be */ - /* OK for one user, but for another to read it, they require the buffer. */ - /* */ - if (cs == 0) - { - cs = GD2_CHUNKSIZE; - } - else if (cs < GD2_CHUNKSIZE_MIN) - { - cs = GD2_CHUNKSIZE_MIN; - } - else if (cs > GD2_CHUNKSIZE_MAX) - { - cs = GD2_CHUNKSIZE_MAX; - }; - - /* Work out number of chunks. */ - ncx = im->sx / cs + 1; - ncy = im->sy / cs + 1; - - /* Write the standard header. */ - _gd2PutHeader (im, out, cs, fmt, ncx, ncy); - - if (fmt == GD2_FMT_COMPRESSED) - { - /* */ - /* Work out size of buffer for compressed data, If CHUNKSIZE is large, */ - /* then these will be large! */ - /* */ - /* The zlib notes say output buffer size should be (input size) * 1.01 * 12 */ - /* - we'll use 1.02 to be paranoid. */ - /* */ - compMax = (int)(cs * bytesPerPixel * cs * 1.02 + 12); - - /* */ - /* Allocate the buffers. */ - /* */ - chunkData = gdCalloc (cs * bytesPerPixel * cs, 1); - compData = gdCalloc (compMax, 1); - - /* */ - /* Save the file position of chunk index, and allocate enough space for */ - /* each chunk_info block . */ - /* */ - idxPos = gdTell (out); - idxSize = ncx * ncy * sizeof (t_chunk_info); - GD2_DBG (printf ("Index size is %d\n", idxSize)); - gdSeek (out, idxPos + idxSize); - - chunkIdx = gdCalloc (idxSize * sizeof (t_chunk_info), 1); - }; - - _gdPutColors (im, out); - - GD2_DBG (printf ("Size: %dx%d\n", im->sx, im->sy)); - GD2_DBG (printf ("Chunks: %dx%d\n", ncx, ncy)); - - for (cy = 0; (cy < ncy); cy++) - { - for (cx = 0; (cx < ncx); cx++) - { - - ylo = cy * cs; - yhi = ylo + cs; - if (yhi > im->sy) - { - yhi = im->sy; - }; - - GD2_DBG (printf ("Processing Chunk (%dx%d), y from %d to %d\n", cx, cy, ylo, yhi)); - chunkLen = 0; - for (y = ylo; (y < yhi); y++) - { - - /*GD2_DBG(printf("y=%d: ",y)); */ - - xlo = cx * cs; - xhi = xlo + cs; - if (xhi > im->sx) - { - xhi = im->sx; - }; - - if (fmt == GD2_FMT_COMPRESSED) - { - for (x = xlo; x < xhi; x++) - { - GD2_DBG(printf("%d...",x)); - if (im->trueColor) - { - int p = im->tpixels[y][x]; - chunkData[chunkLen++] = gdTrueColorGetAlpha (p); - chunkData[chunkLen++] = gdTrueColorGetRed (p); - chunkData[chunkLen++] = gdTrueColorGetGreen (p); - chunkData[chunkLen++] = gdTrueColorGetBlue (p); - } - else - { - chunkData[chunkLen++] = im->pixels[y][x]; + if (chunkBuf) { + gdFree(chunkBuf); + } + if (compBuf) { + gdFree(compBuf); + } + if (chunkIdx) { + gdFree(chunkIdx); + } + + return 0; +} + +static void _gd2PutHeader (gdImagePtr im, gdIOCtx * out, int cs, int fmt, int cx, int cy) +{ + int i; + + /* Send the gd2 id, to verify file format. */ + for (i = 0; i < 4; i++) { + gdPutC((unsigned char) (GD2_ID[i]), out); + } + + /* We put the version info first, so future versions can easily change header info. */ + + gdPutWord(GD2_VERS, out); + gdPutWord(im->sx, out); + gdPutWord(im->sy, out); + gdPutWord(cs, out); + gdPutWord(fmt, out); + gdPutWord(cx, out); + gdPutWord(cy, out); +} + +static void _gdImageGd2 (gdImagePtr im, gdIOCtx * out, int cs, int fmt) +{ + int ncx, ncy, cx, cy; + int x, y, ylo, yhi, xlo, xhi; + int chunkLen; + int chunkNum = 0; + char *chunkData = NULL; /* So we can gdFree it with impunity. */ + char *compData = NULL; /* So we can gdFree it with impunity. */ + uLongf compLen; + int idxPos = 0; + int idxSize; + t_chunk_info *chunkIdx = NULL; /* So we can gdFree it with impunity. */ + int posSave; + int bytesPerPixel = im->trueColor ? 4 : 1; + int compMax = 0; + + /* Force fmt to a valid value since we don't return anything. */ + if ((fmt != GD2_FMT_RAW) && (fmt != GD2_FMT_COMPRESSED)) { + fmt = im->trueColor ? GD2_FMT_TRUECOLOR_COMPRESSED : GD2_FMT_COMPRESSED; + } + if (im->trueColor) { + fmt += 2; + } + /* Make sure chunk size is valid. These are arbitrary values; 64 because it seems + * a little silly to expect performance improvements on a 64x64 bit scale, and + * 4096 because we buffer one chunk, and a 16MB buffer seems a little large - it may be + * OK for one user, but for another to read it, they require the buffer. + */ + if (cs == 0) { + cs = GD2_CHUNKSIZE; + } else if (cs < GD2_CHUNKSIZE_MIN) { + cs = GD2_CHUNKSIZE_MIN; + } else if (cs > GD2_CHUNKSIZE_MAX) { + cs = GD2_CHUNKSIZE_MAX; + } + + /* Work out number of chunks. */ + ncx = im->sx / cs + 1; + ncy = im->sy / cs + 1; + + /* Write the standard header. */ + _gd2PutHeader (im, out, cs, fmt, ncx, ncy); + + if (gd2_compressed(fmt)) { + /* Work out size of buffer for compressed data, If CHUNKSIZE is large, + * then these will be large! + */ + + /* The zlib notes say output buffer size should be (input size) * 1.01 * 12 + * - we'll use 1.02 to be paranoid. + */ + compMax = (int)(cs * bytesPerPixel * cs * 1.02f) + 12; + + /* Allocate the buffers. */ + chunkData = gdCalloc(cs * bytesPerPixel * cs, 1); + compData = gdCalloc(compMax, 1); + + /* Save the file position of chunk index, and allocate enough space for + * each chunk_info block . + */ + idxPos = gdTell(out); + idxSize = ncx * ncy * sizeof(t_chunk_info); + GD2_DBG(php_gd_error("Index size is %d\n", idxSize)); + gdSeek(out, idxPos + idxSize); + + chunkIdx = gdCalloc(idxSize * sizeof(t_chunk_info), 1); + } + + _gdPutColors (im, out); + + GD2_DBG(php_gd_error("Size: %dx%d\n", im->sx, im->sy)); + GD2_DBG(php_gd_error("Chunks: %dx%d\n", ncx, ncy)); + + for (cy = 0; (cy < ncy); cy++) { + for (cx = 0; (cx < ncx); cx++) { + ylo = cy * cs; + yhi = ylo + cs; + if (yhi > im->sy) { + yhi = im->sy; + } + + GD2_DBG(php_gd_error("Processing Chunk (%dx%d), y from %d to %d\n", cx, cy, ylo, yhi)); + chunkLen = 0; + for (y = ylo; (y < yhi); y++) { + GD2_DBG(php_gd_error("y=%d: ",y)); + xlo = cx * cs; + xhi = xlo + cs; + if (xhi > im->sx) { + xhi = im->sx; + } + + if (gd2_compressed(fmt)) { + for (x = xlo; x < xhi; x++) { + GD2_DBG(php_gd_error("%d...",x)); + if (im->trueColor) { + int p = im->tpixels[y][x]; + chunkData[chunkLen++] = gdTrueColorGetAlpha(p); + chunkData[chunkLen++] = gdTrueColorGetRed(p); + chunkData[chunkLen++] = gdTrueColorGetGreen(p); + chunkData[chunkLen++] = gdTrueColorGetBlue(p); + } else { + chunkData[chunkLen++] = im->pixels[y][x]; + } + } + } else { + for (x = xlo; x < xhi; x++) { + GD2_DBG(php_gd_error("%d, ",x)); + + if (im->trueColor) { + gdPutInt(im->tpixels[y][x], out); + } else { + gdPutC((unsigned char) im->pixels[y][x], out); + } + } + } + GD2_DBG(php_gd_error("y=%d done.\n",y)); + } + + if (gd2_compressed(fmt)) { + compLen = compMax; + if (compress((unsigned char *) &compData[0], &compLen, (unsigned char *) &chunkData[0], chunkLen) != Z_OK) { + php_gd_error("Error from compressing\n"); + } else { + chunkIdx[chunkNum].offset = gdTell(out); + chunkIdx[chunkNum++].size = compLen; + GD2_DBG(php_gd_error("Chunk %d size %d offset %d\n", chunkNum, chunkIdx[chunkNum - 1].size, chunkIdx[chunkNum - 1].offset)); + + if (gdPutBuf (compData, compLen, out) <= 0) { + /* Any alternate suggestions for handling this? */ + php_gd_error_ex(E_WARNING, "Error %d on write\n", errno); + } + } } - }; } - else - { - for (x = xlo; x < xhi; x++) - { - /*GD2_DBG(printf("%d, ",x)); */ - - if (im->trueColor) - { - gdPutInt (im->tpixels[y][x], out); - } - else - { - gdPutC ((unsigned char) im->pixels[y][x], out); - } - }; - }; - /*GD2_DBG(printf("y=%d done.\n",y)); */ - }; - if (fmt == GD2_FMT_COMPRESSED) - { - compLen = compMax; - if (compress ((unsigned char *) - &compData[0], &compLen, - (unsigned char *) &chunkData[0], - chunkLen) != Z_OK) - { - printf ("Error from compressing\n"); + } + + if (gd2_compressed(fmt)) { + /* Save the position, write the index, restore position (paranoia). */ + GD2_DBG(php_gd_error("Seeking %d to write index\n", idxPos)); + posSave = gdTell(out); + gdSeek(out, idxPos); + GD2_DBG(php_gd_error("Writing index\n")); + for (x = 0; x < chunkNum; x++) { + GD2_DBG(php_gd_error("Chunk %d size %d offset %d\n", x, chunkIdx[x].size, chunkIdx[x].offset)); + gdPutInt(chunkIdx[x].offset, out); + gdPutInt(chunkIdx[x].size, out); } - else - { - chunkIdx[chunkNum].offset = gdTell (out); - chunkIdx[chunkNum++].size = compLen; - GD2_DBG (printf ("Chunk %d size %d offset %d\n", chunkNum, chunkIdx[chunkNum - 1].size, chunkIdx[chunkNum - 1].offset)); - - if (gdPutBuf (compData, compLen, out) <= 0) - { - /* Any alternate suggestions for handling this? */ - printf ("Error %d on write\n", errno); - }; - }; - }; - }; - }; - if (fmt == GD2_FMT_COMPRESSED) - { - /* Save the position, write the index, restore position (paranoia). */ - GD2_DBG (printf ("Seeking %d to write index\n", idxPos)); - posSave = gdTell (out); - gdSeek (out, idxPos); - GD2_DBG (printf ("Writing index\n")); - for (x = 0; x < chunkNum; x++) - { - GD2_DBG (printf ("Chunk %d size %d offset %d\n", x, chunkIdx[x].size, chunkIdx[x].offset)); - gdPutInt (chunkIdx[x].offset, out); - gdPutInt (chunkIdx[x].size, out); - }; - /* We don't use fwrite for *endian reasons. */ - /*fwrite(chunkIdx, sizeof(int)*2, chunkNum, out); */ - gdSeek (out, posSave); - }; - - GD2_DBG (printf ("Freeing memory\n")); - gdFree (chunkData); - gdFree (compData); - gdFree (chunkIdx); - GD2_DBG (printf ("Done\n")); - - /*printf("Memory block size is %d\n",gdTell(out)); */ + gdSeek(out, posSave); + } + GD2_DBG(php_gd_error("Freeing memory\n")); + if (chunkData) { + gdFree(chunkData); + } + if (compData) { + gdFree(compData); + } + if (chunkIdx) { + gdFree(chunkIdx); + } + GD2_DBG(php_gd_error("Done\n")); } -void -gdImageGd2 (gdImagePtr im, FILE * outFile, int cs, int fmt) -{ - gdIOCtx *out = gdNewFileCtx (outFile); - _gdImageGd2 (im, out, cs, fmt); - out->gd_free (out); -} - -void * -gdImageGd2Ptr (gdImagePtr im, int cs, int fmt, int *size) -{ - void *rv; - gdIOCtx *out = gdNewDynamicCtx (2048, NULL); - _gdImageGd2 (im, out, cs, fmt); - rv = gdDPExtractData (out, size); - out->gd_free (out); - return rv; +void gdImageGd2 (gdImagePtr im, FILE * outFile, int cs, int fmt) +{ + gdIOCtx *out = gdNewFileCtx(outFile); + + _gdImageGd2(im, out, cs, fmt); + + out->gd_free(out); +} + +void *gdImageGd2Ptr (gdImagePtr im, int cs, int fmt, int *size) +{ + void *rv; + gdIOCtx *out = gdNewDynamicCtx(2048, NULL); + + _gdImageGd2(im, out, cs, fmt); + rv = gdDPExtractData(out, size); + out->gd_free(out); + + return rv; } Index: php4/ext/gd/libgd/gd_gif_in.c diff -u php4/ext/gd/libgd/gd_gif_in.c:1.2 php4/ext/gd/libgd/gd_gif_in.c:1.2.2.1 --- php4/ext/gd/libgd/gd_gif_in.c:1.2 Tue Oct 29 18:08:01 2002 +++ php4/ext/gd/libgd/gd_gif_in.c Wed Mar 5 11:04:20 2003 @@ -4,6 +4,8 @@ #include <stdlib.h> #include "gd.h" +#include "php.h" + /* Used only when debugging GIF compression code */ /* #define DEBUGGING_ENVARS */ @@ -290,19 +292,24 @@ static int GetDataBlock(gdIOCtx *fd, unsigned char *buf) { - int rv; - int i; - - rv = GetDataBlock_(fd,buf); - if (VERBOSE) - { printf("[GetDataBlock returning %d",rv); - if (rv > 0) - { printf(":"); - for (i=0;i<rv;i++) printf(" %02x",buf[i]); - } - printf("]\n"); - } - return(rv); + int rv; + int i; + char *tmp = NULL; + + rv = GetDataBlock_(fd,buf); + if (VERBOSE) { + if (rv > 0) { + tmp = emalloc((3*sizeof(char)*rv) + 1); + for (i=0;i<rv;i++) { + sprintf(&tmp[3*sizeof(char)*i], " %02x", buf[i]); + } + } else { + tmp = estrdup(""); + } + php_gd_error_ex(E_NOTICE, "[GetDataBlock returning %d: %s]", rv, tmp); + efree(tmp); + } + return(rv); } static int @@ -352,7 +359,7 @@ int rv; rv = GetCode_(fd,code_size,flag); - if (VERBOSE) printf("[GetCode(,%d,%d) returning %d]\n",code_size,flag,rv); + if (VERBOSE) php_gd_error_ex(E_NOTICE, "[GetCode(,%d,%d) returning %d]\n",code_size,flag,rv); return(rv); } @@ -484,7 +491,7 @@ int rv; rv = LWZReadByte_(fd,flag,input_code_size); - if (VERBOSE) printf("[LWZReadByte(,%d,%d) returning %d]\n",flag,input_code_size,rv); + if (VERBOSE) php_gd_error_ex(E_NOTICE, "[LWZReadByte(,%d,%d) returning %d]\n",flag,input_code_size,rv); return(rv); } Index: php4/ext/gd/libgd/gd_jpeg.c diff -u php4/ext/gd/libgd/gd_jpeg.c:1.4 php4/ext/gd/libgd/gd_jpeg.c:1.4.2.1 --- php4/ext/gd/libgd/gd_jpeg.c:1.4 Tue Oct 29 18:08:01 2002 +++ php4/ext/gd/libgd/gd_jpeg.c Wed Mar 5 11:04:20 2003 @@ -16,6 +16,9 @@ * Modification 4/18/00 TBB: JPEG_DEBUG rather than just DEBUG, * so VC++ builds don't spew to standard output, causing * major CGI brain damage + * + * 2.0.10: more efficient gdImageCreateFromJpegCtx, thanks to + * Christian Aberger */ #include <stdio.h> @@ -29,6 +32,7 @@ /* JCE: arrange HAVE_LIBJPEG so that it can be set in gd.h */ #ifdef HAVE_LIBJPEG #include "gdhelpers.h" +#undef HAVE_STDLIB_H /* 1.8.1: remove dependency on jinclude.h */ #include "jpeglib.h" @@ -37,38 +41,30 @@ static const char *const GD_JPEG_VERSION = "1.0"; typedef struct _jmpbuf_wrapper - { - jmp_buf jmpbuf; - } -jmpbuf_wrapper; +{ + jmp_buf jmpbuf; +} jmpbuf_wrapper; /* Called by the IJG JPEG library upon encountering a fatal error */ static void fatal_jpeg_error (j_common_ptr cinfo) { - jmpbuf_wrapper *jmpbufw; + jmpbuf_wrapper *jmpbufw; + + php_gd_error("gd-jpeg: JPEG library reports unrecoverable error: "); + (*cinfo->err->output_message) (cinfo); - fprintf (stderr, "gd-jpeg: JPEG library reports unrecoverable error: "); - (*cinfo->err->output_message) (cinfo); - fflush (stderr); - - jmpbufw = (jmpbuf_wrapper *) cinfo->client_data; - jpeg_destroy (cinfo); - - if (jmpbufw != 0) - { - longjmp (jmpbufw->jmpbuf, 1); - fprintf (stderr, "gd-jpeg: EXTREMELY fatal error: longjmp" - " returned control; terminating\n"); - } - else - { - fprintf (stderr, "gd-jpeg: EXTREMELY fatal error: jmpbuf" - " unrecoverable; terminating\n"); - } + jmpbufw = (jmpbuf_wrapper *) cinfo->client_data; + jpeg_destroy (cinfo); + + if (jmpbufw != 0) { + longjmp (jmpbufw->jmpbuf, 1); + php_gd_error_ex(E_ERROR, "gd-jpeg: EXTREMELY fatal error: longjmp returned control; terminating"); + } else { + php_gd_error_ex(E_ERROR, "gd-jpeg: EXTREMELY fatal error: jmpbuf unrecoverable; terminating"); + } - fflush (stderr); - exit (99); + exit (99); } /* @@ -77,25 +73,27 @@ * represent higher quality but also larger image size. If QUALITY is * negative, the IJG JPEG library's default quality is used (which * should be near optimal for many applications). See the IJG JPEG - * library documentation for more details. */ + * library documentation for more details. + */ void gdImageJpeg (gdImagePtr im, FILE * outFile, int quality) { - gdIOCtx *out = gdNewFileCtx (outFile); - gdImageJpegCtx (im, out, quality); - out->gd_free (out); + gdIOCtx *out = gdNewFileCtx (outFile); + gdImageJpegCtx (im, out, quality); + out->gd_free (out); } void * gdImageJpegPtr (gdImagePtr im, int *size, int quality) { - void *rv; - gdIOCtx *out = gdNewDynamicCtx (2048, NULL); - gdImageJpegCtx (im, out, quality); - rv = gdDPExtractData (out, size); - out->gd_free (out); - return rv; + void *rv; + gdIOCtx *out = gdNewDynamicCtx (2048, NULL); + gdImageJpegCtx (im, out, quality); + rv = gdDPExtractData (out, size); + out->gd_free (out); + + return rv; } void jpeg_gdIOCtx_dest (j_compress_ptr cinfo, gdIOCtx * outfile); @@ -103,168 +101,127 @@ void gdImageJpegCtx (gdImagePtr im, gdIOCtx * outfile, int quality) { - struct jpeg_compress_struct cinfo; - struct jpeg_error_mgr jerr; - int i, j, jidx; - /* volatile so we can gdFree it on return from longjmp */ - volatile JSAMPROW row = 0; - JSAMPROW rowptr[1]; - jmpbuf_wrapper jmpbufw; - JDIMENSION nlines; - char comment[255]; - -#ifdef JPEG_DEBUG - printf ("gd-jpeg: gd JPEG version %s\n", GD_JPEG_VERSION); - printf ("gd-jpeg: JPEG library version %d, %d-bit sample values\n", - JPEG_LIB_VERSION, BITS_IN_JSAMPLE); - if (!im->trueColor) - { - for (i = 0; i < im->colorsTotal; i++) - { - if (!im->open[i]) - printf ("gd-jpeg: gd colormap index %d: (%d, %d, %d)\n", i, - im->red[i], im->green[i], im->blue[i]); - } - } -#endif /* JPEG_DEBUG */ - - memset (&cinfo, 0, sizeof (cinfo)); - memset (&jerr, 0, sizeof (jerr)); - - cinfo.err = jpeg_std_error (&jerr); - cinfo.client_data = &jmpbufw; - if (setjmp (jmpbufw.jmpbuf) != 0) - { - /* we're here courtesy of longjmp */ - if (row) - gdFree (row); - return; - } + struct jpeg_compress_struct cinfo; + struct jpeg_error_mgr jerr; + int i, j, jidx; + /* volatile so we can gdFree it on return from longjmp */ + volatile JSAMPROW row = 0; + JSAMPROW rowptr[1]; + jmpbuf_wrapper jmpbufw; + JDIMENSION nlines; + char comment[255]; + + memset (&cinfo, 0, sizeof (cinfo)); + memset (&jerr, 0, sizeof (jerr)); + + cinfo.err = jpeg_std_error (&jerr); + cinfo.client_data = &jmpbufw; + if (setjmp (jmpbufw.jmpbuf) != 0) { + /* we're here courtesy of longjmp */ + if (row) { + gdFree (row); + } + return; + } - cinfo.err->error_exit = fatal_jpeg_error; + cinfo.err->error_exit = fatal_jpeg_error; - jpeg_create_compress (&cinfo); + jpeg_create_compress (&cinfo); - cinfo.image_width = im->sx; - cinfo.image_height = im->sy; - cinfo.input_components = 3; /* # of color components per pixel */ - cinfo.in_color_space = JCS_RGB; /* colorspace of input image */ - jpeg_set_defaults (&cinfo); - if (quality >= 0) - jpeg_set_quality (&cinfo, quality, TRUE); - - /* If user requests interlace, translate that to progressive JPEG */ - if (gdImageGetInterlaced (im)) - { -#ifdef JPEG_DEBUG - printf ("gd-jpeg: interlace set, outputting progressive" - " JPEG image\n"); -#endif - jpeg_simple_progression (&cinfo); - } + cinfo.image_width = im->sx; + cinfo.image_height = im->sy; + cinfo.input_components = 3; /* # of color components per pixel */ + cinfo.in_color_space = JCS_RGB; /* colorspace of input image */ + jpeg_set_defaults (&cinfo); + if (quality >= 0) { + jpeg_set_quality (&cinfo, quality, TRUE); + } + + /* If user requests interlace, translate that to progressive JPEG */ + if (gdImageGetInterlaced (im)) { + jpeg_simple_progression (&cinfo); + } - jpeg_gdIOCtx_dest (&cinfo, outfile); + jpeg_gdIOCtx_dest (&cinfo, outfile); + + row = (JSAMPROW) gdCalloc (1, cinfo.image_width * cinfo.input_components * sizeof (JSAMPLE)); + rowptr[0] = row; + + jpeg_start_compress (&cinfo, TRUE); + + if (quality >= 0) { + snprintf(comment, sizeof(comment)-1, "CREATOR: gd-jpeg v%s (using IJG JPEG v%d), quality = %d\n", GD_JPEG_VERSION, JPEG_LIB_VERSION, quality); + } else { + snprintf(comment, sizeof(comment)-1, "CREATOR: gd-jpeg v%s (using IJG JPEG v%d), default quality\n", GD_JPEG_VERSION, JPEG_LIB_VERSION); + } + jpeg_write_marker (&cinfo, JPEG_COM, (unsigned char *) comment, (unsigned int) strlen (comment)); + if (im->trueColor) { - row = (JSAMPROW) gdCalloc (1, cinfo.image_width * cinfo.input_components - * sizeof (JSAMPLE)); - if (row == 0) - { - fprintf (stderr, "gd-jpeg: error: unable to allocate JPEG row " - "structure: gdCalloc returns NULL\n"); - jpeg_destroy_compress (&cinfo); - return; - } - - rowptr[0] = row; - - jpeg_start_compress (&cinfo, TRUE); - - sprintf (comment, "CREATOR: gd-jpeg v%s (using IJG JPEG v%d),", - GD_JPEG_VERSION, JPEG_LIB_VERSION); - if (quality >= 0) - sprintf (comment + strlen (comment), " quality = %d\n", - quality); - else - strcat (comment + strlen (comment), " default quality\n"); - jpeg_write_marker (&cinfo, JPEG_COM, (unsigned char *) comment, - (unsigned int) strlen (comment)); - if (im->trueColor) - { #if BITS_IN_JSAMPLE == 12 - fprintf (stderr, "gd-jpeg: error: jpeg library was compiled for 12-bit\n" - "precision. This is mostly useless, because JPEGs on the web are\n" - "8-bit and such versions of the jpeg library won't read or write\n" - "them. GD doesn't support these unusual images. Edit your\n" - "jmorecfg.h file to specify the correct precision and completely\n" - "'make clean' and 'make install' libjpeg again. Sorry.\n"); - goto error; + php_gd_error("gd-jpeg: error: jpeg library was compiled for 12-bit precision. This is mostly useless, because JPEGs on the web are 8-bit and such versions of the jpeg library won't read or write them. GD doesn't support these unusual images. Edit your jmorecfg.h file to specify the correct precision and completely 'make clean' and 'make install' libjpeg again. Sorry"); + goto error; #endif /* BITS_IN_JSAMPLE == 12 */ - for (i = 0; i < im->sy; i++) - { - for (jidx = 0, j = 0; j < im->sx; j++) - { - int val = im->tpixels[i][j]; - row[jidx++] = gdTrueColorGetRed (val); - row[jidx++] = gdTrueColorGetGreen (val); - row[jidx++] = gdTrueColorGetBlue (val); - } - - nlines = jpeg_write_scanlines (&cinfo, rowptr, 1); - if (nlines != 1) - fprintf (stderr, "gd_jpeg: warning: jpeg_write_scanlines" - " returns %u -- expected 1\n", nlines); - } - } - else - { - for (i = 0; i < im->sy; i++) - { - for (jidx = 0, j = 0; j < im->sx; j++) - { - int idx = im->pixels[i][j]; - - /* - * NB: Although gd RGB values are ints, their max value is - * 255 (see the documentation for gdImageColorAllocate()) - * -- perfect for 8-bit JPEG encoding (which is the norm) - */ + + for (i = 0; i < im->sy; i++) { + for (jidx = 0, j = 0; j < im->sx; j++) { + int val = im->tpixels[i][j]; + + row[jidx++] = gdTrueColorGetRed (val); + row[jidx++] = gdTrueColorGetGreen (val); + row[jidx++] = gdTrueColorGetBlue (val); + } + + nlines = jpeg_write_scanlines (&cinfo, rowptr, 1); + if (nlines != 1) { + php_gd_error_ex(E_WARNING, "gd_jpeg: warning: jpeg_write_scanlines returns %u -- expected 1\n", nlines); + } + } + } else { + for (i = 0; i < im->sy; i++) { + for (jidx = 0, j = 0; j < im->sx; j++) { + int idx = im->pixels[i][j]; + + /* NB: Although gd RGB values are ints, their max value is + * 255 (see the documentation for gdImageColorAllocate()) + * -- perfect for 8-bit JPEG encoding (which is the norm) + */ #if BITS_IN_JSAMPLE == 8 - row[jidx++] = im->red[idx]; - row[jidx++] = im->green[idx]; - row[jidx++] = im->blue[idx]; + row[jidx++] = im->red[idx]; + row[jidx++] = im->green[idx]; + row[jidx++] = im->blue[idx]; #elif BITS_IN_JSAMPLE == 12 - row[jidx++] = im->red[idx] << 4; - row[jidx++] = im->green[idx] << 4; - row[jidx++] = im->blue[idx] << 4; + row[jidx++] = im->red[idx] << 4; + row[jidx++] = im->green[idx] << 4; + row[jidx++] = im->blue[idx] << 4; #else #error IJG JPEG library BITS_IN_JSAMPLE value must be 8 or 12 #endif - } + } + + nlines = jpeg_write_scanlines (&cinfo, rowptr, 1); + if (nlines != 1) { + php_gd_error_ex(E_WARNING, "gd_jpeg: warning: jpeg_write_scanlines returns %u -- expected 1\n", nlines); + } + } + } - nlines = jpeg_write_scanlines (&cinfo, rowptr, 1); - if (nlines != 1) - fprintf (stderr, "gd_jpeg: warning: jpeg_write_scanlines" - " returns %u -- expected 1\n", nlines); - } - } - jpeg_finish_compress (&cinfo); - jpeg_destroy_compress (&cinfo); - gdFree (row); + jpeg_finish_compress (&cinfo); + jpeg_destroy_compress (&cinfo); + gdFree (row); } gdImagePtr gdImageCreateFromJpeg (FILE * inFile) { - gdImagePtr im; - gdIOCtx *in = gdNewFileCtx (inFile); - im = gdImageCreateFromJpegCtx (in); - in->gd_free (in); - return im; + gdImagePtr im; + gdIOCtx *in = gdNewFileCtx (inFile); + im = gdImageCreateFromJpegCtx (in); + in->gd_free (in); + + return im; } -void - jpeg_gdIOCtx_src (j_decompress_ptr cinfo, - gdIOCtx * infile); +void jpeg_gdIOCtx_src (j_decompress_ptr cinfo, gdIOCtx * infile); /* * Create a gd-format image from the JPEG-format INFILE. Returns the @@ -273,197 +230,122 @@ gdImagePtr gdImageCreateFromJpegCtx (gdIOCtx * infile) { - struct jpeg_decompress_struct cinfo; - struct jpeg_error_mgr jerr; - jmpbuf_wrapper jmpbufw; - /* volatile so we can gdFree them after longjmp */ - volatile JSAMPROW row = 0; - volatile gdImagePtr im = 0; - JSAMPROW rowptr[1]; - JDIMENSION i, j; - JDIMENSION nrows; - int retval; - -#ifdef JPEG_DEBUG - printf ("gd-jpeg: gd JPEG version %s\n", GD_JPEG_VERSION); - printf ("gd-jpeg: JPEG library version %d, %d-bit sample values\n", - JPEG_LIB_VERSION, BITS_IN_JSAMPLE); -#endif + struct jpeg_decompress_struct cinfo; + struct jpeg_error_mgr jerr; + jmpbuf_wrapper jmpbufw; + /* volatile so we can gdFree them after longjmp */ + volatile JSAMPROW row = 0; + volatile gdImagePtr im = 0; + JSAMPROW rowptr[1]; + unsigned int i, j; + int retval; + JDIMENSION nrows; + + memset (&cinfo, 0, sizeof (cinfo)); + memset (&jerr, 0, sizeof (jerr)); + + cinfo.err = jpeg_std_error (&jerr); + cinfo.client_data = &jmpbufw; + if (setjmp (jmpbufw.jmpbuf) != 0) { + /* we're here courtesy of longjmp */ + if (row) { + gdFree (row); + } + if (im) { + gdImageDestroy (im); + } + return 0; + } - memset (&cinfo, 0, sizeof (cinfo)); - memset (&jerr, 0, sizeof (jerr)); + cinfo.err->error_exit = fatal_jpeg_error; - cinfo.err = jpeg_std_error (&jerr); - cinfo.client_data = &jmpbufw; - if (setjmp (jmpbufw.jmpbuf) != 0) - { - /* we're here courtesy of longjmp */ - if (row) - gdFree (row); - if (im) - gdImageDestroy (im); - return 0; - } - - cinfo.err->error_exit = fatal_jpeg_error; - - jpeg_create_decompress (&cinfo); - - jpeg_gdIOCtx_src (&cinfo, infile); - - retval = jpeg_read_header (&cinfo, TRUE); - if (retval != JPEG_HEADER_OK) - fprintf (stderr, "gd-jpeg: warning: jpeg_read_header returns" - " %d, expected %d\n", retval, JPEG_HEADER_OK); - - if (cinfo.image_height > INT_MAX) - fprintf (stderr, "gd-jpeg: warning: JPEG image height (%u) is" - " greater than INT_MAX (%d) (and thus greater than" - " gd can handle)", cinfo.image_height, - INT_MAX); - - if (cinfo.image_width > INT_MAX) - fprintf (stderr, "gd-jpeg: warning: JPEG image width (%u) is" - " greater than INT_MAX (%d) (and thus greater than" - " gd can handle)\n", cinfo.image_width, INT_MAX); - - im = gdImageCreateTrueColor ((int) cinfo.image_width, - (int) cinfo.image_height); - if (im == 0) - { - fprintf (stderr, "gd-jpeg error: cannot allocate gdImage" - " struct\n"); - goto error; - } - - /* - * Force the image into RGB colorspace, but don't - * reduce the number of colors anymore (GD 2.0) - */ - cinfo.out_color_space = JCS_RGB; - - if (jpeg_start_decompress (&cinfo) != TRUE) - fprintf (stderr, "gd-jpeg: warning: jpeg_start_decompress" - " reports suspended data source\n"); - -#ifdef JPEG_DEBUG - printf ("gd-jpeg: JPEG image information:"); - if (cinfo.saw_JFIF_marker) - printf (" JFIF version %d.%.2d", - (int) cinfo.JFIF_major_version, - (int) cinfo.JFIF_minor_version); - else if (cinfo.saw_Adobe_marker) - printf (" Adobe format"); - else - printf (" UNKNOWN format"); - - printf (" %ux%u (raw) / %ux%u (scaled) %d-bit", cinfo.image_width, - cinfo.image_height, cinfo.output_width, - cinfo.output_height, cinfo.data_precision); - printf (" %s", (cinfo.progressive_mode ? "progressive" : - "baseline")); - printf (" image, %d quantized colors, ", - cinfo.actual_number_of_colors); - - switch (cinfo.jpeg_color_space) - { - case JCS_GRAYSCALE: - printf ("grayscale"); - break; - - case JCS_RGB: - printf ("RGB"); - break; - - case JCS_YCbCr: - printf ("YCbCr (a.k.a. YUV)"); - break; - - case JCS_CMYK: - printf ("CMYK"); - break; - - case JCS_YCCK: - printf ("YCbCrK"); - break; - - default: - printf ("UNKNOWN (value: %d)", (int) cinfo.jpeg_color_space); - break; - } - printf (" colorspace\n"); - fflush (stdout); -#endif /* JPEG_DEBUG */ - - /* REMOVED by TBB 2/12/01. This field of the structure is - documented as private, and sure enough it's gone in the - latest libjpeg, replaced by something else. Unfortunately - there is still no right way to find out if the file was - progressive or not; just declare your intent before you - write one by calling gdImageInterlace(im, 1) yourself. - After all, we're not really supposed to rework JPEGs and - write them out again anyway. Lossy compression, remember? */ + jpeg_create_decompress (&cinfo); + + jpeg_gdIOCtx_src (&cinfo, infile); + + retval = jpeg_read_header (&cinfo, TRUE); + if (retval != JPEG_HEADER_OK) { + php_gd_error_ex(E_WARNING, "gd-jpeg: warning: jpeg_read_header returned %d, expected %d", retval, JPEG_HEADER_OK); + } + + if (cinfo.image_height > INT_MAX) { + php_gd_error_ex(E_WARNING, "gd-jpeg: warning: JPEG image height (%u) is greater than INT_MAX (%d) (and thus greater than gd can handle)", cinfo.image_height, INT_MAX); + } + + if (cinfo.image_width > INT_MAX) { + php_gd_error_ex(E_WARNING, "gd-jpeg: warning: JPEG image width (%u) is greater than INT_MAX (%d) (and thus greater than gd can handle)", cinfo.image_width, INT_MAX); + } + + im = gdImageCreateTrueColor ((int) cinfo.image_width, (int) cinfo.image_height); + if (im == 0) { + php_gd_error("gd-jpeg error: cannot allocate gdImage struct"); + goto error; + } + + /* Force the image into RGB colorspace, but don't reduce the number of colors anymore (GD 2.0) */ + cinfo.out_color_space = JCS_RGB; + + if (jpeg_start_decompress (&cinfo) != TRUE) { + php_gd_error("gd-jpeg: warning: jpeg_start_decompress reports suspended data source"); + } + + /* REMOVED by TBB 2/12/01. This field of the structure is + * documented as private, and sure enough it's gone in the + * latest libjpeg, replaced by something else. Unfortunately + * there is still no right way to find out if the file was + * progressive or not; just declare your intent before you + * write one by calling gdImageInterlace(im, 1) yourself. + * After all, we're not really supposed to rework JPEGs and + * write them out again anyway. Lossy compression, remember? + */ #if 0 gdImageInterlace (im, cinfo.progressive_mode != 0); #endif - if (cinfo.output_components != 3) - { - fprintf (stderr, "gd-jpeg: error: JPEG color quantization" - " request resulted in output_components == %d" - " (expected 3)\n", cinfo.output_components); - goto error; - } + + if (cinfo.output_components != 3) { + php_gd_error_ex(E_WARNING, "gd-jpeg: error: JPEG color quantization request resulted in output_components == %d (expected 3)", cinfo.output_components); + goto error; + } #if BITS_IN_JSAMPLE == 12 - fprintf (stderr, "gd-jpeg: error: jpeg library was compiled for 12-bit\n" - "precision. This is mostly useless, because JPEGs on the web are\n" - "8-bit and such versions of the jpeg library won't read or write\n" - "them. GD doesn't support these unusual images. Edit your\n" - "jmorecfg.h file to specify the correct precision and completely\n" - "'make clean' and 'make install' libjpeg again. Sorry.\n"); - goto error; + php_gd_error("gd-jpeg: error: jpeg library was compiled for 12-bit precision. This is mostly useless, because JPEGs on the web are 8-bit and such versions of the jpeg library won't read or write them. GD doesn't support these unusual images. Edit your jmorecfg.h file to specify the correct precision and completely 'make clean' and 'make install' libjpeg again. Sorry."); + goto error; #endif /* BITS_IN_JSAMPLE == 12 */ - row = gdCalloc (cinfo.output_width * 3, sizeof (JSAMPLE)); - if (row == 0) - { - fprintf (stderr, "gd-jpeg: error: unable to allocate row for" - " JPEG scanline: gdCalloc returns NULL\n"); - goto error; - } - rowptr[0] = row; - - for (i = 0; i < cinfo.output_height; i++) - { - nrows = jpeg_read_scanlines (&cinfo, rowptr, 1); - if (nrows != 1) - { - fprintf (stderr, "gd-jpeg: error: jpeg_read_scanlines" - " returns %u, expected 1\n", nrows); - goto error; - } - - for (j = 0; j < cinfo.output_width; j++) - im->tpixels[i][j] = gdTrueColor (row[j * 3], row[j * 3 + 1], - row[j * 3 + 2]); - } - - if (jpeg_finish_decompress (&cinfo) != TRUE) - fprintf (stderr, "gd-jpeg: warning: jpeg_finish_decompress" - " reports suspended data source\n"); - - - jpeg_destroy_decompress (&cinfo); - gdFree (row); - return im; + row = gdCalloc (cinfo.output_width * 3, sizeof (JSAMPLE)); + rowptr[0] = row; + + for (i = 0; i < cinfo.output_height; i++) { + register JSAMPROW currow = row; + register int *tpix = im->tpixels[i]; + nrows = jpeg_read_scanlines (&cinfo, rowptr, 1); + if (nrows != 1) { + php_gd_error_ex(E_WARNING, "gd-jpeg: error: jpeg_read_scanlines returns %u, expected 1", nrows); + goto error; + } + for (j = 0; j < cinfo.output_width; j++, currow += 3, tpix++) { + *tpix = gdTrueColor (currow[0], currow[1], currow[2]); + } + } + + if (jpeg_finish_decompress (&cinfo) != TRUE) { + php_gd_error("gd-jpeg: warning: jpeg_finish_decompress reports suspended data source"); + } + + jpeg_destroy_decompress (&cinfo); + gdFree (row); + + return im; error: - jpeg_destroy_decompress (&cinfo); - if (row) - gdFree (row); - if (im) - gdImageDestroy (im); - return 0; + jpeg_destroy_decompress (&cinfo); + if (row) { + gdFree (row); + } + if (im) { + gdImageDestroy (im); + } + return 0; } /* @@ -489,15 +371,13 @@ /* Expanded data source object for gdIOCtx input */ typedef struct - { - struct jpeg_source_mgr pub; /* public fields */ +{ + struct jpeg_source_mgr pub; /* public fields */ - gdIOCtx *infile; /* source stream */ - unsigned char *buffer; /* start of buffer */ - safeboolean start_of_file; /* have we gotten any data yet? */ - - } -my_source_mgr; + gdIOCtx *infile; /* source stream */ + unsigned char *buffer; /* start of buffer */ + safeboolean start_of_file; /* have we gotten any data yet? */ +} my_source_mgr; typedef my_source_mgr *my_src_ptr; @@ -511,13 +391,13 @@ void init_source (j_decompress_ptr cinfo) { - my_src_ptr src = (my_src_ptr) cinfo->src; + my_src_ptr src = (my_src_ptr) cinfo->src; - /* We reset the empty-input-file flag for each image, - * but we don't clear the input buffer. - * This is correct behavior for reading a series of images from one source. - */ - src->start_of_file = TRUE; + /* We reset the empty-input-file flag for each image, + * but we don't clear the input buffer. + * This is correct behavior for reading a series of images from one source. + */ + src->start_of_file = TRUE; } @@ -559,56 +439,42 @@ safeboolean fill_input_buffer (j_decompress_ptr cinfo) { - my_src_ptr src = (my_src_ptr) cinfo->src; - size_t nbytes = 0; + my_src_ptr src = (my_src_ptr) cinfo->src; + size_t nbytes = 0; - /* size_t got; */ - /* char *s; */ - memset (src->buffer, 0, INPUT_BUF_SIZE); + /* size_t got; */ + /* char *s; */ + memset (src->buffer, 0, INPUT_BUF_SIZE); - while (nbytes < INPUT_BUF_SIZE) - { + while (nbytes < INPUT_BUF_SIZE) { + int got = gdGetBuf (src->buffer + nbytes, INPUT_BUF_SIZE - nbytes, src->infile); - int got = gdGetBuf (src->buffer + nbytes, - INPUT_BUF_SIZE - nbytes, - src->infile); - - if ((got == EOF) || (got == 0)) - { - - /* EOF or error. If we got any data, don't worry about it. - If we didn't, then this is unexpected. */ - if (!nbytes) - { - - nbytes = -1; - - } - - break; - + if ((got == EOF) || (got == 0)) { + /* EOF or error. If we got any data, don't worry about it. If we didn't, then this is unexpected. */ + if (!nbytes) { + nbytes = -1; + } + break; + } + nbytes += got; } - - nbytes += got; - - } - if (nbytes <= 0) - { - if (src->start_of_file) /* Treat empty input file as fatal error */ - ERREXIT (cinfo, JERR_INPUT_EMPTY); - WARNMS (cinfo, JWRN_JPEG_EOF); - /* Insert a fake EOI marker */ - src->buffer[0] = (unsigned char) 0xFF; - src->buffer[1] = (unsigned char) JPEG_EOI; - nbytes = 2; - } - - src->pub.next_input_byte = src->buffer; - src->pub.bytes_in_buffer = nbytes; - src->start_of_file = FALSE; + if (nbytes <= 0) { + if (src->start_of_file) { /* Treat empty input file as fatal error */ + ERREXIT (cinfo, JERR_INPUT_EMPTY); + } + WARNMS (cinfo, JWRN_JPEG_EOF); + /* Insert a fake EOI marker */ + src->buffer[0] = (unsigned char) 0xFF; + src->buffer[1] = (unsigned char) JPEG_EOI; + nbytes = 2; + } - return TRUE; + src->pub.next_input_byte = src->buffer; + src->pub.bytes_in_buffer = nbytes; + src->start_of_file = FALSE; + + return TRUE; } @@ -627,24 +493,22 @@ void skip_input_data (j_decompress_ptr cinfo, long num_bytes) { - my_src_ptr src = (my_src_ptr) cinfo->src; + my_src_ptr src = (my_src_ptr) cinfo->src; - /* Just a dumb implementation for now. Not clear that being smart is worth - * any trouble anyway --- large skips are infrequent. - */ - if (num_bytes > 0) - { - while (num_bytes > (long) src->pub.bytes_in_buffer) - { - num_bytes -= (long) src->pub.bytes_in_buffer; - (void) fill_input_buffer (cinfo); - /* note we assume that fill_input_buffer will never return FALSE, - * so suspension need not be handled. - */ - } - src->pub.next_input_byte += (size_t) num_bytes; - src->pub.bytes_in_buffer -= (size_t) num_bytes; - } + /* Just a dumb implementation for now. Not clear that being smart is worth + * any trouble anyway --- large skips are infrequent. + */ + if (num_bytes > 0) { + while (num_bytes > (long) src->pub.bytes_in_buffer) { + num_bytes -= (long) src->pub.bytes_in_buffer; + (void) fill_input_buffer (cinfo); + /* note we assume that fill_input_buffer will never return FALSE, + * so suspension need not be handled. + */ + } + src->pub.next_input_byte += (size_t) num_bytes; + src->pub.bytes_in_buffer -= (size_t) num_bytes; + } } @@ -669,11 +533,9 @@ void term_source (j_decompress_ptr cinfo) { - #if 0 -/* never used */ - my_src_ptr src = (my_src_ptr) cinfo->src; - + * never used */ + my_src_ptr src = (my_src_ptr) cinfo->src; #endif } @@ -685,50 +547,44 @@ */ void -jpeg_gdIOCtx_src (j_decompress_ptr cinfo, - gdIOCtx * infile) +jpeg_gdIOCtx_src (j_decompress_ptr cinfo, gdIOCtx * infile) { - my_src_ptr src; + my_src_ptr src; - /* The source object and input buffer are made permanent so that a series - * of JPEG images can be read from the same file by calling jpeg_gdIOCtx_src - * only before the first one. (If we discarded the buffer at the end of - * one image, we'd likely lose the start of the next one.) - * This makes it unsafe to use this manager and a different source - * manager serially with the same JPEG object. Caveat programmer. - */ - if (cinfo->src == NULL) - { /* first time for this JPEG object? */ - cinfo->src = (struct jpeg_source_mgr *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, - sizeof (my_source_mgr)); - src = (my_src_ptr) cinfo->src; - src->buffer = (unsigned char *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, - INPUT_BUF_SIZE * sizeof (unsigned char)); + /* The source object and input buffer are made permanent so that a series + * of JPEG images can be read from the same file by calling jpeg_gdIOCtx_src + * only before the first one. (If we discarded the buffer at the end of + * one image, we'd likely lose the start of the next one.) + * This makes it unsafe to use this manager and a different source + * manager serially with the same JPEG object. Caveat programmer. + */ + if (cinfo->src == NULL) { /* first time for this JPEG object? */ + cinfo->src = (struct jpeg_source_mgr *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, sizeof (my_source_mgr)); + src = (my_src_ptr) cinfo->src; + src->buffer = (unsigned char *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, INPUT_BUF_SIZE * sizeof (unsigned char)); - } + } - src = (my_src_ptr) cinfo->src; - src->pub.init_source = init_source; - src->pub.fill_input_buffer = fill_input_buffer; - src->pub.skip_input_data = skip_input_data; - src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */ - src->pub.term_source = term_source; - src->infile = infile; - src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */ - src->pub.next_input_byte = NULL; /* until buffer loaded */ + src = (my_src_ptr) cinfo->src; + src->pub.init_source = init_source; + src->pub.fill_input_buffer = fill_input_buffer; + src->pub.skip_input_data = skip_input_data; + src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */ + src->pub.term_source = term_source; + src->infile = infile; + src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */ + src->pub.next_input_byte = NULL; /* until buffer loaded */ } /* Expanded data destination object for stdio output */ typedef struct { - struct jpeg_destination_mgr pub; /* public fields */ - gdIOCtx *outfile; /* target stream */ - unsigned char *buffer; /* start of buffer */ -} -my_destination_mgr; + struct jpeg_destination_mgr pub; /* public fields */ + gdIOCtx *outfile; /* target stream */ + unsigned char *buffer; /* start of buffer */ +} my_destination_mgr; typedef my_destination_mgr *my_dest_ptr; @@ -742,15 +598,13 @@ void init_destination (j_compress_ptr cinfo) { - my_dest_ptr dest = (my_dest_ptr) cinfo->dest; + my_dest_ptr dest = (my_dest_ptr) cinfo->dest; - /* Allocate the output buffer --- it will be released when done with image */ - dest->buffer = (unsigned char *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - OUTPUT_BUF_SIZE * sizeof (unsigned char)); + /* Allocate the output buffer --- it will be released when done with image */ + dest->buffer = (unsigned char *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, OUTPUT_BUF_SIZE * sizeof (unsigned char)); - dest->pub.next_output_byte = dest->buffer; - dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; + dest->pub.next_output_byte = dest->buffer; + dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; } @@ -780,16 +634,16 @@ safeboolean empty_output_buffer (j_compress_ptr cinfo) { - my_dest_ptr dest = (my_dest_ptr) cinfo->dest; + my_dest_ptr dest = (my_dest_ptr) cinfo->dest; - if (gdPutBuf (dest->buffer, OUTPUT_BUF_SIZE, dest->outfile) != - (size_t) OUTPUT_BUF_SIZE) - ERREXIT (cinfo, JERR_FILE_WRITE); + if (gdPutBuf (dest->buffer, OUTPUT_BUF_SIZE, dest->outfile) != (size_t) OUTPUT_BUF_SIZE) { + ERREXIT (cinfo, JERR_FILE_WRITE); + } - dest->pub.next_output_byte = dest->buffer; - dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; + dest->pub.next_output_byte = dest->buffer; + dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; - return TRUE; + return TRUE; } @@ -805,15 +659,13 @@ void term_destination (j_compress_ptr cinfo) { - my_dest_ptr dest = (my_dest_ptr) cinfo->dest; - size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer; + my_dest_ptr dest = (my_dest_ptr) cinfo->dest; + size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer; - /* Write any data remaining in the buffer */ - if (datacount > 0) - { - if ((size_t)gdPutBuf (dest->buffer, datacount, dest->outfile) != datacount) - ERREXIT (cinfo, JERR_FILE_WRITE); - } + /* Write any data remaining in the buffer */ + if (datacount > 0 && ((size_t)gdPutBuf (dest->buffer, datacount, dest->outfile) != datacount)) { + ERREXIT (cinfo, JERR_FILE_WRITE); + } } @@ -826,26 +678,23 @@ void jpeg_gdIOCtx_dest (j_compress_ptr cinfo, gdIOCtx * outfile) { - my_dest_ptr dest; + my_dest_ptr dest; + + /* The destination object is made permanent so that multiple JPEG images + * can be written to the same file without re-executing jpeg_stdio_dest. + * This makes it dangerous to use this manager and a different destination + * manager serially with the same JPEG object, because their private object + * sizes may be different. Caveat programmer. + */ + if (cinfo->dest == NULL) { /* first time for this JPEG object? */ + cinfo->dest = (struct jpeg_destination_mgr *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, sizeof (my_destination_mgr)); + } - /* The destination object is made permanent so that multiple JPEG images - * can be written to the same file without re-executing jpeg_stdio_dest. - * This makes it dangerous to use this manager and a different destination - * manager serially with the same JPEG object, because their private object - * sizes may be different. Caveat programmer. - */ - if (cinfo->dest == NULL) - { /* first time for this JPEG object? */ - cinfo->dest = (struct jpeg_destination_mgr *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, - sizeof (my_destination_mgr)); - } - - dest = (my_dest_ptr) cinfo->dest; - dest->pub.init_destination = init_destination; - dest->pub.empty_output_buffer = empty_output_buffer; - dest->pub.term_destination = term_destination; - dest->outfile = outfile; + dest = (my_dest_ptr) cinfo->dest; + dest->pub.init_destination = init_destination; + dest->pub.empty_output_buffer = empty_output_buffer; + dest->pub.term_destination = term_destination; + dest->outfile = outfile; } #endif /* HAVE_JPEG */ Index: php4/ext/gd/libgd/gd_png.c diff -u php4/ext/gd/libgd/gd_png.c:1.4.2.1 php4/ext/gd/libgd/gd_png.c:1.4.2.2 --- php4/ext/gd/libgd/gd_png.c:1.4.2.1 Wed Dec 4 12:28:55 2002 +++ php4/ext/gd/libgd/gd_png.c Wed Mar 5 11:04:20 2003 @@ -7,8 +7,8 @@ /* JCE: Arrange HAVE_LIBPNG so that it can be set in gd.h */ #ifdef HAVE_LIBPNG -#include "gdhelpers.h" #include "png.h" /* includes zlib.h and setjmp.h */ +#include "gdhelpers.h" #define TRUE 1 #define FALSE 0 @@ -59,15 +59,12 @@ * regardless of whether _BSD_SOURCE or anything else has (or has not) * been defined. */ - fprintf (stderr, "gd-png: fatal libpng error: %s\n", msg); - fflush (stderr); + 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 */ - fprintf (stderr, - "gd-png: EXTREMELY fatal error: jmpbuf unrecoverable; terminating.\n"); - fflush (stderr); + php_gd_error_ex(E_ERROR, "gd-png: EXTREMELY fatal error: jmpbuf unrecoverable; terminating.\n"); exit (99); } @@ -116,7 +113,7 @@ 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; @@ -127,7 +124,6 @@ png_bytepp row_pointers = NULL; gdImagePtr im = NULL; int i, j, *open = NULL; - png_uint_32 ui, uj; volatile int transparent = -1; volatile int palette_allocated = FALSE; @@ -149,14 +145,14 @@ #endif if (png_ptr == NULL) { - fprintf (stderr, "gd-png error: cannot allocate libpng main struct\n"); + 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) { - fprintf (stderr, "gd-png error: cannot allocate libpng info struct\n"); + php_gd_error("gd-png error: cannot allocate libpng info struct\n"); png_destroy_read_struct (&png_ptr, NULL, NULL); return NULL; } @@ -170,7 +166,7 @@ #ifndef PNG_SETJMP_NOT_SUPPORTED if (setjmp (gdPngJmpbufStruct.jmpbuf)) { - fprintf (stderr, "gd-png error: setjmp returns error condition\n"); + php_gd_error("gd-png error: setjmp returns error condition\n"); png_destroy_read_struct (&png_ptr, &info_ptr, NULL); return NULL; } @@ -194,7 +190,7 @@ } if (im == NULL) { - fprintf (stderr, "gd-png error: cannot allocate gdImage struct\n"); + 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); @@ -210,7 +206,7 @@ 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", + 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)) @@ -227,7 +223,7 @@ im->alpha[i] = gdAlphaMax - (trans[i] >> 1); if ((trans[i] == 0) && (firstZero)) { - transparent = i; + transparent = i; firstZero = 0; } } @@ -239,7 +235,7 @@ /* create a fake palette and check for single-shade transparency */ if ((palette = (png_colorp) gdMalloc (256 * sizeof (png_color))) == NULL) { - fprintf (stderr, "gd-png error: cannot allocate gray palette\n"); + php_gd_error("gd-png error: cannot allocate gray palette\n"); png_destroy_read_struct (&png_ptr, &info_ptr, NULL); return NULL; } @@ -307,22 +303,22 @@ rowbytes = png_get_rowbytes (png_ptr, info_ptr); if ((image_data = (png_bytep) gdMalloc (rowbytes * height)) == NULL) { - fprintf (stderr, "gd-png error: cannot allocate image data\n"); + 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) { - fprintf (stderr, "gd-png error: cannot allocate row pointers\n"); + 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; } /* set the individual row_pointers to point at the correct offsets */ - for (uj = 0; uj < height; ++uj) + for (h = 0; h < height; ++h) { - row_pointers[uj] = image_data + uj * rowbytes; + row_pointers[h] = image_data + h * rowbytes; } png_read_image (png_ptr, row_pointers); /* read whole image... */ @@ -353,44 +349,44 @@ switch (color_type) { case PNG_COLOR_TYPE_RGB: - for (uj = 0; uj < height; uj++) + for (h = 0; h < height; h++) { int boffset = 0; - for (ui = 0; ui < width; ui++) + for (w = 0; w < width; w++) { - register png_byte r = row_pointers[uj][boffset++]; - register png_byte g = row_pointers[uj][boffset++]; - register png_byte b = row_pointers[uj][boffset++]; - im->tpixels[uj][ui] = gdTrueColor (r, g, b); + 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 (uj = 0; uj < height; uj++) + for (h = 0; h < height; h++) { int boffset = 0; - for (ui = 0; ui < width; ui++) + for (w = 0; w < width; w++) { - register png_byte r = row_pointers[uj][boffset++]; - register png_byte g = row_pointers[uj][boffset++]; - register png_byte b = row_pointers[uj][boffset++]; + 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[uj][boffset++] >> 1); - im->tpixels[uj][ui] = gdTrueColorAlpha (r, g, b, a); + (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 (uj = 0; uj < height; ++uj) + for (h = 0; h < height; ++h) { - for (ui = 0; ui < width; ++ui) + for (w = 0; w < width; ++w) { - register png_byte idx = row_pointers[uj][ui]; - im->pixels[uj][ui] = idx; + register png_byte idx = row_pointers[h][w]; + im->pixels[h][w] = idx; open[idx] = 0; } } @@ -402,7 +398,7 @@ { if (!open[i]) { - fprintf (stderr, "gd-png warning: image data references out-of-range" + php_gd_error("gd-png warning: image data references out-of-range" " color index (%d)\n", i); } } @@ -467,14 +463,14 @@ #endif if (png_ptr == NULL) { - fprintf (stderr, "gd-png error: cannot allocate libpng main struct\n"); + 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) { - fprintf (stderr, "gd-png error: cannot allocate libpng info struct\n"); + php_gd_error("gd-png error: cannot allocate libpng info struct\n"); png_destroy_write_struct (&png_ptr, (png_infopp) NULL); return; } @@ -482,7 +478,7 @@ #ifndef PNG_SETJMP_NOT_SUPPORTED if (setjmp (gdPngJmpbufStruct.jmpbuf)) { - fprintf (stderr, "gd-png error: setjmp returns error condition\n"); + php_gd_error("gd-png error: setjmp returns error condition\n"); png_destroy_write_struct (&png_ptr, &info_ptr); return; } @@ -565,9 +561,10 @@ } if (im->trueColor && (!im->saveAlphaFlag) && (transparent >= 0)) { - trans_rgb_value.red = gdTrueColorGetRed (im->trueColor); - trans_rgb_value.green = gdTrueColorGetGreen (im->trueColor); - trans_rgb_value.blue = gdTrueColorGetBlue (im->trueColor); + /* 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) @@ -596,7 +593,7 @@ { trans_values[i] = 255 - ((im->alpha[i] << 1) + - (im->alpha[i] >> 7)); + (im->alpha[i] >> 6)); } png_set_tRNS (png_ptr, info_ptr, trans_values, 256, NULL); #endif @@ -615,9 +612,10 @@ { 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] >> 7)); + (im->alpha[i] >> 6)); mapping[i] = j++; } else @@ -670,20 +668,10 @@ /* Our little 7-bit alpha channel trick costs us a bit here. */ png_bytep *row_pointers; row_pointers = gdMalloc (sizeof (png_bytep) * height); - if (row_pointers == NULL) - { - fprintf (stderr, "gd-png error: unable to allocate row_pointers\n"); - } for (j = 0; j < height; ++j) { int bo = 0; - if ((row_pointers[j] = (png_bytep) gdMalloc (width * channels)) == NULL) - { - fprintf (stderr, "gd-png error: unable to allocate rows\n"); - for (i = 0; i < j; ++i) - gdFree (row_pointers[i]); - return; - } + row_pointers[j] = (png_bytep) gdMalloc (width * channels); for (i = 0; i < width; ++i) { unsigned char a; @@ -698,7 +686,8 @@ 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]); - row_pointers[j][bo++] = 255 - ((a << 1) + (a >> 7)); + /* Andrew Hull: >> 6, not >> 7! (gd 2.0.5) */ + row_pointers[j][bo++] = 255 - ((a << 1) + (a >> 6)); } } } Index: php4/ext/gd/libgd/gd_ss.c diff -u php4/ext/gd/libgd/gd_ss.c:1.2 php4/ext/gd/libgd/gd_ss.c:1.2.2.1 --- php4/ext/gd/libgd/gd_ss.c:1.2 Tue Oct 29 18:08:01 2002 +++ php4/ext/gd/libgd/gd_ss.c Wed Mar 5 11:04:20 2003 @@ -41,12 +41,12 @@ void gdImagePngToSink (gdImagePtr im, gdSinkPtr outSink) { - fprintf(stderr,"PNG support is not available\n"); + php_gd_error("PNG support is not available\n"); } gdImagePtr gdImageCreateFromPngSource (gdSourcePtr inSource) { - fprintf(stderr,"PNG support is not available\n"); + php_gd_error("PNG support is not available\n"); return NULL; } #endif /* HAVE_LIBPNG */ Index: php4/ext/gd/libgd/gd_topal.c diff -u php4/ext/gd/libgd/gd_topal.c:1.8.2.1 php4/ext/gd/libgd/gd_topal.c:1.8.2.2 --- php4/ext/gd/libgd/gd_topal.c:1.8.2.1 Wed Dec 4 12:28:55 2002 +++ php4/ext/gd/libgd/gd_topal.c Wed Mar 5 11:04:20 2003 @@ -1626,7 +1626,7 @@ return -3; /* the images are meant to be the same dimensions */ } - buf = (unsigned long *)malloc( sizeof(unsigned long) * 5 * im2->colorsTotal ); + buf = (unsigned long *)gdMalloc( sizeof(unsigned long) * 5 * im2->colorsTotal ); memset( buf, 0, sizeof(unsigned long) * 5 * im2->colorsTotal ); for( x=0; x<im1->sx; x++ ) { @@ -1653,6 +1653,6 @@ bp += 4; } } - free(buf); + gdFree(buf); return 0; } Index: php4/ext/gd/libgd/gd_wbmp.c diff -u php4/ext/gd/libgd/gd_wbmp.c:1.3 php4/ext/gd/libgd/gd_wbmp.c:1.3.2.1 --- php4/ext/gd/libgd/gd_wbmp.c:1.3 Tue Oct 29 18:08:01 2002 +++ php4/ext/gd/libgd/gd_wbmp.c Wed Mar 5 11:04:20 2003 @@ -70,7 +70,7 @@ void gd_putout (int i, void *out) { - gdPutC ((unsigned char)i, (gdIOCtx *) out); + gdPutC (i, (gdIOCtx *) out); } @@ -105,7 +105,7 @@ /* create the WBMP */ if ((wbmp = createwbmp (gdImageSX (image), gdImageSY (image), WBMP_WHITE)) == NULL) - fprintf (stderr, "Could not create WBMP\n"); + php_gd_error("Could not create WBMP\n"); /* fill up the WBMP structure */ pos = 0; @@ -123,7 +123,7 @@ /* write the WBMP to a gd file descriptor */ if (writewbmp (wbmp, &gd_putout, out)) - fprintf (stderr, "Could not save WBMP\n"); + php_gd_error("Could not save WBMP\n"); /* des submitted this bugfix: gdFree the memory. */ freewbmp (wbmp); } Index: php4/ext/gd/libgd/gdcache.c diff -u php4/ext/gd/libgd/gdcache.c:1.1 php4/ext/gd/libgd/gdcache.c:1.1.4.1 --- php4/ext/gd/libgd/gdcache.c:1.1 Fri Apr 12 22:03:08 2002 +++ php4/ext/gd/libgd/gdcache.c Wed Mar 5 11:04:20 2003 @@ -66,7 +66,7 @@ { gdCache_head_t *head; - head = (gdCache_head_t *) gdMalloc (sizeof (gdCache_head_t)); + head = (gdCache_head_t *) gdPMalloc(sizeof (gdCache_head_t)); head->mru = NULL; head->size = size; head->gdCacheTest = gdCacheTest; @@ -86,9 +86,9 @@ (*(head->gdCacheRelease)) (elem->userdata); prev = elem; elem = elem->next; - gdFree ((char *) prev); + gdPFree ((char *) prev); } - gdFree ((char *) head); + gdPFree ((char *) head); } void * @@ -125,7 +125,7 @@ } if (i < head->size) { /* cache still growing - add new elem */ - elem = (gdCache_element_t *) gdMalloc (sizeof (gdCache_element_t)); + elem = (gdCache_element_t *) gdPMalloc(sizeof (gdCache_element_t)); } else { /* cache full - replace least-recently-used */ Index: php4/ext/gd/libgd/gdft.c diff -u php4/ext/gd/libgd/gdft.c:1.11.2.4 php4/ext/gd/libgd/gdft.c:1.11.2.5 --- php4/ext/gd/libgd/gdft.c:1.11.2.4 Sun Jan 5 19:47:47 2003 +++ php4/ext/gd/libgd/gdft.c Wed Mar 5 11:04:20 2003 @@ -19,25 +19,38 @@ #endif #ifdef WIN32 -extern int access(const char *pathname, int mode); +#define access _access #ifndef R_OK #define R_OK 2 #endif #endif /* number of antialised colors for indexed bitmaps */ +/* overwrite Windows GDI define in case of windows build */ +#ifdef NUMCOLORS +#undef NUMCOLORS +#endif #define NUMCOLORS 8 char * gdImageStringTTF (gdImage * im, int *brect, int fg, char *fontlist, double ptsize, double angle, int x, int y, char *string) { + /* 2.0.6: valid return */ return gdImageStringFT (im, brect, fg, fontlist, ptsize, angle, x, y, string); } #ifndef HAVE_LIBFREETYPE char * +gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist, + double ptsize, double angle, int x, int y, char *string, + gdFTStringExtraPtr strex) +{ + return "libgd was not built with FreeType font support\n"; +} + +char * gdImageStringFT (gdImage * im, int *brect, int fg, char *fontlist, double ptsize, double angle, int x, int y, char *string) { @@ -86,8 +99,13 @@ #define TRUE !FALSE #endif +#ifndef MAX #define MAX(a,b) ((a)>(b)?(a):(b)) +#endif + +#ifndef MIN #define MIN(a,b) ((a)<(b)?(a):(b)) +#endif typedef struct { @@ -330,159 +348,161 @@ return (strcmp (a->fontlist, b->fontlist) == 0); } -static void * -fontFetch (char **error, void *key) +static void *fontFetch (char **error, void *key) { - font_t *a; - fontkey_t *b = (fontkey_t *) key; - int n; - int font_found = 0; - unsigned short platform, encoding; - char *fontsearchpath, *fontlist; - char *fullname = NULL; - char *name, *path, *dir; - char *strtok_ptr; - FT_Error err; - FT_CharMap found = 0; - FT_CharMap charmap; - - a = (font_t *) gdMalloc (sizeof (font_t)); - a->fontlist = strdup (b->fontlist); - a->library = b->library; - - /* - * Search the pathlist for any of a list of font names. - */ - fontsearchpath = getenv ("GDFONTPATH"); - if (!fontsearchpath) - fontsearchpath = DEFAULT_FONTPATH; - fontlist = strdup (a->fontlist); - - /* - * Must use gd_strtok_r else pointer corrupted by strtok in nested loop. - */ - for (name = gd_strtok_r (fontlist, LISTSEPARATOR, &strtok_ptr); name; - name = gd_strtok_r (0, LISTSEPARATOR, &strtok_ptr)) - { - - /* make a fresh copy each time - strtok corrupts it. */ - path = strdup (fontsearchpath); - /* - * Allocate an oversized buffer that is guaranteed to be - * big enough for all paths to be tested. - */ - fullname = gdRealloc (fullname, - strlen (fontsearchpath) + strlen (name) + 6); - /* if name is an absolute filename then test directly */ - if (*name == '/' || (name[0] != 0 && name[1] == ':' && (name[2] == '/' || name[2] == '\\'))) - { - sprintf (fullname, "%s", name); - if (access (fullname, R_OK) == 0) - { - font_found++; - break; - } - } - for (dir = strtok (path, PATHSEPARATOR); dir; - dir = strtok (0, PATHSEPARATOR)) - { - sprintf (fullname, "%s/%s", dir, name); - if (access (fullname, R_OK) == 0) - { - font_found++; - break; - } - sprintf (fullname, "%s/%s.ttf", dir, name); - if (access (fullname, R_OK) == 0) - { - font_found++; - break; - } - sprintf (fullname, "%s/%s.pfa", dir, name); - if (access (fullname, R_OK) == 0) - { - font_found++; - break; - } - sprintf (fullname, "%s/%s.pfb", dir, name); - if (access (fullname, R_OK) == 0) - { - font_found++; - break; - } + font_t *a; + fontkey_t *b = (fontkey_t *) key; + int n; + int font_found = 0; + unsigned short platform, encoding; + char *fontsearchpath, *fontlist; + char *fullname = NULL; + char *name, *path=NULL, *dir; + char *strtok_ptr; + FT_Error err; + FT_CharMap found = 0; + FT_CharMap charmap; + + a = (font_t *) gdPMalloc(sizeof(font_t)); + a->fontlist = gdPEstrdup(b->fontlist); + a->library = b->library; + + /* + * Search the pathlist for any of a list of font names. + */ + fontsearchpath = getenv ("GDFONTPATH"); + if (!fontsearchpath) { + fontsearchpath = DEFAULT_FONTPATH; + } + fontlist = gdEstrdup(a->fontlist); + + /* + * Must use gd_strtok_r else pointer corrupted by strtok in nested loop. + */ + for (name = gd_strtok_r (fontlist, LISTSEPARATOR, &strtok_ptr); name; name = gd_strtok_r (0, LISTSEPARATOR, &strtok_ptr)) { + /* make a fresh copy each time - strtok corrupts it. */ + path = gdEstrdup (fontsearchpath); + + /* + * Allocate an oversized buffer that is guaranteed to be + * big enough for all paths to be tested. + */ + fullname = gdRealloc (fullname, strlen (fontsearchpath) + strlen (name) + 6); + + /* if name is an absolute filename then test directly */ + if (*name == '/' || (name[0] != 0 && name[1] == ':' && (name[2] == '/' || name[2] == '\\'))) { + sprintf(fullname, "%s", name); + if (access(fullname, R_OK) == 0) { + font_found++; + break; + } + } + for (dir = strtok (path, PATHSEPARATOR); dir; dir = strtok (0, PATHSEPARATOR)) { + sprintf(fullname, "%s/%s", dir, name); + if (access (fullname, R_OK) == 0) { + font_found++; + break; + } + sprintf(fullname, "%s/%s.ttf", dir, name); + if (access (fullname, R_OK) == 0) { + font_found++; + break; + } + sprintf(fullname, "%s/%s.pfa", dir, name); + if (access(fullname, R_OK) == 0) { + font_found++; + break; + } + sprintf (fullname, "%s/%s.pfb", dir, name); + if (access(fullname, R_OK) == 0) { + font_found++; + break; + } + } + gdFree(path); + path = NULL; + if (font_found) { + break; + } + } + + if (path) { + gdFree(path); + } + + gdFree(fontlist); + + if (!font_found) { + gdPFree(a->fontlist); + gdPFree(a); + if (fullname) { + gdFree(fullname); + } + *error = "Could not find/open font"; + return NULL; } - gdFree (path); - if (font_found) - break; - } - gdFree (fontlist); - if (!font_found) - { - *error = "Could not find/open font"; - return NULL; - } - err = FT_New_Face (*b->library, fullname, 0, &a->face); - if (err) - { - *error = "Could not read font"; - return NULL; - } - gdFree (fullname); + err = FT_New_Face (*b->library, fullname, 0, &a->face); + if (err) { + gdPFree(a->fontlist); + gdPFree(a); + if (fullname) { + gdFree(fullname); + } + *error = "Could not read font"; + return NULL; + } + gdFree(fullname); -/* FIXME - This mapping stuff is imcomplete - where is the spec? */ + /* FIXME - This mapping stuff is imcomplete - where is the spec? */ - a->have_char_map_unicode = 0; - a->have_char_map_big5 = 0; - a->have_char_map_sjis = 0; - a->have_char_map_apple_roman = 0; - for (n = 0; n < a->face->num_charmaps; n++) - { - charmap = a->face->charmaps[n]; - platform = charmap->platform_id; - encoding = charmap->encoding_id; - if ((platform == 3 && encoding == 1) /* Windows Unicode */ - || (platform == 3 && encoding == 0) /* Windows Symbol */ - || (platform == 2 && encoding == 1) /* ISO Unicode */ - || (platform == 0)) - { /* Apple Unicode */ - a->have_char_map_unicode = 1; - found = charmap; - } - else if (platform == 3 && encoding == 4) - { /* Windows Big5 */ - a->have_char_map_big5 = 1; - found = charmap; - } - else if (platform == 3 && encoding == 2) - { /* Windows Sjis */ - a->have_char_map_sjis = 1; - found = charmap; + a->have_char_map_unicode = 0; + a->have_char_map_big5 = 0; + a->have_char_map_sjis = 0; + a->have_char_map_apple_roman = 0; + for (n = 0; n < a->face->num_charmaps; n++) { + charmap = a->face->charmaps[n]; + platform = charmap->platform_id; + encoding = charmap->encoding_id; + if ((platform == 3 && encoding == 1) /* Windows Unicode */ + || (platform == 3 && encoding == 0) /* Windows Symbol */ + || (platform == 2 && encoding == 1) /* ISO Unicode */ + || (platform == 0)) + { /* Apple Unicode */ + a->have_char_map_unicode = 1; + found = charmap; + } else if (platform == 3 && encoding == 4) { /* Windows Big5 */ + a->have_char_map_big5 = 1; + found = charmap; + } else if (platform == 3 && encoding == 2) { /* Windows Sjis */ + a->have_char_map_sjis = 1; + found = charmap; + } else if ((platform == 1 && encoding == 0) /* Apple Roman */ + || (platform == 2 && encoding == 0)) + { /* ISO ASCII */ + a->have_char_map_apple_roman = 1; + found = charmap; + } } - else if ((platform == 1 && encoding == 0) /* Apple Roman */ - || (platform == 2 && encoding == 0)) - { /* ISO ASCII */ - a->have_char_map_apple_roman = 1; - found = charmap; + if (!found) { + gdPFree(a->fontlist); + gdPFree(a); + *error = "Unable to find a CharMap that I can handle"; + return NULL; } - } - if (!found) - { - *error = "Unable to find a CharMap that I can handle"; - return NULL; - } - return (void *) a; + /* 2.0.5: we should actually return this */ + a->face->charmap = found; + return (void *) a; } -static void -fontRelease (void *element) +static void fontRelease (void *element) { - font_t *a = (font_t *) element; + font_t *a = (font_t *) element; - FT_Done_Face (a->face); - gdFree (a->fontlist); - gdFree ((char *) element); + FT_Done_Face (a->face); + gdPFree(a->fontlist); + gdPFree((char *) element); } /********************************************************************/ @@ -570,7 +590,7 @@ { unsigned char *pixel = NULL; int *tpixel = NULL; - int x, y, row, col, pc; + int x, y, row, col, pc, pcr; tweencolor_t *tc_elem; tweencolorkey_t tc_key; @@ -584,6 +604,7 @@ for (row = 0; row < bitmap.rows; row++) { pc = row * bitmap.pitch; + pcr = pc; y = pen_y + row; /* clip if out of bounds */ if (y >= im->sy || y < 0) @@ -602,17 +623,20 @@ } else if (bitmap.pixel_mode == ft_pixel_mode_mono) { - level = ((bitmap.buffer[pc / 8] - << (pc % 8)) & 128) ? gdAlphaOpaque : - gdAlphaTransparent; + /* 2.0.5: mode_mono fix from Giuliano Pochini */ + level = ((bitmap.buffer[(col>>3)+pcr]) & (1<<(~col&0x07))) + ? gdAlphaTransparent : + gdAlphaOpaque; } else { return "Unsupported ft_pixel_mode"; } - if (fg >= 0) { + if ((fg >= 0) && (im->trueColor)) { /* Consider alpha in the foreground color itself to be an - upper bound on how opaque things get */ + upper bound on how opaque things get, when truecolor is + available. Without truecolor this results in far too many + color indexes. */ level = level * (gdAlphaMax - gdTrueColorGetAlpha(fg)) / gdAlphaMax; } level = gdAlphaMax - level; @@ -640,7 +664,9 @@ /* Non-truecolor case, restored to its more or less original form */ for (row = 0; row < bitmap.rows; row++) { + int pcr; pc = row * bitmap.pitch; + pcr = pc; if(bitmap.pixel_mode==ft_pixel_mode_mono) pc *= 8; /* pc is measured in bits for monochrome images */ @@ -667,6 +693,9 @@ { tc_key.pixel = ((bitmap.buffer[pc / 8] << (pc % 8)) & 128) ? NUMCOLORS : 0; + /* 2.0.5: mode_mono fix from Giuliano Pochini */ + tc_key.pixel = ((bitmap.buffer[(col>>3)+pcr]) & (1<<(~col&0x07))) + ? NUMCOLORS : 0; } else { @@ -729,17 +758,19 @@ /********************************************************************/ /* gdImageStringFT - render a utf8 string onto a gd image */ + char * gdImageStringFT (gdImage * im, int *brect, int fg, char *fontlist, - double ptsize, double angle, int x, int y, char *string) + double ptsize, double angle, int x, int y, char *string) { - return gdImageStringFTEx(im, brect, fg, fontlist, ptsize, angle, x, y, string, NULL); + return gdImageStringFTEx(im, brect, fg, fontlist, + ptsize, angle, x, y, string, 0); } char * gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist, double ptsize, double angle, int x, int y, char *string, - gdFTStringExtra * strex) + gdFTStringExtraPtr strex) { FT_BBox bbox, glyph_bbox; FT_Matrix matrix; @@ -761,10 +792,9 @@ int render = (im && (im->trueColor || (fg <= 255 && fg >= -255))); FT_BitmapGlyph bm; int render_mode = FT_LOAD_RENDER | FT_LOAD_FORCE_AUTOHINT; - - /* fine tuning */ + /* Now tuneable thanks to Wez Furlong */ double linespace = LINESPACE; - + /* 2.0.6: put this declaration with the other declarations! */ /* * make a new tweenColorCache on every call * because caching colormappings between calls @@ -774,6 +804,11 @@ */ gdCache_head_t *tc_cache; + if (strex) { + if ((strex->flags & gdFTEX_LINESPACE) == gdFTEX_LINESPACE) { + linespace = strex->linespacing; + } + } tc_cache = gdCacheCreate( TWEENCOLORCACHESIZE, tweenColorTest, tweenColorFetch, tweenColorRelease ); @@ -810,12 +845,6 @@ return "Could not set character size"; } - /* pull in supplied extended settings */ - if (strex) { - if ((strex->flags & gdFTEX_LINESPACE) == gdFTEX_LINESPACE) - linespace = strex->linespacing; - } - matrix.xx = (FT_Fixed) (cos_a * (1 << 16)); matrix.yx = (FT_Fixed) (sin_a * (1 << 16)); matrix.xy = -matrix.yx; @@ -860,8 +889,8 @@ if (ch == '\r') { penf.x = 0; - x1 = (int)((penf.x * cos_a - penf.y * sin_a + 32.0) / 64.0); - y1 = (int)((penf.x * sin_a + penf.y * cos_a + 32.0) / 64.0); + x1 = (int)(penf.x * cos_a - penf.y * sin_a + 32) / 64; + y1 = (int)(penf.x * sin_a + penf.y * cos_a + 32) / 64; pen.x = pen.y = 0; previous = 0; /* clear kerning flag */ next++; @@ -870,10 +899,10 @@ /* newlines */ if (ch == '\n') { - penf.y = penf.y - (int)(face->size->metrics.height * LINESPACE); + penf.y -= (long)(face->size->metrics.height * linespace); penf.y = (penf.y - 32) & -64; /* round to next pixel row */ - x1 = (int)((penf.x * cos_a - penf.y * sin_a + 32.0) / 64.0); - y1 = (int)((penf.x * sin_a + penf.y * cos_a + 32.0) / 64.0); + x1 = (int)(penf.x * cos_a - penf.y * sin_a + 32) / 64; + y1 = (int)(penf.x * sin_a + penf.y * cos_a + 32) / 64; pen.x = pen.y = 0; previous = 0; /* clear kerning flag */ next++; @@ -936,10 +965,8 @@ next++; } } - /* set rotation transform */ FT_Set_Transform(face, &matrix, NULL); - /* Convert character code to glyph index */ glyph_index = FT_Get_Char_Index (face, ch); Index: php4/ext/gd/libgd/gdhelpers.c diff -u php4/ext/gd/libgd/gdhelpers.c:1.3.2.2 php4/ext/gd/libgd/gdhelpers.c:1.3.2.3 --- php4/ext/gd/libgd/gdhelpers.c:1.3.2.2 Mon Nov 18 08:00:52 2002 +++ php4/ext/gd/libgd/gdhelpers.c Wed Mar 5 11:04:20 2003 @@ -2,8 +2,6 @@ #include "config.h" #endif -#include "php.h" - #include "gd.h" #include "gdhelpers.h" #include <stdlib.h> @@ -75,28 +73,4 @@ /* 5. Return token */ *state = s; return result; -} - -void * -gdCalloc (size_t nmemb, size_t size) -{ - return calloc (nmemb, size); -} - -void * -gdMalloc (size_t size) -{ - return malloc (size); -} - -void * -gdRealloc (void *ptr, size_t size) -{ - return realloc (ptr, size); -} - -void -gdFree (void *ptr) -{ - free (ptr); } Index: php4/ext/gd/libgd/gdhelpers.h diff -u php4/ext/gd/libgd/gdhelpers.h:1.2.2.1 php4/ext/gd/libgd/gdhelpers.h:1.2.2.2 --- php4/ext/gd/libgd/gdhelpers.h:1.2.2.1 Sun Nov 17 14:40:38 2002 +++ php4/ext/gd/libgd/gdhelpers.h Wed Mar 5 11:04:20 2003 @@ -2,6 +2,7 @@ #define GDHELPERS_H 1 #include <sys/types.h> +#include "php.h" /* TBB: strtok_r is not universal; provide an implementation of it. */ @@ -11,10 +12,14 @@ in gd.h, where callers can utilize it to correctly free memory allocated by these functions with the right version of free(). */ -void *gdCalloc(size_t nmemb, size_t size); -void *gdMalloc(size_t size); -void *gdRealloc(void *ptr, size_t size); -char *gdEstrdup(const char *ptr); +#define gdCalloc(nmemb, size) ecalloc(nmemb, size) +#define gdMalloc(size) emalloc(size) +#define gdRealloc(ptr, size) erealloc(ptr, size) +#define gdEstrdup(ptr) estrdup(ptr) +#define gdFree(ptr) efree(ptr) +#define gdPMalloc(ptr) pemalloc(ptr, 1) +#define gdPFree(ptr) pefree(ptr, 1) +#define gdPEstrdup(ptr) pestrdup(ptr, 1) #endif /* GDHELPERS_H */ Index: php4/ext/gd/libgd/gdkanji.c diff -u php4/ext/gd/libgd/gdkanji.c:1.2 php4/ext/gd/libgd/gdkanji.c:1.2.2.1 --- php4/ext/gd/libgd/gdkanji.c:1.2 Tue Oct 29 18:08:01 2002 +++ php4/ext/gd/libgd/gdkanji.c Wed Mar 5 11:04:20 2003 @@ -72,13 +72,15 @@ static void error (const char *format,...) { - va_list args; - - va_start (args, format); - fprintf (stderr, "%s: ", LIBNAME); - vfprintf (stderr, format, args); - fprintf (stderr, "\n"); - va_end (args); + va_list args; + char *tmp; + TSRMLS_FETCH(); + + va_start(args, format); + vspprintf(&tmp, 0, format, args); + va_end(args); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s: %s", LIBNAME, tmp); + efree(tmp); } /* DetectKanjiCode() derived from DetectCodeType() by Ken Lunde. */ Index: php4/ext/gd/libgd/gdxpm.c diff -u php4/ext/gd/libgd/gdxpm.c:1.2.2.1 php4/ext/gd/libgd/gdxpm.c:1.2.2.2 --- php4/ext/gd/libgd/gdxpm.c:1.2.2.1 Mon Nov 25 18:12:15 2002 +++ php4/ext/gd/libgd/gdxpm.c Wed Mar 5 11:04:20 2003 @@ -7,21 +7,13 @@ */ #include <stdio.h> #include <stdlib.h> +#include <string.h> #include "gd.h" #include "gdhelpers.h" -#ifndef HAVE_XPM -gdImagePtr -gdImageCreateFromXpm (char *filename) -{ - fprintf (stderr, "libgd was not built with xpm support\n"); - return (NULL); -} - -#else +#ifdef HAVE_XPM #include <X11/xpm.h> -#include <string.h> gdImagePtr gdImageCreateFromXpm (char *filename) @@ -46,8 +38,6 @@ number = image.ncolors; colors = (int *) gdMalloc (sizeof (int) * number); - if (colors == NULL) - return (0); for (i = 0; i < number; i++) { switch (strlen (image.colorTable[i].c_color)) @@ -125,15 +115,13 @@ colors[i] = gdImageColorResolve (im, red, green, blue); if (colors[i] == -1) - fprintf (stderr, "ARRRGH\n"); + php_gd_error("ARRRGH\n"); } apixel = (char *) gdMalloc (image.cpp + 1); - if (apixel == NULL) - return (0); apixel[image.cpp] = '\0'; - pointer = image.data; + pointer = (int *) image.data; for (i = 0; i < image.height; i++) { for (j = 0; j < image.width; j++)