From dca28c8f6eedc1d30ff068a69ab4d23de5886563 Mon Sep 17 00:00:00 2001 From: Steve Herrell Date: Tue, 7 Dec 2010 11:25:37 -0500 Subject: [PATCH] Make setjmp in jpeg code thread safe. --- rtengine/CMakeLists.txt | 2 +- rtengine/imageio.cc | 127 ++++++++++++++++++++-------------------- rtengine/jdatasrc.c | 16 ++--- rtengine/jpeg.h | 35 +++++++++++ rtengine/jpeg_memsrc.c | 4 +- rtengine/rtthumbnail.cc | 19 ++---- 6 files changed, 115 insertions(+), 88 deletions(-) create mode 100644 rtengine/jpeg.h diff --git a/rtengine/CMakeLists.txt b/rtengine/CMakeLists.txt index a16fbd9a5..a1862d947 100644 --- a/rtengine/CMakeLists.txt +++ b/rtengine/CMakeLists.txt @@ -13,7 +13,7 @@ set (RTENGINESOURCEFILES colortemp.cc curves.cc dcraw.cc iccstore.cc dfmanager.c stdimagesource.cc myfile.cc iccjpeg.c hlmultipliers.cc improccoordinator.cc processingjob.cc rtthumbnail.cc utils.cc labimage.cc slicer.cc iplab2rgb.cc ipsharpen.cc iptransform.cc ipresize.cc - jpeg_memsrc.c + jpeg_memsrc.c jdatasrc.c PF_correct_RT.cc wavelet_dec.cc ipequalizer.cc dirpyrLab_denoise.cc dirpyrLab_equalizer.cc dirpyr_equalizer.cc) diff --git a/rtengine/imageio.cc b/rtengine/imageio.cc index 12da83048..799c6ac5a 100644 --- a/rtengine/imageio.cc +++ b/rtengine/imageio.cc @@ -31,11 +31,11 @@ #endif #include #include + extern "C" { -#include "jdatasrc.c" -#include #include } +#include "jpeg.h" Glib::ustring safe_locale_to_utf8 (const std::string& src); @@ -257,68 +257,63 @@ int ImageIO::loadPNG (Glib::ustring fname) { return IMIO_SUCCESS; } -extern jmp_buf jpeg_jmp_buf; - -extern "C" { -void jpeg_memory_src (jpeg_decompress_struct* cinfo, const char* buffer, int bufsize); -} - int ImageIO::loadJPEGFromMemory (const char* buffer, int bufsize) { jpeg_decompress_struct cinfo; jpeg_error_mgr jerr; cinfo.err = my_jpeg_std_error(&jerr); jpeg_create_decompress(&cinfo); - jpeg_memory_src (&cinfo,buffer,bufsize); - if (pl) { - pl->setProgressStr ("Loading JPEG file..."); - pl->setProgress (0.0); + jpeg_memory_src (&cinfo,(const JOCTET*)buffer,bufsize); + if ( setjmp(((rt_jpeg_error_mgr*)cinfo.src)->error_jmp_buf) == 0 ) + { + if (pl) { + pl->setProgressStr ("Loading JPEG file..."); + pl->setProgress (0.0); - } + } - setup_read_icc_profile (&cinfo); + setup_read_icc_profile (&cinfo); - if (!setjmp(jpeg_jmp_buf)) { - jpeg_memory_src (&cinfo,buffer,bufsize); - jpeg_read_header(&cinfo, TRUE); + //jpeg_memory_src (&cinfo,buffer,bufsize); + jpeg_read_header(&cinfo, TRUE); unsigned int proflen; delete loadedProfileData; loadedProfileData = NULL; bool hasprofile = read_icc_profile (&cinfo, (JOCTET**)&loadedProfileData, (unsigned int*)&loadedProfileLength); - if (hasprofile) - embProfile = cmsOpenProfileFromMem (loadedProfileData, loadedProfileLength); - else + if (hasprofile) + embProfile = cmsOpenProfileFromMem (loadedProfileData, loadedProfileLength); + else embProfile = NULL; - - jpeg_start_decompress(&cinfo); + + jpeg_start_decompress(&cinfo); int width = cinfo.output_width; int height = cinfo.output_height; allocate (width, height); - unsigned char *row=new unsigned char[width*3]; - while (cinfo.output_scanline < height) { - if (jpeg_read_scanlines(&cinfo,&row,1) < 1) { - jpeg_finish_decompress(&cinfo); - jpeg_destroy_decompress(&cinfo); - delete [] row; - return IMIO_READERROR; + unsigned char *row=new unsigned char[width*3]; + while (cinfo.output_scanline < height) { + if (jpeg_read_scanlines(&cinfo,&row,1) < 1) { + jpeg_finish_decompress(&cinfo); + jpeg_destroy_decompress(&cinfo); + delete [] row; + return IMIO_READERROR; } setScanline (cinfo.output_scanline-1, row, 8); if (pl && !(cinfo.output_scanline%100)) - pl->setProgress ((double)(cinfo.output_scanline)/cinfo.output_height); - } - delete [] row; + pl->setProgress ((double)(cinfo.output_scanline)/cinfo.output_height); + } + delete [] row; - jpeg_finish_decompress(&cinfo); - jpeg_destroy_decompress(&cinfo); + jpeg_finish_decompress(&cinfo); + jpeg_destroy_decompress(&cinfo); if (pl) { - pl->setProgressStr ("Ready."); - pl->setProgress (1.0); + pl->setProgressStr ("Ready."); + pl->setProgress (1.0); } return IMIO_SUCCESS; } @@ -338,57 +333,59 @@ int ImageIO::loadJPEG (Glib::ustring fname) { jpeg_error_mgr jerr; cinfo.err = my_jpeg_std_error(&jerr); jpeg_create_decompress(&cinfo); + + my_jpeg_stdio_src (&cinfo,file); + if ( setjmp(((rt_jpeg_error_mgr*)cinfo.src)->error_jmp_buf) == 0 ) + { + if (pl) { + pl->setProgressStr ("Loading JPEG file..."); + pl->setProgress (0.0); - if (pl) { - pl->setProgressStr ("Loading JPEG file..."); - pl->setProgress (0.0); + } - } + setup_read_icc_profile (&cinfo); - setup_read_icc_profile (&cinfo); - - if (!setjmp(jpeg_jmp_buf)) { - jpeg_stdio_src(&cinfo,file); - jpeg_read_header(&cinfo, TRUE); + //jpeg_stdio_src(&cinfo,file); + jpeg_read_header(&cinfo, TRUE); unsigned int proflen; delete loadedProfileData; loadedProfileData = NULL; bool hasprofile = read_icc_profile (&cinfo, (JOCTET**)&loadedProfileData, (unsigned int*)&loadedProfileLength); - if (hasprofile) - embProfile = cmsOpenProfileFromMem (loadedProfileData, loadedProfileLength); - else + if (hasprofile) + embProfile = cmsOpenProfileFromMem (loadedProfileData, loadedProfileLength); + else embProfile = NULL; - - jpeg_start_decompress(&cinfo); + + jpeg_start_decompress(&cinfo); int width = cinfo.output_width; int height = cinfo.output_height; allocate (width, height); - unsigned char *row=new unsigned char[width*3]; - while (cinfo.output_scanline < height) { - if (jpeg_read_scanlines(&cinfo,&row,1) < 1) { - jpeg_finish_decompress(&cinfo); - jpeg_destroy_decompress(&cinfo); - delete [] row; - return IMIO_READERROR; + unsigned char *row=new unsigned char[width*3]; + while (cinfo.output_scanline < height) { + if (jpeg_read_scanlines(&cinfo,&row,1) < 1) { + jpeg_finish_decompress(&cinfo); + jpeg_destroy_decompress(&cinfo); + delete [] row; + return IMIO_READERROR; } setScanline (cinfo.output_scanline-1, row, 8); if (pl && !(cinfo.output_scanline%100)) - pl->setProgress ((double)(cinfo.output_scanline)/cinfo.output_height); - } - delete [] row; + pl->setProgress ((double)(cinfo.output_scanline)/cinfo.output_height); + } + delete [] row; - jpeg_finish_decompress(&cinfo); - jpeg_destroy_decompress(&cinfo); - fclose(file); + jpeg_finish_decompress(&cinfo); + jpeg_destroy_decompress(&cinfo); + fclose(file); if (pl) { - pl->setProgressStr ("Ready."); - pl->setProgress (1.0); + pl->setProgressStr ("Ready."); + pl->setProgress (1.0); } return IMIO_SUCCESS; } diff --git a/rtengine/jdatasrc.c b/rtengine/jdatasrc.c index 0b77f26b1..3553558d7 100644 --- a/rtengine/jdatasrc.c +++ b/rtengine/jdatasrc.c @@ -1,7 +1,10 @@ #ifndef WIN32 #define jboolean boolean #endif -#include +#include +#include +#include +#include "jpeg.h" /* * jdatasrc.c @@ -21,9 +24,6 @@ /* this is not a core library module, so it doesn't define JPEG_INTERNALS */ //#include "jinclude.h" -#include -#include -#include #define JFREAD(file,buf,sizeofbuf) \ ((size_t) fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) @@ -37,6 +37,7 @@ typedef struct { struct jpeg_source_mgr pub; /* public fields */ + jmp_buf error_jmp_buf; /* error handler for this instance */ FILE * infile; /* source stream */ JOCTET * buffer; /* start of buffer */ @@ -227,8 +228,6 @@ my_jpeg_stdio_src (j_decompress_ptr cinfo, FILE * infile) src->pub.next_input_byte = NULL; /* until buffer loaded */ } -jmp_buf jpeg_jmp_buf; - METHODDEF(void) my_error_exit (j_common_ptr cinfo) { @@ -236,9 +235,10 @@ my_error_exit (j_common_ptr cinfo) (*cinfo->err->output_message) (cinfo); /* Let the memory manager delete any temp files before we die */ - jpeg_destroy(cinfo); + //jpeg_destroy(cinfo); - longjmp (jpeg_jmp_buf, 1); + j_decompress_ptr dinfo = (j_decompress_ptr)cinfo; + longjmp (((rt_jpeg_error_mgr*)(dinfo->src))->error_jmp_buf, 1); } diff --git a/rtengine/jpeg.h b/rtengine/jpeg.h new file mode 100644 index 000000000..f709bb0d5 --- /dev/null +++ b/rtengine/jpeg.h @@ -0,0 +1,35 @@ +#ifndef _RT_JPEG_H +#define _RT_JPEG_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +extern GLOBAL(struct jpeg_error_mgr *) +my_jpeg_std_error (struct jpeg_error_mgr * err); + +extern GLOBAL(void) +my_jpeg_stdio_src (j_decompress_ptr cinfo, FILE * infile); + +GLOBAL(void) +jpeg_memory_src (j_decompress_ptr cinfo, const JOCTET * buffer, size_t bufsize); + +/** + * @brief jpeg from file and memory use this as base to managers + */ +typedef struct +{ + struct jpeg_source_mgr pub; /* public fields */ + jmp_buf error_jmp_buf; /* error handler for this instance */ +} rt_jpeg_error_mgr; + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/rtengine/jpeg_memsrc.c b/rtengine/jpeg_memsrc.c index 595649b85..4932b2f89 100644 --- a/rtengine/jpeg_memsrc.c +++ b/rtengine/jpeg_memsrc.c @@ -22,12 +22,14 @@ #include #include #include +#include "jpeg.h" /* Expanded data source object for memory input */ typedef struct { - struct jpeg_source_mgr pub; /* public fields */ + struct jpeg_source_mgr pub; /* public fields */ + jmp_buf error_jmp_buf; /* error handler for this instance */ JOCTET eoi_buffer[2]; /* a place to put a dummy EOI */ } my_source_mgr; diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc index a99e5399f..92b966598 100644 --- a/rtengine/rtthumbnail.cc +++ b/rtengine/rtthumbnail.cc @@ -34,15 +34,7 @@ #include #include #include - -extern "C" { -#include -extern jmp_buf jpeg_jmp_buf; -extern GLOBAL(struct jpeg_error_mgr *) -my_jpeg_std_error (struct jpeg_error_mgr * err); -extern GLOBAL(void) -my_jpeg_stdio_src (j_decompress_ptr cinfo, FILE * infile); -} +#include "jpeg.h" #define MAXVAL 0xffff #define CLIP(a) ((a)>0?((a)error_jmp_buf) == 0 ) + { jpeg_read_header (&cinfo, TRUE); int width, height; width = cinfo.image_width;