Make setjmp in jpeg code thread safe.

This commit is contained in:
Steve Herrell 2010-12-07 11:25:37 -05:00
parent f4796cc776
commit dca28c8f6e
6 changed files with 115 additions and 88 deletions

View File

@ -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)

View File

@ -31,11 +31,11 @@
#endif
#include <iptcpairs.h>
#include <libiptcdata/iptc-jpeg.h>
extern "C" {
#include "jdatasrc.c"
#include <jpeglib.h>
#include <iccjpeg.h>
}
#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;
}

View File

@ -1,7 +1,10 @@
#ifndef WIN32
#define jboolean boolean
#endif
#include <setjmp.h>
#include <stdio.h>
#include <jpeglib.h>
#include <jerror.h>
#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 <stdio.h>
#include <jpeglib.h>
#include <jerror.h>
#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);
}

35
rtengine/jpeg.h Normal file
View File

@ -0,0 +1,35 @@
#ifndef _RT_JPEG_H
#define _RT_JPEG_H
#include <setjmp.h>
#ifdef __cplusplus
extern "C" {
#endif
#include <jpeglib.h>
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

View File

@ -22,12 +22,14 @@
#include <stdio.h>
#include <jpeglib.h>
#include <jerror.h>
#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;

View File

@ -34,15 +34,7 @@
#include <setjmp.h>
#include <safekeyfile.h>
#include <rawimage.h>
extern "C" {
#include <jpeglib.h>
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)<MAXVAL?(a):MAXVAL):0)
@ -1130,10 +1122,11 @@ bool Thumbnail::readImage (const Glib::ustring& fname) {
return false;
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
if (!setjmp(jpeg_jmp_buf)) {
cinfo.err = my_jpeg_std_error (&jerr);
jpeg_create_decompress (&cinfo);
my_jpeg_stdio_src (&cinfo,f);
cinfo.err = my_jpeg_std_error (&jerr);
jpeg_create_decompress (&cinfo);
my_jpeg_stdio_src (&cinfo,f);
if ( setjmp(((rt_jpeg_error_mgr*)cinfo.src)->error_jmp_buf) == 0 )
{
jpeg_read_header (&cinfo, TRUE);
int width, height;
width = cinfo.image_width;