当JPEG数据出现问题时,libjpeg解码会崩溃

3
我有一些使用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并不会导致程序崩溃,只会在生成的图像右下角留下一些瑕疵……这对于我的需求来说还是可以接受的。但是最后两行出现的时候,程序似乎就要崩溃了。
2个回答

4
默认情况下,libjpeg错误处理程序会退出程序(参见 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

我遇到了同样的错误。

请检查jconfigint.h和config.h文件。

#define SIZEOF_SIZE_T 4

32位 -> 4

64位 -> 8

如果您的目标平台是32位,但“SIZEOF_SIZE_T 8”将会出现此错误。

希望对您有所帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接