我有一些代码使用libjpeg来解码内存中的jpeg图像,但有时当输入数据不好时会崩溃。我对libjpeg不是特别熟悉——我只是稍微修改了一些cut&粘贴代码。:)所以我想知道如何让它报告并出错或其他什么,而不是崩溃,这样我就可以跳过坏图像,继续下一个。。。
这是我的代码:我有一个std::vector<unsigned char> m_jpegBuffer;
和这个方法:
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;
}
以下是崩溃时输出的一些示例。这些日志消息不是来自我的代码-libjpeg本身一定是在打印这些消息。
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
注意,Premature end of JPEG file
似乎不会导致崩溃——我只是得到了一个右下角有点伪影的结果图像。。。这对我正在做的事情来说很好。然而,最后两行似乎只是发生在崩溃之前。
默认情况下,libjpeg错误处理程序退出程序(请参阅jerror.c
error_exit
函数)。文件表明:
如果应用程序希望在错误后重新获得控制权,则可以覆盖[error_exit]
该库包含一个示例代码,用于解释如何做到这一点:请参阅example.c
,并参阅ERROR HANDLING
部分:
错误处理:[…]我们这里的例子展示了如何重写"error_exit"方法,以便当发生致命错误时,控制被返回到库的调用方,而不是像标准的error_exit方法那样调用exit()。
然后参考my_error_exit
功能:
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);
}
主解压缩函数(GLOBAL(int) read_JPEG_file (char * filename)
)包括发生致命错误时调用的代码部分:
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;
}
因此,您需要以类似的方式覆盖默认的错误处理程序。
我也有同样的错误。
检查jconfigint.h和config.h
#define SIZEOF_SIZE_T 4
32位->4
64位->8
如果您的目标平台是32位,但"SIZEOF_SIZE_T 8"会出现此错误。
希望对你有用。