|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2009-09-28 05:03 UTC] sriram dot natarajan at gmail dot com
Description: ------------ GD library is commonly used in PHP5 applications for image processing. When creating thumbnails from a large jpeg image, the original image currently has to be decoded to a full-size copy before being resampled or resized. This is a relatively expensive step. The underlying jpeg library has a capability of prescaling an image when it is being decoded, so for example the decoded image could be only 1/16 the size of the fullsize image by prescaling by a factor of 4. This saves a substantial amount of cpu time. Expected result: ---------------- we can update php libgd library and our php gd extension to leverage underlying jpeg's ability to prescale image at the time of creating jpeg images. for example, we can introduce new API or patch our existing gdImageCreateFromJpeg API to have an extra argument for prescale size so that we can set the value of 'prescale' value like below cinfo.scale_denom = prescale; before calling "jpeg_start_decompress (&cinfo)" function. [credits: thanks to Richard Smith for coming up with this nice suggestion] af course, this will allow users to invoke our 'imagecreatefromjpeg' with an optional argument which specifies the prescale size of this jpeg. $src_img=imagecreatefromjpeg($name, 4); Actual result: -------------- better performance while producing jpeg based thumbnails PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Sat Nov 08 13:00:01 2025 UTC |
here is a suggested patch (against 5.3). i have made this patch so that it uses this prescale value only against bundled libgd. let me know , if this makes sense to you. Index: ext/gd/libgd/gd_jpeg.c =================================================================== --- ext/gd/libgd/gd_jpeg.c (revision 289063) +++ ext/gd/libgd/gd_jpeg.c (working copy) @@ -260,21 +260,21 @@ gdFree (row); } -gdImagePtr gdImageCreateFromJpeg (FILE * inFile, int ignore_warning) +gdImagePtr gdImageCreateFromJpeg (FILE * inFile, int ignore_warning, int prescale) { gdImagePtr im; gdIOCtx *in = gdNewFileCtx(inFile); - im = gdImageCreateFromJpegCtx(in, ignore_warning); + im = gdImageCreateFromJpegCtx(in, ignore_warning, prescale); in->gd_free (in); return im; } -gdImagePtr gdImageCreateFromJpegPtr (int size, void *data, int ignore_warning) +gdImagePtr gdImageCreateFromJpegPtr (int size, void *data, int ignore_warning, int prescale) { gdImagePtr im; gdIOCtx *in = gdNewDynamicCtxEx(size, data, 0); - im = gdImageCreateFromJpegCtx(in, ignore_warning); + im = gdImageCreateFromJpegCtx(in, ignore_warning, prescale); in->gd_free(in); return im; @@ -289,7 +289,7 @@ * Create a gd-format image from the JPEG-format INFILE. Returns the * image, or NULL upon error. */ -gdImagePtr gdImageCreateFromJpegCtx (gdIOCtx * infile, int ignore_warning) +gdImagePtr gdImageCreateFromJpegCtx (gdIOCtx * infile, int ignore_warning, int prescale) { struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr; @@ -327,6 +327,8 @@ cinfo.err->error_exit = fatal_jpeg_error; + cinfo.scale_denom = prescale; + jpeg_create_decompress (&cinfo); jpeg_gdIOCtx_src (&cinfo, infile); Index: ext/gd/libgd/gd.h =================================================================== --- ext/gd/libgd/gd.h (revision 289063) +++ ext/gd/libgd/gd.h (working copy) @@ -247,8 +247,8 @@ gdImagePtr gdImageCreateFromPngCtx(gdIOCtxPtr in); gdImagePtr gdImageCreateFromWBMP(FILE *inFile); gdImagePtr gdImageCreateFromWBMPCtx(gdIOCtx *infile); -gdImagePtr gdImageCreateFromJpeg(FILE *infile, int ignore_warning); -gdImagePtr gdImageCreateFromJpegCtx(gdIOCtx *infile, int ignore_warning); +gdImagePtr gdImageCreateFromJpeg(FILE *infile, int ignore_warning, int prescale); +gdImagePtr gdImageCreateFromJpegCtx(gdIOCtx *infile, int ignore_warning, int prescale); int gdJpegGetVersionInt(); const char * gdPngGetVersionString(); Index: ext/gd/gd.c =================================================================== --- ext/gd/gd.c (revision 289063) +++ ext/gd/gd.c (working copy) @@ -342,6 +342,7 @@ #ifdef HAVE_GD_JPG ZEND_BEGIN_ARG_INFO(arginfo_imagecreatefromjpeg, 0) ZEND_ARG_INFO(0, filename) + ZEND_ARG_INFO(0, prescale) ZEND_END_ARG_INFO() #endif @@ -2407,7 +2408,10 @@ FILE * fp = NULL; #ifdef HAVE_GD_JPG long ignore_warning; +#if HAVE_GD_BUNDLED + long prescale = 0; #endif +#endif if (image_type == PHP_GDIMG_TYPE_GD2PART) { if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sllll", &file, &file_len, &srcx, &srcy, &width, &height) == FAILURE) { return; @@ -2416,6 +2420,12 @@ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Zero width or height not allowed"); RETURN_FALSE; } +#if defined(HAVE_GD_JPG) && defined(HAVE_GD_BUNDLED) + } else if (image_type == PHP_GDIMG_TYPE_JPG) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &file, &file_len, &prescale) == FAILURE) { + return; + } +#endif } else { if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &file, &file_len) == FAILURE) { return; @@ -2460,6 +2470,10 @@ if (image_type == PHP_GDIMG_TYPE_GD2PART) { im = (*ioctx_func_p)(io_ctx, srcx, srcy, width, height); +#if defined(HAVE_GD_JPG) && defined(HAVE_GD_BUNDLED) + } else if (image_type == PHP_GDIMG_TYPE_JPG) { + im = (*ioctx_func_p)(io_ctx, prescale); +#endif } else { im = (*ioctx_func_p)(io_ctx); } @@ -2493,7 +2507,7 @@ case PHP_GDIMG_TYPE_JPG: ignore_warning = INI_INT("gd.jpeg_ignore_warning"); #ifdef HAVE_GD_BUNDLED - im = gdImageCreateFromJpeg(fp, ignore_warning); + im = gdImageCreateFromJpeg(fp, ignore_warning, prescale); #else im = gdImageCreateFromJpeg(fp); #endif @@ -2533,7 +2547,7 @@ #endif /* HAVE_GD_GIF_READ */ #ifdef HAVE_GD_JPG -/* {{{ proto resource imagecreatefromjpeg(string filename) +/* {{{ proto resource imagecreatefromjpeg(string filename[, int prescale]) Create a new image from JPEG file or URL */ PHP_FUNCTION(imagecreatefromjpeg) {