]> granicus.if.org Git - php/commitdiff
- MFH: add a weak/tolerant mode to the jpeg loader
authorPierre Joye <pajoye@php.net>
Sun, 5 Feb 2006 15:53:58 +0000 (15:53 +0000)
committerPierre Joye <pajoye@php.net>
Sun, 5 Feb 2006 15:53:58 +0000 (15:53 +0000)
ext/gd/gd.c
ext/gd/libgd/gd.h
ext/gd/libgd/gd_jpeg.c

index bc6f6b00b706b028bacd28a288a71c161f49a91b..c509b95f252f4e6dbc25bc5feac18268fd46aba7 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"
@@ -357,6 +358,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)
@@ -405,6 +412,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);
@@ -1540,6 +1549,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) ||
@@ -1620,6 +1631,14 @@ static void _php_image_create_from(INTERNAL_FUNCTION_PARAMETERS, int image_type,
                                im = gdImageCreateFromXpm(fn);
                                break;
 #endif
+
+#ifdef HAVE_GD_JPG
+                       case PHP_GDIMG_TYPE_JPG:
+                               ignore_warning = INI_INT("gd.jpeg_ignore_warning");
+                               im = gdImageCreateFromJpeg(fp, ignore_warning);
+                       break;
+#endif
+
                        default:
                                im = (*func_p)(fp);
                                break;
@@ -3841,7 +3860,8 @@ 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();
        }
@@ -3897,7 +3917,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 ce54a3c071c8883af4d766bfe4c29a430dd9b367..751a1e74e857b6db7a31424ed736c89ada2e5368 100644 (file)
@@ -237,8 +237,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..9573c1cf695687d00b0fca8a8b1cada96b2a0450 100644 (file)
@@ -43,8 +43,44 @@ static const char *const GD_JPEG_VERSION = "1.0";
 typedef struct _jmpbuf_wrapper
 {
        jmp_buf jmpbuf;
+       int ignore_warning;
 } jmpbuf_wrapper;
 
+static long php_jpeg_emit_message(j_common_ptr jpeg_info, int level)
+{
+       char message[JMSG_LENGTH_MAX];
+       jmpbuf_wrapper *jmpbufw;
+       int ignore_warning = 0;
+       
+    jmpbufw = (jmpbuf_wrapper *) jpeg_info->client_data;
+
+       if (jmpbufw != 0) {
+               ignore_warning = jmpbufw->ignore_warning;
+       }
+
+       (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(ignore_warning ? E_NOTICE : E_WARNING, "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 +243,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 +267,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;
@@ -253,8 +290,13 @@ gdImagePtr gdImageCreateFromJpegCtx (gdIOCtx * infile)
        memset (&cinfo, 0, sizeof (cinfo));
        memset (&jerr, 0, sizeof (jerr));
 
+       jmpbufw.ignore_warning = ignore_warning;
+
        cinfo.err = jpeg_std_error (&jerr);
        cinfo.client_data = &jmpbufw;
+
+       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 +428,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);