(Oops sent this to wrong list address first.)
On Tue, 19 Oct 2004, Greg Donald wrote:
> On Tue, 19 Oct 2004 10:32:01 +0300 (EEST), Jaakko Hyvätti
> <[EMAIL PROTECTED]> wrote:
> > I hope people can test this patch and suggest improvements, and that
> > eventually the patch makes it into php-4 and php-5. I'll try to include
> > examples and updated manual patches for the new functions on that page
> > later. Please do not hesitate to contact me for any questions or
> > suggestions!
>
> You probably want to post this info to php-dev. php-general is for
> users of PHP, not necessarily the actual PHP developers.
Well while I waited for the official GD to be updated, I wanted to give
users some idea what might be coming up. Now as the gd-2.0.30 includes
animated gifs, I would like to suggest that the developers update to that
version the bundled gd. My patch at http://www.iki.fi/hyvatti/sw/
implements the PHP functions also. Included with this email is a patch
to just php to add the function wrappers for new gd features, without
the gd patches.
The patch implements three new functions, imagegifanimbegin(),
imagegifanimadd(), and imagegifanimend(). With these functions, animated
gif images can be created on the fly with php. The documentation for the
functions is included in php-doc-anim.diff on the above url (this may be
outdated). Note that the animations are not optimized as heavily as with
some programs like gifsicle, but if you plan carefully you can get fairly
good optimization on the fly.
GD-2.17 perl module also implements these functions now.
Please consider these patches.
Regards,
Jaakko
--
Foreca Ltd [EMAIL PROTECTED]
Pursimiehenkatu 29-31 B, FIN-00150 Helsinki, Finland http://www.foreca.com
diff -ru old/php-5.0.2/configure php-5.0.2/configure
--- old/php-5.0.2/configure 2004-09-24 00:26:32.000000000 +0300
+++ php-5.0.2/configure 2004-10-19 08:57:34.560094663 +0300
@@ -31989,6 +31989,9 @@
cat >> confdefs.h <<\EOF
#define HAVE_GD_BUNDLED 1
+#define HAVE_GD_GIF_CREATE 1
+#define HAVE_GD_GIF_CTX 1
+#define HAVE_GD_GIF_ANIM 1
EOF
cat >> confdefs.h <<\EOF
@@ -36318,6 +36321,60 @@
echo "$ac_t""no" 1>&6
LDFLAGS=$save_old_LDFLAGS
+ unset ac_cv_func_gd
+
+
+fi
+
+
+ save_old_LDFLAGS=$LDFLAGS
+ LDFLAGS=" -L$GD_LIB $GD_SHARED_LIBADD $LDFLAGS"
+ echo $ac_n "checking for gdImageGifAnimBegin in -lgd""... $ac_c" 1>&6
+echo "configure:32003: checking for gdImageGifAnimBegin in -lgd" >&5
+ac_lib_var=`echo gd'_'gdImageGifAnimBegin | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lgd $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 32011 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char gdImageGifAnimBegin();
+
+int main() {
+gdImageGifAnimBegin()
+; return 0; }
+EOF
+if { (eval echo configure:32022: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }
&& test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+
+ LDFLAGS=$save_old_LDFLAGS
+ cat >> confdefs.h <<\EOF
+#define HAVE_GD_GIF_ANIM 1
+EOF
+
+
+else
+ echo "$ac_t""no" 1>&6
+
+ LDFLAGS=$save_old_LDFLAGS
ext_shared=$save_ext_shared
unset ac_cv_func_gd
diff -ru old/php-5.0.2/ext/gd/config.m4 php-5.0.2/ext/gd/config.m4
--- old/php-5.0.2/ext/gd/config.m4 2004-07-27 15:44:35.000000000 +0300
+++ php-5.0.2/ext/gd/config.m4 2004-10-19 08:57:34.587090922 +0300
@@ -257,6 +257,7 @@
PHP_CHECK_LIBRARY(gd, gdImageColorClosestHWB,
[AC_DEFINE(HAVE_COLORCLOSESTHWB, 1, [ ])], [], [ -L$GD_LIB
$GD_SHARED_LIBADD ])
PHP_CHECK_LIBRARY(gd, gdImageColorResolve,
[AC_DEFINE(HAVE_GDIMAGECOLORRESOLVE, 1, [ ])], [], [ -L$GD_LIB
$GD_SHARED_LIBADD ])
PHP_CHECK_LIBRARY(gd, gdImageGifCtx, [AC_DEFINE(HAVE_GD_GIF_CTX,
1, [ ])], [], [ -L$GD_LIB $GD_SHARED_LIBADD ])
+ PHP_CHECK_LIBRARY(gd, gdImageGifAnimBegin, [AC_DEFINE(HAVE_GD_GIF_ANIM,
1, [ ])], [], [ -L$GD_LIB $GD_SHARED_LIBADD ])
PHP_CHECK_LIBRARY(gd, gdCacheCreate,
[AC_DEFINE(HAVE_GD_CACHE_CREATE, 1, [ ])], [], [ -L$GD_LIB
$GD_SHARED_LIBADD ])
PHP_CHECK_LIBRARY(gd, gdFontCacheShutdown,
[AC_DEFINE(HAVE_GD_THREAD_SAFE, 1, [ ])], [], [ -L$GD_LIB
$GD_SHARED_LIBADD ])
PHP_CHECK_LIBRARY(gd, gdNewDynamicCtxEx,
[AC_DEFINE(HAVE_GD_DYNAMIC_CTX_EX, 1, [ ])], [], [ -L$GD_LIB
$GD_SHARED_LIBADD ])
diff -ru old/php-5.0.2/ext/gd/gd.c php-5.0.2/ext/gd/gd.c
--- old/php-5.0.2/ext/gd/gd.c 2004-08-17 02:08:56.000000000 +0300
+++ php-5.0.2/ext/gd/gd.c 2004-10-19 08:57:34.662080529 +0300
@@ -253,6 +253,11 @@
#ifdef HAVE_GD_GIF_CREATE
PHP_FE(imagegif,
NULL)
#endif
+#ifdef HAVE_GD_GIF_ANIM
+ PHP_FE(imagegifanimbegin,
NULL)
+ PHP_FE(imagegifanimadd,
NULL)
+ PHP_FE(imagegifanimend,
NULL)
+#endif
#ifdef HAVE_GD_JPG
PHP_FE(imagejpeg,
NULL)
#endif
@@ -1847,12 +1852,36 @@
#ifdef HAVE_GD_GIF_CTX
_php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU,
PHP_GDIMG_TYPE_GIF, "GIF", gdImageGifCtx);
#else
+
+#ifdef HAVE_GD_BUNDLED
+#error "I really think there should be ctx version of imagegif in the bundled
GD library. Fix the configuration."
+#endif
+
_php_image_output(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_GIF,
"GIF", gdImageGif);
#endif
}
/* }}} */
#endif /* HAVE_GD_GIF_CREATE */
+#ifdef HAVE_GD_GIF_ANIM
+/* {{{ proto int imagegifanimbegin(int im [, string filename [, int
GlobalColormap [, int Loops]]])
+ Begin GIF animation. Image parameter is only used for size and colormap,
+ all animation frames must be added separately. */
+PHP_FUNCTION(imagegifanimbegin)
+{
+ _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU,
PHP_GDIMG_TYPE_GIFANIMBEGIN, "GIF", gdImageGifAnimBeginCtx);
+}
+/* }}} */
+
+/* {{{ proto int imagegifanimadd(int im [, string filename [, int
LocalColormap [, LeftOfs [, int TopOfs [, int Delay [, int Disposal [, int
previm]]]]]]])
+ Append GIF image to animation */
+PHP_FUNCTION(imagegifanimadd)
+{
+ _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU,
PHP_GDIMG_TYPE_GIFANIMADD, "GIF", gdImageGifAnimAddCtx);
+}
+/* }}} */
+#endif /* HAVE_GD_GIF_ANIM */
+
#ifdef HAVE_GD_PNG
/* {{{ proto bool imagepng(resource im [, string filename])
Output PNG image to browser or file */
diff -ru old/php-5.0.2/ext/gd/gd_ctx.c php-5.0.2/ext/gd/gd_ctx.c
--- old/php-5.0.2/ext/gd/gd_ctx.c 2004-01-28 18:25:12.000000000 +0200
+++ php-5.0.2/ext/gd/gd_ctx.c 2004-10-19 09:24:12.799612064 +0300
@@ -49,23 +49,28 @@
/* {{{ _php_image_output_ctx */
static void _php_image_output_ctx(INTERNAL_FUNCTION_PARAMETERS, int
image_type, char *tn, void (*func_p)())
{
- zval **imgind, **file, **quality;
- gdImagePtr im;
+ zval **imgind, **file, **quality, **lo, **to, **del, **dis, **previmind;
+ gdImagePtr im, previm = 0;
char *fn = NULL;
FILE *fp = NULL;
int argc = ZEND_NUM_ARGS();
int q = -1, i;
+#ifdef HAVE_GD_GIF_ANIM
+ int LeftOfs = -1, TopOfs = -1, Delay = -1, Disposal = -1;
+#endif /* HAVE_GD_GIF_ANIM */
gdIOCtx *ctx;
/* The third (quality) parameter for Wbmp stands for the threshold when
called from image2wbmp().
* The third (quality) parameter for Wbmp and Xbm stands for the
foreground color index when called
* from imagey<type>().
+ * The quality parameter for GIF animation stands for colormap
inclusion. 1==include local/global colormap
+ * The LeftOfs parameter for GIF animation begin stands for NETSCAPE2.0
Loop count extension.
*/
if (argc < 2 && image_type == PHP_GDIMG_TYPE_XBM) {
WRONG_PARAM_COUNT;
}
- if (argc < 1 || argc > 3 || zend_get_parameters_ex(argc, &imgind,
&file, &quality) == FAILURE)
+ if (argc < 1 || argc > 8 || zend_get_parameters_ex(argc, &imgind,
&file, &quality, &lo, &to, &del, &dis, &previmind) == FAILURE)
{
WRONG_PARAM_COUNT;
}
@@ -75,11 +80,32 @@
if (argc > 1) {
convert_to_string_ex(file);
fn = Z_STRVAL_PP(file);
- if (argc == 3) {
- convert_to_long_ex(quality);
- q = Z_LVAL_PP(quality);/* or colorindex for foreground
of BW images (defaults to black) */
- }
}
+ if (argc >= 3) {
+ convert_to_long_ex(quality);
+ q = Z_LVAL_PP(quality);/* or colorindex for foreground of BW
images (defaults to black) */
+ }
+#ifdef HAVE_GD_GIF_ANIM
+ if (argc >= 4) {
+ convert_to_long_ex(lo);
+ LeftOfs = Z_LVAL_PP(lo);
+ }
+ if (argc >= 5) {
+ convert_to_long_ex(to);
+ TopOfs = Z_LVAL_PP(to);
+ }
+ if (argc >= 6) {
+ convert_to_long_ex(del);
+ Delay = Z_LVAL_PP(del);
+ }
+ if (argc >= 7) {
+ convert_to_long_ex(dis);
+ Disposal = Z_LVAL_PP(dis);
+ }
+ if (argc >= 8) {
+ ZEND_FETCH_RESOURCE(previm, gdImagePtr, previmind, -1, "Image",
phpi_get_le_gd());
+ }
+#endif /* HAVE_GD_GIF_ANIM */
if ((argc == 2) || (argc > 2 && Z_STRLEN_PP(file))) {
if (!fn || fn == empty_string || php_check_open_basedir(fn
TSRMLS_CC)) {
@@ -87,7 +113,7 @@
RETURN_FALSE;
}
- fp = VCWD_FOPEN(fn, "wb");
+ fp = VCWD_FOPEN(fn, PHP_GDIMG_TYPE_GIFANIMADD == image_type ?
"ab" : "wb");
if (!fp) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to
open '%s' for writing", fn);
RETURN_FALSE;
@@ -133,6 +159,14 @@
(*func_p)(im, q, ctx);
}
break;
+#ifdef HAVE_GD_GIF_ANIM
+ case PHP_GDIMG_TYPE_GIFANIMBEGIN:
+ (*func_p)(im, ctx, q, LeftOfs);
+ break;
+ case PHP_GDIMG_TYPE_GIFANIMADD:
+ (*func_p)(im, ctx, q, LeftOfs, TopOfs, Delay, Disposal,
previm);
+ break;
+#endif /* HAVE_GD_GIF_ANIM */
default:
(*func_p)(im, ctx);
break;
@@ -153,6 +187,75 @@
}
/* }}} */
+#ifdef HAVE_GD_GIF_ANIM
+/* {{{ proto int imagegifanimend([string filename])
+ Write end mark to gif animation. */
+PHP_FUNCTION(imagegifanimend)
+{
+ zval **file;
+ char *fn = NULL;
+ FILE *fp = NULL;
+ int argc = ZEND_NUM_ARGS();
+ gdIOCtx *ctx;
+
+ if (argc < 0 || argc > 1 || zend_get_parameters_ex(argc, &file) ==
FAILURE) {
+ ZEND_WRONG_PARAM_COUNT();
+ }
+
+ if (argc >= 1) {
+ convert_to_string_ex(file);
+ fn = Z_STRVAL_PP(file);
+ }
+
+ if ((argc == 1) || (argc > 1 && Z_STRLEN_PP(file))) {
+ if (!fn || fn == empty_string || php_check_open_basedir(fn
TSRMLS_CC)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid
filename '%s'", fn);
+ RETURN_FALSE;
+ }
+
+ fp = VCWD_FOPEN(fn, "ab");
+ if (!fp) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to
open '%s' for writing", fn);
+ RETURN_FALSE;
+ }
+
+ ctx = gdNewFileCtx(fp);
+ } else {
+ ctx = emalloc(sizeof(gdIOCtx));
+ ctx->putC = _php_image_output_putc;
+ ctx->putBuf = _php_image_output_putbuf;
+#if HAVE_LIBGD204
+ ctx->gd_free = _php_image_output_ctxfree;
+#else
+ ctx->free = _php_image_output_ctxfree;
+#endif
+
+#if APACHE && defined(CHARSET_EBCDIC)
+ /* XXX this is unlikely to work any more [EMAIL PROTECTED] */
+ /* This is a binary file already: avoid EBCDIC->ASCII
conversion */
+ ap_bsetflag(php3_rqst->connection->client, B_EBCDIC2ASCII, 0);
+#endif
+ }
+
+ /* This could be coded in here, as it only outputs ';' */
+ gdImageGifAnimEndCtx(ctx);
+
+#if HAVE_LIBGD204
+ ctx->gd_free(ctx);
+#else
+ ctx->free(ctx);
+#endif
+
+ if(fp) {
+ fflush(fp);
+ fclose(fp);
+ }
+
+ RETURN_TRUE;
+}
+/* }}} */
+#endif /* HAVE_GD_GIF_ANIM */
+
/*
* Local variables:
* tab-width: 4
diff -ru old/php-5.0.2/ext/gd/php_gd.h php-5.0.2/ext/gd/php_gd.h
--- old/php-5.0.2/ext/gd/php_gd.h 2004-01-08 19:32:08.000000000 +0200
+++ php-5.0.2/ext/gd/php_gd.h 2004-10-19 09:02:18.605711736 +0300
@@ -40,6 +40,8 @@
#define PHP_GDIMG_TYPE_GD 8
#define PHP_GDIMG_TYPE_GD2 9
#define PHP_GDIMG_TYPE_GD2PART 10
+#define PHP_GDIMG_TYPE_GIFANIMBEGIN 11
+#define PHP_GDIMG_TYPE_GIFANIMADD 12
#ifdef PHP_WIN32
#define PHP_GD_API __declspec(dllexport)
@@ -137,6 +139,9 @@
PHP_FUNCTION(imagefontheight);
PHP_FUNCTION(imagegif );
+PHP_FUNCTION(imagegifanimbegin);
+PHP_FUNCTION(imagegifanimadd);
+PHP_FUNCTION(imagegifanimend);
PHP_FUNCTION(imagejpeg );
PHP_FUNCTION(imagepng);
PHP_FUNCTION(imagewbmp);
diff -ru old/php-5.0.2/main/php_config.h.in php-5.0.2/main/php_config.h.in
--- old/php-5.0.2/main/php_config.h.in 2004-09-24 00:26:44.000000000 +0300
+++ php-5.0.2/main/php_config.h.in 2004-10-19 09:04:24.991177007 +0300
@@ -1418,6 +1418,9 @@
#undef HAVE_GD_GIF_CREATE
/* */
+#undef HAVE_GD_GIF_ANIM
+
+/* */
#undef HAVE_GD_IMAGEELLIPSE
/* */
diff -ru old/php-4.3.9/configure php-4.3.9/configure
--- old/php-4.3.9/configure 2004-09-21 01:31:33.000000000 +0300
+++ php-4.3.9/configure 2004-10-19 15:35:54.485471572 +0300
@@ -31649,6 +31649,9 @@
cat >> confdefs.h <<\EOF
#define HAVE_GD_BUNDLED 1
+#define HAVE_GD_GIF_CREATE 1
+#define HAVE_GD_GIF_CTX 1
+#define HAVE_GD_GIF_ANIM 1
EOF
cat >> confdefs.h <<\EOF
@@ -35976,6 +35979,60 @@
echo "$ac_t""no" 1>&6
LDFLAGS=$save_old_LDFLAGS
+ unset ac_cv_func_gd
+
+
+fi
+
+
+ save_old_LDFLAGS=$LDFLAGS
+ LDFLAGS=" -L$GD_LIB $GD_SHARED_LIBADD $LDFLAGS"
+ echo $ac_n "checking for gdImageGifAnimBegin in -lgd""... $ac_c" 1>&6
+echo "configure:32003: checking for gdImageGifAnimBegin in -lgd" >&5
+ac_lib_var=`echo gd'_'gdImageGifAnimBegin | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lgd $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 32011 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char gdImageGifAnimBegin();
+
+int main() {
+gdImageGifAnimBegin()
+; return 0; }
+EOF
+if { (eval echo configure:32022: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }
&& test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+
+ LDFLAGS=$save_old_LDFLAGS
+ cat >> confdefs.h <<\EOF
+#define HAVE_GD_GIF_ANIM 1
+EOF
+
+
+else
+ echo "$ac_t""no" 1>&6
+
+ LDFLAGS=$save_old_LDFLAGS
ext_shared=$save_ext_shared
unset ac_cv_func_gd
diff -ru old/php-4.3.9/ext/gd/config.m4 php-4.3.9/ext/gd/config.m4
--- old/php-4.3.9/ext/gd/config.m4 2004-07-27 15:44:44.000000000 +0300
+++ php-4.3.9/ext/gd/config.m4 2004-10-19 15:35:54.488471150 +0300
@@ -256,6 +256,7 @@
PHP_CHECK_LIBRARY(gd, gdImageColorClosestHWB,
[AC_DEFINE(HAVE_COLORCLOSESTHWB, 1, [ ])], [], [ -L$GD_LIB
$GD_SHARED_LIBADD ])
PHP_CHECK_LIBRARY(gd, gdImageColorResolve,
[AC_DEFINE(HAVE_GDIMAGECOLORRESOLVE, 1, [ ])], [], [ -L$GD_LIB
$GD_SHARED_LIBADD ])
PHP_CHECK_LIBRARY(gd, gdImageGifCtx, [AC_DEFINE(HAVE_GD_GIF_CTX,
1, [ ])], [], [ -L$GD_LIB $GD_SHARED_LIBADD ])
+ PHP_CHECK_LIBRARY(gd, gdImageGifAnimBegin, [AC_DEFINE(HAVE_GD_GIF_ANIM,
1, [ ])], [], [ -L$GD_LIB $GD_SHARED_LIBADD ])
PHP_CHECK_LIBRARY(gd, gdCacheCreate,
[AC_DEFINE(HAVE_GD_CACHE_CREATE, 1, [ ])], [], [ -L$GD_LIB
$GD_SHARED_LIBADD ])
PHP_CHECK_LIBRARY(gd, gdFontCacheShutdown,
[AC_DEFINE(HAVE_GD_THREAD_SAFE, 1, [ ])], [], [ -L$GD_LIB
$GD_SHARED_LIBADD ])
PHP_CHECK_LIBRARY(gd, gdNewDynamicCtxEx,
[AC_DEFINE(HAVE_GD_DYNAMIC_CTX_EX, 1, [ ])], [], [ -L$GD_LIB
$GD_SHARED_LIBADD ])
diff -ru old/php-4.3.9/ext/gd/gd.c php-4.3.9/ext/gd/gd.c
--- old/php-4.3.9/ext/gd/gd.c 2004-08-17 02:08:54.000000000 +0300
+++ php-4.3.9/ext/gd/gd.c 2004-10-19 15:35:54.529465389 +0300
@@ -211,6 +211,11 @@
#ifdef HAVE_GD_GIF_CREATE
PHP_FE(imagegif,
NULL)
#endif
+#ifdef HAVE_GD_GIF_ANIM
+ PHP_FE(imagegifanimbegin,
NULL)
+ PHP_FE(imagegifanimadd,
NULL)
+ PHP_FE(imagegifanimend,
NULL)
+#endif
#ifdef HAVE_GD_JPG
PHP_FE(imagejpeg,
NULL)
#endif
@@ -1731,12 +1736,36 @@
#ifdef HAVE_GD_GIF_CTX
_php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU,
PHP_GDIMG_TYPE_GIF, "GIF", gdImageGifCtx);
#else
+
+#ifdef HAVE_GD_BUNDLED
+#error "I really think there should be ctx version of imagegif in the bundled
GD library. Fix the configuration."
+#endif
+
_php_image_output(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_GIF,
"GIF", gdImageGif);
#endif
}
/* }}} */
#endif /* HAVE_GD_GIF_CREATE */
+#ifdef HAVE_GD_GIF_ANIM
+/* {{{ proto int imagegifanimbegin(int im [, string filename [, int
GlobalColormap [, int Loops]]])
+ Begin GIF animation. Image parameter is only used for size and colormap,
+ all animation frames must be added separately. */
+PHP_FUNCTION(imagegifanimbegin)
+{
+ _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU,
PHP_GDIMG_TYPE_GIFANIMBEGIN, "GIF", gdImageGifAnimBeginCtx);
+}
+/* }}} */
+
+/* {{{ proto int imagegifanimadd(int im [, string filename [, int
LocalColormap [, LeftOfs [, int TopOfs [, int Delay [, int Disposal [, int
previm]]]]]]])
+ Append GIF image to animation */
+PHP_FUNCTION(imagegifanimadd)
+{
+ _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU,
PHP_GDIMG_TYPE_GIFANIMADD, "GIF", gdImageGifAnimAddCtx);
+}
+/* }}} */
+#endif /* HAVE_GD_GIF_ANIM */
+
#ifdef HAVE_GD_PNG
/* {{{ proto int imagepng(int im [, string filename])
Output PNG image to browser or file */
diff -ru old/php-4.3.9/ext/gd/gd_ctx.c php-4.3.9/ext/gd/gd_ctx.c
--- old/php-4.3.9/ext/gd/gd_ctx.c 2004-01-28 18:27:42.000000000 +0200
+++ php-4.3.9/ext/gd/gd_ctx.c 2004-10-19 15:39:45.612992648 +0300
@@ -46,17 +46,22 @@
static void _php_image_output_ctx(INTERNAL_FUNCTION_PARAMETERS, int
image_type, char *tn, void (*func_p)())
{
- zval **imgind, **file, **quality;
- gdImagePtr im;
+ zval **imgind, **file, **quality, **lo, **to, **del, **dis, **previmind;
+ gdImagePtr im, previm = 0;
char *fn = NULL;
FILE *fp = NULL;
int argc = ZEND_NUM_ARGS();
int q = -1, i;
+#ifdef HAVE_GD_GIF_ANIM
+ int LeftOfs = -1, TopOfs = -1, Delay = -1, Disposal = -1;
+#endif /* HAVE_GD_GIF_ANIM */
gdIOCtx *ctx;
/* The quality parameter for Wbmp stands for the threshold when called
from image2wbmp() */
+ /* The quality parameter for GIF animation stands for colormap
inclusion. 1==include local/global colormap */
+ /* The LeftOfs parameter for GIF animation begin stands for NETSCAPE2.0
Loop count extension. */
- if (argc < 1 || argc > 3 || zend_get_parameters_ex(argc, &imgind,
&file, &quality) == FAILURE)
+ if (argc < 1 || argc > 8 || zend_get_parameters_ex(argc, &imgind,
&file, &quality, &lo, &to, &del, &dis, &previmind) == FAILURE)
{
WRONG_PARAM_COUNT;
}
@@ -66,11 +71,32 @@
if (argc > 1) {
convert_to_string_ex(file);
fn = Z_STRVAL_PP(file);
- if (argc == 3) {
- convert_to_long_ex(quality);
- q = Z_LVAL_PP(quality);
- }
}
+ if (argc >= 3) {
+ convert_to_long_ex(quality);
+ q = Z_LVAL_PP(quality);/* or colorindex for foreground of BW
images (defaults to black) */
+ }
+#ifdef HAVE_GD_GIF_ANIM
+ if (argc >= 4) {
+ convert_to_long_ex(lo);
+ LeftOfs = Z_LVAL_PP(lo);
+ }
+ if (argc >= 5) {
+ convert_to_long_ex(to);
+ TopOfs = Z_LVAL_PP(to);
+ }
+ if (argc >= 6) {
+ convert_to_long_ex(del);
+ Delay = Z_LVAL_PP(del);
+ }
+ if (argc >= 7) {
+ convert_to_long_ex(dis);
+ Disposal = Z_LVAL_PP(dis);
+ }
+ if (argc >= 8) {
+ ZEND_FETCH_RESOURCE(previm, gdImagePtr, previmind, -1, "Image",
phpi_get_le_gd());
+ }
+#endif /* HAVE_GD_GIF_ANIM */
if ((argc == 2) || (argc > 2 && Z_STRLEN_PP(file))) {
if (!fn || fn == empty_string || php_check_open_basedir(fn
TSRMLS_CC)) {
@@ -78,7 +104,7 @@
RETURN_FALSE;
}
- fp = VCWD_FOPEN(fn, "wb");
+ fp = VCWD_FOPEN(fn, PHP_GDIMG_TYPE_GIFANIMADD == image_type ?
"ab" : "wb");
if (!fp) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to
open '%s' for writing", fn);
RETURN_FALSE;
@@ -116,6 +142,14 @@
}
(*func_p)(im, i, ctx);
break;
+#ifdef HAVE_GD_GIF_ANIM
+ case PHP_GDIMG_TYPE_GIFANIMBEGIN:
+ (*func_p)(im, ctx, q, LeftOfs);
+ break;
+ case PHP_GDIMG_TYPE_GIFANIMADD:
+ (*func_p)(im, ctx, q, LeftOfs, TopOfs, Delay, Disposal,
previm);
+ break;
+#endif /* HAVE_GD_GIF_ANIM */
default:
(*func_p)(im, ctx);
break;
@@ -134,3 +168,72 @@
RETURN_TRUE;
}
+
+#ifdef HAVE_GD_GIF_ANIM
+/* {{{ proto int imagegifanimend([string filename])
+ Write end mark to gif animation. */
+PHP_FUNCTION(imagegifanimend)
+{
+ zval **file;
+ char *fn = NULL;
+ FILE *fp = NULL;
+ int argc = ZEND_NUM_ARGS();
+ gdIOCtx *ctx;
+
+ if (argc < 0 || argc > 1 || zend_get_parameters_ex(argc, &file) ==
FAILURE) {
+ ZEND_WRONG_PARAM_COUNT();
+ }
+
+ if (argc >= 1) {
+ convert_to_string_ex(file);
+ fn = Z_STRVAL_PP(file);
+ }
+
+ if ((argc == 1) || (argc > 1 && Z_STRLEN_PP(file))) {
+ if (!fn || fn == empty_string || php_check_open_basedir(fn
TSRMLS_CC)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid
filename '%s'", fn);
+ RETURN_FALSE;
+ }
+
+ fp = VCWD_FOPEN(fn, "ab");
+ if (!fp) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to
open '%s' for writing", fn);
+ RETURN_FALSE;
+ }
+
+ ctx = gdNewFileCtx(fp);
+ } else {
+ ctx = emalloc(sizeof(gdIOCtx));
+ ctx->putC = _php_image_output_putc;
+ ctx->putBuf = _php_image_output_putbuf;
+#if HAVE_LIBGD204
+ ctx->gd_free = _php_image_output_ctxfree;
+#else
+ ctx->free = _php_image_output_ctxfree;
+#endif
+
+#if APACHE && defined(CHARSET_EBCDIC)
+ /* XXX this is unlikely to work any more [EMAIL PROTECTED] */
+ /* This is a binary file already: avoid EBCDIC->ASCII
conversion */
+ ap_bsetflag(php3_rqst->connection->client, B_EBCDIC2ASCII, 0);
+#endif
+ }
+
+ /* This could be coded in here, as it only outputs ';' */
+ gdImageGifAnimEndCtx(ctx);
+
+#if HAVE_LIBGD204
+ ctx->gd_free(ctx);
+#else
+ ctx->free(ctx);
+#endif
+
+ if(fp) {
+ fflush(fp);
+ fclose(fp);
+ }
+
+ RETURN_TRUE;
+}
+/* }}} */
+#endif /* HAVE_GD_GIF_ANIM */
diff -ru old/php-4.3.9/ext/gd/php_gd.h php-4.3.9/ext/gd/php_gd.h
--- old/php-4.3.9/ext/gd/php_gd.h 2003-03-31 11:49:30.000000000 +0300
+++ php-4.3.9/ext/gd/php_gd.h 2004-10-19 15:35:54.579458364 +0300
@@ -40,6 +40,8 @@
#define PHP_GDIMG_TYPE_GD 8
#define PHP_GDIMG_TYPE_GD2 9
#define PHP_GDIMG_TYPE_GD2PART 10
+#define PHP_GDIMG_TYPE_GIFANIMBEGIN 11
+#define PHP_GDIMG_TYPE_GIFANIMADD 12
#ifdef PHP_WIN32
#define PHP_GD_API __declspec(dllexport)
@@ -137,6 +139,9 @@
PHP_FUNCTION(imagefontheight);
PHP_FUNCTION(imagegif );
+PHP_FUNCTION(imagegifanimbegin);
+PHP_FUNCTION(imagegifanimadd);
+PHP_FUNCTION(imagegifanimend);
PHP_FUNCTION(imagejpeg );
PHP_FUNCTION(imagepng);
PHP_FUNCTION(imagewbmp);
diff -ru old/php-4.3.9/main/php_config.h.in php-4.3.9/main/php_config.h.in
--- old/php-4.3.9/main/php_config.h.in 2004-09-21 01:31:59.000000000 +0300
+++ php-4.3.9/main/php_config.h.in 2004-10-19 15:35:54.582457943 +0300
@@ -1481,6 +1481,9 @@
#undef HAVE_GD_GIF_CREATE
/* */
+#undef HAVE_GD_GIF_ANIM
+
+/* */
#undef HAVE_GD_IMAGEELLIPSE
/* */
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php