Reputation: 3108
I have some code that uses libjpeg to decode jpeg images in memory, but it crashes sometimes when the input data is bad. I'm not particularly familiar with libjpeg - I just slightly modified some cut&paste code. :) So I'm wondering how I can get it to report and error or something instead of crashing, so that I can just skip the bad image and move on to the next one...
Here's my code:
I have one of these std::vector<unsigned char> m_jpegBuffer;
and this method:
const IplImage* JpegImageSerializer::getImage()
{
int offset, row_stride;
JSAMPROW rowptr[1];
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
memset(&cinfo, 0, sizeof(cinfo));
memset(&jerr, 0, sizeof(jerr));
// Initialize the JPEG decompression object with default error handling
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
#ifdef NEED_SIGNAL_CATCHER
enable_signal_catcher((j_common_ptr) &cinfo); // Now safe to enable signal catcher
#endif
jpeg_mem_src(&cinfo, &this->m_jpegBuffer[0], this->m_jpegBuffer.size()); // Specify data source for decompression
jpeg_read_header(&cinfo, TRUE); // Read file header, set default decompression parameters
jpeg_start_decompress(&cinfo); // Start decompressor
IplImage* pImage = cvCreateImage(cvSize(cinfo.image_width, cinfo.image_height),
IPL_DEPTH_8U, 3);
// Process data
offset = 0;
row_stride = cinfo.image_width * 3;
while(cinfo.output_scanline < cinfo.output_height)
{
rowptr[0] = (JSAMPROW) &pImage->imageData[offset * row_stride];
jpeg_read_scanlines(&cinfo, rowptr, 1);
++offset;
}
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
return pImage;
}
Here are some examples of the output when it crashes. These log messages are not from my code - libjpeg itself must be printing these.
Premature end of JPEG file
Premature end of JPEG file
Corrupt JPEG data: premature end of data segment
Unsupported marker type 0xaf
Premature end of JPEG file
Premature end of JPEG file
Premature end of JPEG file
Premature end of JPEG file
Premature end of JPEG file
Corrupt JPEG data: premature end of data segment
Invalid JPEG file structure: two SOI markers
Note that the Premature end of JPEG file
does not appear to cause a crash - I just get a resulting image that has a little artifact in the lower right corner... which is fine for what I'm doing. The last two lines, however, appear to occur only just before a crash.
Upvotes: 3
Views: 4041
Reputation: 11
I have the same error.
check the jconfigint.h and config.h
#define SIZEOF_SIZE_T 4
32bit -> 4
64bit -> 8
if your target platform is 32bit, but “SIZEOF_SIZE_T 8” will got this error.
hopefully useful to you.
Upvotes: 1
Reputation: 16121
By defaut libjpeg error handler exits the program (see jerror.c
error_exit
function). The documentation indicates that:
Applications may override [error_exit] if they want to get control back after an error
The library contains a sample code that explains how to do that: see example.c
and please refer to the ERROR HANDLING
section:
ERROR HANDLING: [...] Our example here shows how to override the "error_exit" method so that control is returned to the library's caller when a fatal error occurs, rather than calling exit() as the standard error_exit method does.
Then refer to the my_error_exit
function:
METHODDEF(void)
my_error_exit (j_common_ptr cinfo)
{
/* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
my_error_ptr myerr = (my_error_ptr) cinfo->err;
/* Always display the message. */
/* We could postpone this until after returning, if we chose. */
(*cinfo->err->output_message) (cinfo);
/* Return control to the setjmp point */
longjmp(myerr->setjmp_buffer, 1);
}
The main decompression function (GLOBAL(int) read_JPEG_file (char * filename)
) includes the code section that gets called when a fatal error occurs:
struct my_error_mgr jerr;
/* ... */
jerr.pub.error_exit = my_error_exit;
/* 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 0;
}
So you need to override the default error handler in a similar fashion.
Upvotes: 4