From 63aae8a69bd2052e8601a957f31c3d5873829b89 Mon Sep 17 00:00:00 2001 From: Pierre Joye Date: Mon, 3 Jan 2011 09:22:58 +0000 Subject: [PATCH] - stream output support for image outputs functions --- ext/gd/gd.c | 31 ++++------------ ext/gd/gd_ctx.c | 86 +++++++++++++++++++++++++++++--------------- ext/gd/libgd/gd_io.h | 1 + 3 files changed, 65 insertions(+), 53 deletions(-) diff --git a/ext/gd/gd.c b/ext/gd/gd.c index a77bbb579e..52d39bf6ec 100644 --- a/ext/gd/gd.c +++ b/ext/gd/gd.c @@ -2821,7 +2821,8 @@ static void _php_image_output(INTERNAL_FUNCTION_PARAMETERS, int image_type, char #if HAVE_GD_BUNDLED PHP_FUNCTION(imagexbm) { - _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_XBM, "XBM", gdImageXbmCtx); +// _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_XBM, "XBM", gdImageXbmCtx); + _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_XBM, "GIF", gdImageXbmCtx); } #endif /* }}} */ @@ -2831,11 +2832,7 @@ PHP_FUNCTION(imagexbm) Output GIF image to browser or file */ PHP_FUNCTION(imagegif) { -#ifdef HAVE_GD_GIF_CTX _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_GIF, "GIF", gdImageGifCtx); -#else - _php_image_output(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_GIF, "GIF", gdImageGif); -#endif } /* }}} */ #endif /* HAVE_GD_GIF_CREATE */ @@ -2845,11 +2842,7 @@ PHP_FUNCTION(imagegif) Output PNG image to browser or file */ PHP_FUNCTION(imagepng) { -#ifdef USE_GD_IOCTX - _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_PNG, "PNG", gdImagePngCtxEx); -#else - _php_image_output(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_PNG, "PNG", gdImagePng); -#endif + _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_PNG, "GIF", gdImagePngCtxEx); } /* }}} */ #endif /* HAVE_GD_PNG */ @@ -2860,11 +2853,7 @@ PHP_FUNCTION(imagepng) Output PNG image to browser or file */ PHP_FUNCTION(imagewebp) { -#ifdef USE_GD_IOCTX - _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_WEBP, "WEBP", gdImageWebpCtx); -#else - _php_image_output(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_WEBP, "WEBP", gdImageWebpCtx); -#endif + _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_WEBP, "GIF", gdImageWebpCtx); } /* }}} */ #endif /* HAVE_GD_WEBP */ @@ -2875,11 +2864,7 @@ PHP_FUNCTION(imagewebp) Output JPEG image to browser or file */ PHP_FUNCTION(imagejpeg) { -#ifdef USE_GD_IOCTX - _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_JPG, "JPEG", gdImageJpegCtx); -#else - _php_image_output(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_JPG, "JPEG", gdImageJpeg); -#endif + _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_JPG, "GIF", gdImageJpegCtx); } /* }}} */ #endif /* HAVE_GD_JPG */ @@ -2889,11 +2874,7 @@ PHP_FUNCTION(imagejpeg) Output WBMP image to browser or file */ PHP_FUNCTION(imagewbmp) { -#ifdef USE_GD_IOCTX - _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_WBM, "WBMP", gdImageWBMPCtx); -#else - _php_image_output(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_WBM, "WBMP", gdImageWBMP); -#endif + _php_image_output_ctx(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_GDIMG_TYPE_WBM, "GIF", gdImageWBMPCtx); } /* }}} */ #endif /* HAVE_GD_WBMP */ diff --git a/ext/gd/gd_ctx.c b/ext/gd/gd_ctx.c index 0ac04c855f..eb7c299203 100644 --- a/ext/gd/gd_ctx.c +++ b/ext/gd/gd_ctx.c @@ -46,6 +46,33 @@ static void _php_image_output_ctxfree(struct gdIOCtx *ctx) } } +static void _php_image_stream_putc(struct gdIOCtx *ctx, int c) { + char ch = (char) c; + php_stream * stream = (php_stream *)ctx->data; + TSRMLS_FETCH(); + php_stream_write(stream, &ch, 1); +} + +static int _php_image_stream_putbuf(struct gdIOCtx *ctx, const void* buf, int l) +{ + php_stream * stream = (php_stream *)ctx->data; + TSRMLS_FETCH(); + return php_stream_write(stream, (void *)buf, l); +} + +static void _php_image_stream_ctxfree(struct gdIOCtx *ctx) +{ + TSRMLS_FETCH(); + + if(ctx->data) { + php_stream_close((php_stream *) ctx->data); + ctx->data = NULL; + } + if(ctx) { + efree(ctx); + } +} + /* {{{ _php_image_output_ctx */ static void _php_image_output_ctx(INTERNAL_FUNCTION_PARAMETERS, int image_type, char *tn, void (*func_p)()) { @@ -54,17 +81,17 @@ static void _php_image_output_ctx(INTERNAL_FUNCTION_PARAMETERS, int image_type, int file_len = 0; long quality, basefilter; gdImagePtr im; - FILE *fp = NULL; int argc = ZEND_NUM_ARGS(); int q = -1, i; int f = -1; - gdIOCtx *ctx; + gdIOCtx *ctx = NULL; + zval *to_zval = NULL; + php_stream *stream; /* 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(). */ - if (image_type == PHP_GDIMG_TYPE_XBM) { if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs!|ll", &imgind, &file, &file_len, &quality, &basefilter) == FAILURE) { return; @@ -76,41 +103,41 @@ static void _php_image_output_ctx(INTERNAL_FUNCTION_PARAMETERS, int image_type, * PHP_GDIMG_TYPE_WBM * PHP_GDIMG_TYPE_WEBP * */ - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|s!ll", &imgind, &file, &file_len, &quality, &basefilter) == FAILURE) { + //if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|s!ll", &imgind, &file, &file_len, &quality, &basefilter) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|z/!ll", &imgind, &to_zval, &quality, &basefilter) == FAILURE) { return; } } ZEND_FETCH_RESOURCE(im, gdImagePtr, &imgind, -1, "Image", phpi_get_le_gd()); - if (argc > 1) { - if (argc >= 3) { - q = quality; /* or colorindex for foreground of BW images (defaults to black) */ - if (argc == 4) { - f = basefilter; - } + if (argc >= 3) { + q = quality; /* or colorindex for foreground of BW images (defaults to black) */ + if (argc == 4) { + f = basefilter; } } - if (argc > 1 && file_len) { - PHP_GD_CHECK_OPEN_BASEDIR(file, "Invalid filename"); - - fp = VCWD_FOPEN(file, "wb"); - if (!fp) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to open '%s' for writing: %s", file, strerror(errno)); + if (argc > 1) { + if (Z_TYPE_P(to_zval) == IS_RESOURCE) { + php_stream_from_zval_no_verify(stream, &to_zval); + if (stream == NULL) { + RETURN_FALSE; + } + } else if (Z_TYPE_P(to_zval) == IS_STRING) { + stream = php_stream_open_wrapper(Z_STRVAL_P(to_zval), "wb", REPORT_ERRORS|IGNORE_PATH|IGNORE_URL_WIN, NULL); + if (stream == NULL) { + RETURN_FALSE; + } + } else { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid 2nd parameter, it must a filename or a stream"); 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 thies@thieso.net */ @@ -119,6 +146,14 @@ static void _php_image_output_ctx(INTERNAL_FUNCTION_PARAMETERS, int image_type, #endif } + if (!ctx) { + ctx = emalloc(sizeof(gdIOCtx)); + ctx->putC = _php_image_stream_putc; + ctx->putBuf = _php_image_stream_putbuf; + ctx->gd_free = _php_image_stream_ctxfree; + ctx->data = (void *)stream; + } + switch(image_type) { case PHP_GDIMG_CONVERT_WBM: if(q<0||q>255) { @@ -161,12 +196,7 @@ static void _php_image_output_ctx(INTERNAL_FUNCTION_PARAMETERS, int image_type, ctx->free(ctx); #endif - if(fp) { - fflush(fp); - fclose(fp); - } - - RETURN_TRUE; + RETURN_TRUE; } /* }}} */ diff --git a/ext/gd/libgd/gd_io.h b/ext/gd/libgd/gd_io.h index b893751b7b..a4d66bb349 100644 --- a/ext/gd/libgd/gd_io.h +++ b/ext/gd/libgd/gd_io.h @@ -19,6 +19,7 @@ typedef struct gdIOCtx { void (*gd_free)(struct gdIOCtx*); + void *data; } gdIOCtx; typedef struct gdIOCtx *gdIOCtxPtr; -- 2.50.1