]> granicus.if.org Git - php/commitdiff
- add a weak/tolerant mode to the jpeg loader
authorPierre Joye <pajoye@php.net>
Thu, 2 Feb 2006 20:30:54 +0000 (20:30 +0000)
committerPierre Joye <pajoye@php.net>
Thu, 2 Feb 2006 20:30:54 +0000 (20:30 +0000)
 * new INI option to enable it (off by default)
   gd.jpeg_ignore_warning (0|1)
 * The default mode is the current behavior
 * if the warning mode is enabled, the image may be loaded succesfully
   but the jpeg warnings will be raise as notices

ext/gd/gd.c
ext/gd/libgd/gd.h
ext/gd/libgd/gd_jpeg.c

index 27858202946e638d86a4f8356c86e1334acc55e3..5dc1011bed792f7aaf61e7c6ea8e8bc40de8bab4 100644 (file)
@@ -35,6 +35,7 @@
 #endif
 
 #include "php.h"
+#include "php_ini.h"
 #include "ext/standard/head.h"
 #include <math.h>
 #include "SAPI.h"
@@ -309,6 +310,12 @@ zend_module_entry gd_module_entry = {
 ZEND_GET_MODULE(gd)
 #endif
 
+/* {{{ PHP_INI_BEGIN */
+PHP_INI_BEGIN()
+    PHP_INI_ENTRY("gd.jpeg_ignore_warning", "0", PHP_INI_ALL, NULL)
+PHP_INI_END()
+/* }}} */
+
 /* {{{ php_free_gd_image
  */
 static void php_free_gd_image(zend_rsrc_list_entry *rsrc TSRMLS_DC)
@@ -357,6 +364,8 @@ PHP_MINIT_FUNCTION(gd)
        le_ps_enc = zend_register_list_destructors_ex(php_free_ps_enc, NULL, "gd PS encoding", module_number);
 #endif
 
+       REGISTER_INI_ENTRIES();
+
        REGISTER_LONG_CONSTANT("IMG_GIF", 1, CONST_CS | CONST_PERSISTENT);
        REGISTER_LONG_CONSTANT("IMG_JPG", 2, CONST_CS | CONST_PERSISTENT);
        REGISTER_LONG_CONSTANT("IMG_JPEG", 2, CONST_CS | CONST_PERSISTENT);
@@ -1375,7 +1384,8 @@ static void _php_image_create_from(INTERNAL_FUNCTION_PARAMETERS, int image_type,
        php_stream *stream;
        FILE * fp = NULL;
        int argc=ZEND_NUM_ARGS();
-
+       long ignore_warning;
+       
        if ((image_type == PHP_GDIMG_TYPE_GD2PART && argc != 5) ||
                (image_type != PHP_GDIMG_TYPE_GD2PART && argc != 1) ||
                zend_get_parameters_ex(argc, &file, &srcx, &srcy, &width, &height) == FAILURE) {
@@ -1444,6 +1454,11 @@ static void _php_image_create_from(INTERNAL_FUNCTION_PARAMETERS, int image_type,
                                im = gdImageCreateFromXpm(fn);
                                break;
 #endif
+                       case PHP_GDIMG_TYPE_JPG:
+                               ignore_warning = INI_INT("gd.jpeg_ignore_warning");
+                               im = gdImageCreateFromJpeg(fp, ignore_warning);
+                               break;
+
                        default:
                                im = (*func_p)(fp);
                                break;
@@ -3575,6 +3590,7 @@ static void _php_image_convert(INTERNAL_FUNCTION_PARAMETERS, int image_type )
        int int_threshold;
        int x, y;
        float x_ratio, y_ratio;
+       long ignore_warning;
 
        if (argc != 5 || zend_get_parameters_ex(argc, &f_org, &f_dest, &height, &width, &threshold) == FAILURE) {
                ZEND_WRONG_PARAM_COUNT();
@@ -3631,7 +3647,8 @@ static void _php_image_convert(INTERNAL_FUNCTION_PARAMETERS, int image_type )
 
 #ifdef HAVE_GD_JPG
                case PHP_GDIMG_TYPE_JPG:
-                       im_org = gdImageCreateFromJpeg(org);
+                       ignore_warning = INI_INT("gd.jpeg_ignore_warning");
+                       im_org = gdImageCreateFromJpeg(org, ignore_warning);
                        if (im_org == NULL) {
                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to open '%s' Not a valid JPEG file", fn_dest);
                                RETURN_FALSE;
index 40b27a5da91049bafa70bfd041cd713c4c0cc78f..be353abb53a4b568856029ed87c831a561f58a7b 100644 (file)
@@ -233,8 +233,8 @@ gdImagePtr gdImageCreateFromPng(FILE *fd);
 gdImagePtr gdImageCreateFromPngCtx(gdIOCtxPtr in);
 gdImagePtr gdImageCreateFromWBMP(FILE *inFile);
 gdImagePtr gdImageCreateFromWBMPCtx(gdIOCtx *infile);
-gdImagePtr gdImageCreateFromJpeg(FILE *infile);
-gdImagePtr gdImageCreateFromJpegCtx(gdIOCtx *infile);
+gdImagePtr gdImageCreateFromJpeg(FILE *infile, int ignore_warning);
+gdImagePtr gdImageCreateFromJpegCtx(gdIOCtx *infile, int ignore_warning);
 
 /* A custom data source. */
 /* The source function must return -1 on error, otherwise the number
index a276fe8539dfa026d420dbfb07170c79c17593ac..b8aced826e6d5ed2023c579b413e06480feca15f 100644 (file)
@@ -45,6 +45,33 @@ typedef struct _jmpbuf_wrapper
        jmp_buf jmpbuf;
 } jmpbuf_wrapper;
 
+static long php_jpeg_emit_message(j_common_ptr jpeg_info, int level)
+{
+       char message[JMSG_LENGTH_MAX];
+
+       (jpeg_info->err->format_message)(jpeg_info,message);
+
+       /* It is a warning message */
+       if (level < 0) {
+               /* display only the 1st warning, as would do a default libjpeg
+                * unless strace_level >= 3
+                */
+               if ((jpeg_info->err->num_warnings == 0) || (jpeg_info->err->trace_level >= 3)) {
+                       php_gd_error_ex(E_NOTICE, "gd-jpeg, libjpeg: recoverable error: %s\n", message);
+               }
+
+               jpeg_info->err->num_warnings++;
+       } else {
+               /* strace msg, Show it if trace_level >= level. */
+               if (jpeg_info->err->trace_level >= level) {
+                       php_gd_error_ex(E_NOTICE, "gd-jpeg, libjpeg: strace message: %s\n", message);
+               }
+       }
+       return 1;
+}
+
+
+
 /* Called by the IJG JPEG library upon encountering a fatal error */
 static void fatal_jpeg_error (j_common_ptr cinfo)
 {
@@ -207,21 +234,21 @@ void gdImageJpegCtx (gdImagePtr im, gdIOCtx * outfile, int quality)
        gdFree (row);
 }
 
-gdImagePtr gdImageCreateFromJpeg (FILE * inFile)
+gdImagePtr gdImageCreateFromJpeg (FILE * inFile, int ignore_warning)
 {
        gdImagePtr im;
        gdIOCtx *in = gdNewFileCtx(inFile);
-       im = gdImageCreateFromJpegCtx(in);
+       im = gdImageCreateFromJpegCtx(in, ignore_warning);
        in->gd_free (in);
 
        return im;
 }
 
-gdImagePtr gdImageCreateFromJpegPtr (int size, void *data)
+gdImagePtr gdImageCreateFromJpegPtr (int size, void *data, int ignore_warning)
 {
        gdImagePtr im;
        gdIOCtx *in = gdNewDynamicCtxEx(size, data, 0);
-       im = gdImageCreateFromJpegCtx(in);
+       im = gdImageCreateFromJpegCtx(in, ignore_warning);
        in->gd_free(in);
 
        return im;
@@ -231,11 +258,12 @@ void jpeg_gdIOCtx_src (j_decompress_ptr cinfo, gdIOCtx * infile);
 
 static int CMYKToRGB(int c, int m, int y, int k, int inverted);
 
+
 /*
  * Create a gd-format image from the JPEG-format INFILE.  Returns the
  * image, or NULL upon error.
  */
-gdImagePtr gdImageCreateFromJpegCtx (gdIOCtx * infile)
+gdImagePtr gdImageCreateFromJpegCtx (gdIOCtx * infile, int ignore_warning)
 {
        struct jpeg_decompress_struct cinfo;
        struct jpeg_error_mgr jerr;
@@ -255,6 +283,11 @@ gdImagePtr gdImageCreateFromJpegCtx (gdIOCtx * infile)
 
        cinfo.err = jpeg_std_error (&jerr);
        cinfo.client_data = &jmpbufw;
+
+       if (ignore_warning) {
+               cinfo.err->emit_message = (void (*)(j_common_ptr,int)) php_jpeg_emit_message;
+       }
+
        if (setjmp (jmpbufw.jmpbuf) != 0) {
                /* we're here courtesy of longjmp */
                if (row) {
@@ -386,12 +419,12 @@ gdImagePtr gdImageCreateFromJpegCtx (gdIOCtx * infile)
        if (jpeg_finish_decompress (&cinfo) != TRUE) {
                php_gd_error("gd-jpeg: warning: jpeg_finish_decompress reports suspended data source");
        }
-
-       /* Thanks to Truxton Fulton */
-       if (cinfo.err->num_warnings > 0) {
-               goto error;
+       if (!ignore_warning) {
+               if (cinfo.err->num_warnings > 0) {
+                       goto error;
+               }
        }
-
+       
        jpeg_destroy_decompress (&cinfo);
        gdFree (row);