From 412aa510a121c2fa39b0c7ba0d3e4e7ae87eb89c Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Mon, 25 Mar 2013 18:29:29 -0700 Subject: [PATCH] fix jpeg/tiff error handling on failed reads - closes #1775 --- src/jpeg_reader.cpp | 44 ++++++++++++++++++++++++++++++-------------- src/tiff_reader.cpp | 8 ++++++++ 2 files changed, 38 insertions(+), 14 deletions(-) diff --git a/src/jpeg_reader.cpp b/src/jpeg_reader.cpp index 1b3eab6c1..05dbd66fe 100644 --- a/src/jpeg_reader.cpp +++ b/src/jpeg_reader.cpp @@ -45,6 +45,9 @@ private: std::string fileName_; unsigned width_; unsigned height_; + jpeg_decompress_struct cinfo; + jpeg_error_mgr jerr; + FILE *fp; public: explicit JpegReader(std::string const& fileName); ~JpegReader(); @@ -54,6 +57,8 @@ public: void read(unsigned x,unsigned y,image_data_32& image); private: void init(); + static void on_error(j_common_ptr cinfo); + static void on_error_message(j_common_ptr cinfo); }; namespace @@ -68,27 +73,43 @@ const bool registered = register_image_reader("jpeg",createJpegReader); JpegReader::JpegReader(std::string const& fileName) : fileName_(fileName), width_(0), - height_(0) + height_(0), + fp(NULL) { init(); } -JpegReader::~JpegReader() {} +JpegReader::~JpegReader() { + if (fp) + { + fclose(fp); + } + jpeg_destroy_decompress(&cinfo); +} + +void JpegReader::on_error(j_common_ptr cinfo) +{ + (*cinfo->err->output_message)(cinfo); + jpeg_destroy(cinfo); + throw image_reader_exception("JPEG Reader: libjpeg could not read image"); +} + +void JpegReader::on_error_message(j_common_ptr cinfo) +{ + // used to supress jpeg from printing to stderr +} void JpegReader::init() { - FILE *fp = fopen(fileName_.c_str(),"rb"); + fp = fopen(fileName_.c_str(),"rb"); if (!fp) throw image_reader_exception("JPEG Reader: cannot open image file " + fileName_); - struct jpeg_decompress_struct cinfo; - struct jpeg_error_mgr jerr; - cinfo.err = jpeg_std_error(&jerr); - + jerr.error_exit = on_error; + jerr.output_message = on_error_message; jpeg_create_decompress(&cinfo); jpeg_stdio_src(&cinfo, fp); jpeg_read_header(&cinfo, TRUE); - jpeg_start_decompress(&cinfo); width_ = cinfo.output_width; height_ = cinfo.output_height; @@ -110,12 +131,9 @@ unsigned JpegReader::height() const void JpegReader::read(unsigned x0, unsigned y0, image_data_32& image) { - struct jpeg_decompress_struct cinfo; - - FILE *fp = fopen(fileName_.c_str(),"rb"); + fp = fopen(fileName_.c_str(),"rb"); if (!fp) throw image_reader_exception("JPEG Reader: cannot open image file " + fileName_); - struct jpeg_error_mgr jerr; cinfo.err = jpeg_std_error(&jerr); jpeg_create_decompress(&cinfo); @@ -129,7 +147,6 @@ void JpegReader::read(unsigned x0, unsigned y0, image_data_32& image) if (cinfo.output_width == 0) { jpeg_destroy_decompress (&cinfo); - fclose(fp); throw image_reader_exception("JPEG Reader: failed to read image size of " + fileName_); } @@ -168,6 +185,5 @@ void JpegReader::read(unsigned x0, unsigned y0, image_data_32& image) } jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); - fclose(fp); } } diff --git a/src/tiff_reader.cpp b/src/tiff_reader.cpp index 43a3beac1..9c1897b68 100644 --- a/src/tiff_reader.cpp +++ b/src/tiff_reader.cpp @@ -82,6 +82,7 @@ private: void read_stripped(unsigned x,unsigned y,image_data_32& image); void read_tiled(unsigned x,unsigned y,image_data_32& image); TIFF* load_if_exists(std::string const& filename); + static void on_error(const char* /*module*/, const char* fmt, va_list argptr); }; namespace @@ -107,11 +108,18 @@ tiff_reader::tiff_reader(std::string const& file_name) init(); } +void tiff_reader::on_error(const char* /*module*/, const char* fmt, va_list argptr) +{ + char msg[10240]; + vsprintf(msg, fmt, argptr); + throw image_reader_exception(msg); +} void tiff_reader::init() { // TODO: error handling TIFFSetWarningHandler(0); + TIFFSetErrorHandler(on_error); TIFF* tif = load_if_exists(file_name_); if (!tif) throw image_reader_exception( std::string("Can't load tiff file: '") + file_name_ + "'");