diff --git a/src/zm_image.cpp b/src/zm_image.cpp index 653561365..aeaf1845d 100644 --- a/src/zm_image.cpp +++ b/src/zm_image.cpp @@ -113,19 +113,29 @@ Image *Image::HighlightEdges( Rgb colour, const Box *limits ) return( high_image ); } -void Image::ReadJpeg( const char *filename ) +bool Image::ReadJpeg( const char *filename ) { struct jpeg_decompress_struct cinfo; - struct jpeg_error_mgr jerr; - cinfo.err = jpeg_std_error(&jerr); + struct zm_error_mgr jerr; + cinfo.err = jpeg_std_error(&jerr.pub); + jerr.pub.error_exit = zm_jpeg_error_exit; + jpeg_create_decompress(&cinfo); FILE * infile; if ((infile = fopen(filename, "rb" )) == NULL) { Error(( "Can't open %s: %s", filename, strerror(errno))); - exit( -1 ); + return( false ); } + + if ( setjmp(jerr.setjmp_buffer) ) + { + jpeg_destroy_decompress(&cinfo); + fclose( infile ); + return( false ); + } + jpeg_stdio_src(&cinfo, infile); jpeg_read_header(&cinfo, TRUE); @@ -154,16 +164,17 @@ void Image::ReadJpeg( const char *filename ) jpeg_destroy_decompress(&cinfo); fclose( infile ); + + return( true ); } -void Image::WriteJpeg( const char *filename ) const +bool Image::WriteJpeg( const char *filename ) const { if ( config.colour_jpeg_files && colours == 1 ) { Image temp_image( *this ); temp_image.Colourise(); - temp_image.WriteJpeg( filename ); - return; + return( temp_image.WriteJpeg( filename ) ); } struct jpeg_compress_struct cinfo; @@ -175,7 +186,7 @@ void Image::WriteJpeg( const char *filename ) const if ((outfile = fopen(filename, "wb" )) == NULL) { Error(( "Can't open %s: %s", filename, strerror(errno))); - exit( -1 ); + return( false ); } jpeg_stdio_dest(&cinfo, outfile); @@ -209,15 +220,25 @@ void Image::WriteJpeg( const char *filename ) const jpeg_destroy_compress(&cinfo); fclose( outfile ); + + return( true ); } -void Image::DecodeJpeg( JOCTET *inbuffer, int inbuffer_size ) +bool Image::DecodeJpeg( JOCTET *inbuffer, int inbuffer_size ) { struct jpeg_decompress_struct cinfo; - struct jpeg_error_mgr jerr; - cinfo.err = jpeg_std_error(&jerr); + struct zm_error_mgr jerr; + cinfo.err = jpeg_std_error(&jerr.pub); + jerr.pub.error_exit = zm_jpeg_error_exit; + jpeg_create_decompress(&cinfo); + if ( setjmp(jerr.setjmp_buffer) ) + { + jpeg_destroy_decompress(&cinfo); + return( false ); + } + jpeg_mem_src(&cinfo, inbuffer, inbuffer_size ); jpeg_read_header(&cinfo, TRUE); @@ -244,16 +265,17 @@ void Image::DecodeJpeg( JOCTET *inbuffer, int inbuffer_size ) jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); + + return( true ); } -void Image::EncodeJpeg( JOCTET *outbuffer, int *outbuffer_size ) const +bool Image::EncodeJpeg( JOCTET *outbuffer, int *outbuffer_size ) const { if ( config.colour_jpeg_files && colours == 1 ) { Image temp_image( *this ); temp_image.Colourise(); - temp_image.EncodeJpeg( outbuffer, outbuffer_size ); - return; + return( temp_image.EncodeJpeg( outbuffer, outbuffer_size ) ); } struct jpeg_compress_struct cinfo; @@ -290,6 +312,8 @@ void Image::EncodeJpeg( JOCTET *outbuffer, int *outbuffer_size ) const jpeg_finish_compress(&cinfo); jpeg_destroy_compress(&cinfo); + + return( true ); } void Image::Overlay( const Image &image ) diff --git a/src/zm_image.h b/src/zm_image.h index 6d1086b06..23df63bef 100644 --- a/src/zm_image.h +++ b/src/zm_image.h @@ -191,10 +191,10 @@ public: return( *this ); } - void ReadJpeg( const char *filename ); - void WriteJpeg( const char *filename ) const; - void DecodeJpeg( JOCTET *inbuffer, int inbuffer_size ); - void EncodeJpeg( JOCTET *outbuffer, int *outbuffer_size ) const; + bool ReadJpeg( const char *filename ); + bool WriteJpeg( const char *filename ) const; + bool DecodeJpeg( JOCTET *inbuffer, int inbuffer_size ); + bool EncodeJpeg( JOCTET *outbuffer, int *outbuffer_size ) const; void Overlay( const Image &image ); void Blend( const Image &image, int transparency=10 ) const; diff --git a/src/zm_jpeg.c b/src/zm_jpeg.c index e8be528b9..c5dbffa57 100644 --- a/src/zm_jpeg.c +++ b/src/zm_jpeg.c @@ -18,6 +18,30 @@ */ #include "zm_jpeg.h" +#include "zm_debug.h" + +/* Overridden error handlers, mostly for decompression */ + +#define MAX_JPEG_ERRS 25 + +static int jpeg_err_count = 0; +void zm_jpeg_error_exit( j_common_ptr cinfo ) +{ + static char message[JMSG_LENGTH_MAX]; + + zm_error_ptr zmerr = (zm_error_ptr)cinfo->err; + + (*cinfo->err->format_message)( cinfo, message ); + + Error(( "JPEG error: %s", message )); + if ( ++jpeg_err_count == MAX_JPEG_ERRS ) + { + Fatal(( "Maximum number (%d) of JPEG errors reached, exiting", jpeg_err_count )); + exit( -1 ); + } + + longjmp( zmerr->setjmp_buffer, 1 ); +} /* Expanded data destination object for memory */ diff --git a/src/zm_jpeg.h b/src/zm_jpeg.h index 526a73b02..3dc8745ec 100644 --- a/src/zm_jpeg.h +++ b/src/zm_jpeg.h @@ -17,10 +17,23 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include + #include "jinclude.h" #include "jpeglib.h" #include "jerror.h" +/* Stuff for overriden error handlers */ +struct zm_error_mgr +{ + struct jpeg_error_mgr pub; + jmp_buf setjmp_buffer; +}; + +typedef struct zm_error_mgr *zm_error_ptr; + +void zm_jpeg_error_exit( j_common_ptr cinfo ); + // Prototypes for memory compress/decompression object */ void jpeg_mem_src(j_decompress_ptr cinfo, JOCTET *inbuffer, int inbuffer_size ); void jpeg_mem_dest(j_compress_ptr cinfo, JOCTET *outbuffer, int *outbuffer_size );