Revision: 25053
          
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=25053
Author:   elubie
Date:     2009-12-01 21:37:26 +0100 (Tue, 01 Dec 2009)

Log Message:
-----------
fix for [#19990] file browser crash

needed to fix jpg error handling to not return control to the library from 
jpg_error used as error exit. Needed to add structured exception handling 
(setjmp/longjmp) - not very nice but needed in this case. (Also recommended in 
example.c from libjpg and used in gimp ;) )

Modified Paths:
--------------
    trunk/blender/source/blender/imbuf/intern/jpeg.c

Modified: trunk/blender/source/blender/imbuf/intern/jpeg.c
===================================================================
--- trunk/blender/source/blender/imbuf/intern/jpeg.c    2009-12-01 19:43:09 UTC 
(rev 25052)
+++ trunk/blender/source/blender/imbuf/intern/jpeg.c    2009-12-01 20:37:26 UTC 
(rev 25053)
@@ -32,6 +32,8 @@
 
 /* This little block needed for linking to Blender... */
 #include <stdio.h>
+#include <setjmp.h>
+
 #include "BLI_blenlib.h"
 
 #include "imbuf.h"
@@ -41,6 +43,7 @@
 #include "IMB_imginfo.h"
 #include "IMB_jpeg.h"
 #include "jpeglib.h" 
+#include "jerror.h"
 
 /* the types are from the jpeg lib */
 static void jpeg_error (j_common_ptr cinfo);
@@ -66,7 +69,6 @@
  * 4. jmax - no scaling in the components
  */
 
-static int jpeg_failed = FALSE;
 static int jpeg_default_quality;
 static int ibuf_ftype;
 
@@ -76,15 +78,30 @@
        return 0;
 }
 
+//----------------------------------------------------------
+//     JPG ERROR HANDLING
+//----------------------------------------------------------
+
+typedef struct my_error_mgr {
+  struct jpeg_error_mgr pub;   /* "public" fields */
+
+  jmp_buf setjmp_buffer;       /* for return to caller */
+} my_error_mgr;
+
+typedef my_error_mgr * my_error_ptr;
+
 static void jpeg_error (j_common_ptr cinfo)
 {
+       my_error_ptr err = (my_error_ptr)cinfo->err;
+
        /* Always display the message */
        (*cinfo->err->output_message) (cinfo);
 
        /* Let the memory manager delete any temp files before we die */
        jpeg_destroy(cinfo);
 
-       jpeg_failed = TRUE;
+       /* return control to the setjmp point */
+       longjmp(err->setjmp_buffer, 1);
 }
 
 //----------------------------------------------------------
@@ -255,7 +272,7 @@
                x = cinfo->image_width;
                y = cinfo->image_height;
                depth = cinfo->num_components;
-               
+
                if (cinfo->jpeg_color_space == JCS_YCCK) cinfo->out_color_space 
= JCS_CMYK;
 
                jpeg_start_decompress(cinfo);
@@ -407,15 +424,25 @@
 ImBuf * imb_ibJpegImageFromFilename (const char * filename, int flags)
 {
        struct jpeg_decompress_struct _cinfo, *cinfo = &_cinfo;
-       struct jpeg_error_mgr jerr;
+       struct my_error_mgr jerr;
        FILE * infile;
        ImBuf * ibuf;
        
        if ((infile = fopen(filename, "rb")) == NULL) return 0;
 
-       cinfo->err = jpeg_std_error(&jerr);
-       jerr.error_exit = jpeg_error;
+       cinfo->err = jpeg_std_error(&jerr.pub);
+       jerr.pub.error_exit = jpeg_error;
 
+       /* Establish the setjmp return context for my_error_exit to use. */
+       if (setjmp(jerr.setjmp_buffer)) {
+               /* If we get here, the JPEG code has signaled an error.
+                * We need to clean up the JPEG object, close the input file, 
and return.
+                */
+               jpeg_destroy_decompress(cinfo);
+               fclose(infile);
+               return NULL;
+       }
+
        jpeg_create_decompress(cinfo);
        jpeg_stdio_src(cinfo, infile);
 
@@ -428,12 +455,21 @@
 ImBuf * imb_ibJpegImageFromMemory (unsigned char * buffer, int size, int flags)
 {
        struct jpeg_decompress_struct _cinfo, *cinfo = &_cinfo;
-       struct jpeg_error_mgr jerr;
+       struct my_error_mgr jerr;
        ImBuf * ibuf;
        
-       cinfo->err = jpeg_std_error(&jerr);
-       jerr.error_exit = jpeg_error;
+       cinfo->err = jpeg_std_error(&jerr.pub);
+       jerr.pub.error_exit = jpeg_error;
 
+       /* Establish the setjmp return context for my_error_exit to use. */
+       if (setjmp(jerr.setjmp_buffer)) {
+               /* If we get here, the JPEG code has signaled an error.
+                * We need to clean up the JPEG object, close the input file, 
and return.
+                */
+               jpeg_destroy_decompress(cinfo);
+               return NULL;
+       }
+
        jpeg_create_decompress(cinfo);
        memory_source(cinfo, buffer, size);
 
@@ -521,11 +557,9 @@
                }
 
                jpeg_write_scanlines(cinfo, row_pointer, 1);
-
-               if (jpeg_failed) break;
        }
 
-       if (jpeg_failed == FALSE) jpeg_finish_compress(cinfo);
+       jpeg_finish_compress(cinfo);
        free(row_pointer[0]);
 }
 
@@ -577,14 +611,25 @@
 {
        FILE * outfile;
        struct jpeg_compress_struct _cinfo, *cinfo = &_cinfo;
-       struct jpeg_error_mgr jerr;
+       struct my_error_mgr jerr;
 
        if ((outfile = fopen(name, "wb")) == NULL) return 0;
        jpeg_default_quality = 75;
 
-       cinfo->err = jpeg_std_error(&jerr);
-       jerr.error_exit = jpeg_error;
+       cinfo->err = jpeg_std_error(&jerr.pub);
+       jerr.pub.error_exit = jpeg_error;
 
+       /* Establish the setjmp return context for jpeg_error to use. */
+       if (setjmp(jerr.setjmp_buffer)) {
+               /* If we get here, the JPEG code has signaled an error.
+                * We need to clean up the JPEG object, close the input file, 
and return.
+                */
+               jpeg_destroy_compress(cinfo);
+               fclose(outfile);
+               remove(name);
+               return 0;
+       }
+
        init_jpeg(outfile, cinfo, ibuf);
 
        write_jpeg(cinfo, ibuf);
@@ -592,10 +637,6 @@
        fclose(outfile);
        jpeg_destroy_compress(cinfo);
 
-       if (jpeg_failed) {
-               remove(name);
-               return 0;
-       }
        return 1;
 }
 
@@ -604,14 +645,25 @@
 {
        FILE * outfile;
        struct jpeg_compress_struct _cinfo, *cinfo = &_cinfo;
-       struct jpeg_error_mgr jerr;
+       struct my_error_mgr jerr;
 
        if ((outfile = fopen(name, "wb")) == NULL) return 0;
        jpeg_default_quality = 90;
 
-       cinfo->err = jpeg_std_error(&jerr);
-       jerr.error_exit = jpeg_error;
+       cinfo->err = jpeg_std_error(&jerr.pub);
+       jerr.pub.error_exit = jpeg_error;
 
+       /* Establish the setjmp return context for jpeg_error to use. */
+       if (setjmp(jerr.setjmp_buffer)) {
+               /* If we get here, the JPEG code has signaled an error.
+                * We need to clean up the JPEG object, close the input file, 
and return.
+                */
+               jpeg_destroy_compress(cinfo);
+               fclose(outfile);
+               remove(name);
+               return 0;
+       }
+
        init_jpeg(outfile, cinfo, ibuf);
 
        /* adjust scaling factors */
@@ -625,10 +677,6 @@
        fclose(outfile);
        jpeg_destroy_compress(cinfo);
 
-       if (jpeg_failed) {
-               remove(name);
-               return 0;
-       }
        return 1;
 }
 
@@ -667,14 +715,25 @@
 {
        FILE * outfile;
        struct jpeg_compress_struct _cinfo, *cinfo = &_cinfo;
-       struct jpeg_error_mgr jerr;
+       struct my_error_mgr jerr;
 
        if ((outfile = fopen(name, "wb")) == NULL) return 0;
        jpeg_default_quality = 100;
 
-       cinfo->err = jpeg_std_error(&jerr);
-       jerr.error_exit = jpeg_error;
+       cinfo->err = jpeg_std_error(&jerr.pub);
+       jerr.pub.error_exit = jpeg_error;
 
+       /* Establish the setjmp return context for jpeg_error to use. */
+       if (setjmp(jerr.setjmp_buffer)) {
+               /* If we get here, the JPEG code has signaled an error.
+                * We need to clean up the JPEG object, close the input file, 
and return.
+                */
+               jpeg_destroy_compress(cinfo);
+               fclose(outfile);
+               remove(name);
+               return 0;
+       }
+
        init_jpeg(outfile, cinfo, ibuf);
 
        /* adjust scaling factors */
@@ -688,10 +747,6 @@
        fclose(outfile);
        jpeg_destroy_compress(cinfo);
 
-       if (jpeg_failed) {
-               remove(name);
-               return 0;
-       }
        return 1;
 }
 


_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to