我有一些代码使用libjpeg来解码内存中的jpeg图像,但是当输入数据不好时它会崩溃。我对libjpeg并不是特别熟悉 - 我只是略微修改了一些剪切和粘贴代码。 :)所以我想知道如何让它报告和错误或其他东西而不是崩溃,这样我就可以跳过坏图像继续下一个...
这是我的代码:
我有其中一个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
似乎不会导致崩溃 - 我只是得到一个在右下角有一点神器的结果图像......这对我正在做的事情很好。然而,最后两行似乎只是在崩溃之前发生。
答案 0 :(得分:3)
通过defaut 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;
}
因此,您需要以类似的方式覆盖默认错误处理程序。
答案 1 :(得分:0)
我有同样的错误。
检查jconfigint.h和config.h
#define SIZEOF_SIZE_T 4
32位 - &gt; 4
64位 - &gt; 8
如果您的目标平台是32位,但“SIZEOF_SIZE_T 8”将收到此错误。
希望对你有用。