当JPEG数据不好时,libjpeg解码崩溃

时间:2013-12-04 19:09:20

标签: c++ crash jpeg decode libjpeg

我有一些代码使用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 个答案:

答案 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”将收到此错误。

希望对你有用。