Qt将不完整的JPEG数据加载到QPixMap中如何验证?

时间:2015-10-18 13:12:06

标签: c++ qt qt5

我有一个脚本,显示在服务器上找到的所有图像并定期检查。 它会不时下载一张尚未完全上传的图片,导致半张JPEG,下半部分为灰色。

我使用qbyteAray存储收到的数据并加载到QPixmap中:

QByteArray bytes = reply->readAll();  // bytes
qDebug() << "loading pixmap" ; 
qDebug() << pixmap.loadFromData(bytes);

我想检测加载是否失败并在500ms之后重试,但我找不到解决方案来验证pixmap是否包含有效的JPG数据。 loadFromData返回TRUE但在此方法中我得到一个警告,这是上面几行的应用程序输出:

loading pixmap
Corrupt JPEG data: premature end of data segment
true

如果pixmap数据已损坏,有没有办法检查/ bool?

解决方案

正如vsz所建议的,如果图像是自然图像而不是图形,则下排像素不太可能是无效JPG的精确灰色。因此,可以在方法中确定图像是否对这些行有效:

QImage img = pixmap.toImage();
    if(  img.pixel(img.width()-1,img.height()-1 )  ==  4286611584   &&  img.pixel(img.width()/2,img.height()-1 )  ==  4286611584  &&  img.pixel(0,img.height()-1 )  ==  4286611584  ) return false; //invalid color : 4286611584  (default gray jpg)
    else return true;

2 个答案:

答案 0 :(得分:3)

在损坏的JPEG数据上有几种可能的消息:

  • 损坏的JPEG数据:数据段的过早结束
  • 损坏的JPEG数据:标记0xd9
  • 之前的12个无关字节
  • 损坏的JPEG数据:坏的霍夫曼代码

不幸的是,很好的vsz方式不会捕获我遇到的其他2个错误,因为在坏图像区域没有使用默认灰色。 但是第一个错误比我在下面提出的尝试报告所有错误但在多线程中失败更好。

在Qt 4.8.6中,&#34; Corrupt JPEG数据&#34;错误直接发送到控制台,无法从qt代码中捕获它们。 不确定它何时改变,但在Qt5.5.1中,这些消息通过MessageHandler,因此可以捕获它们。

在软件中仅加载磁盘中的图片,我使用以下内容来了解​​哪张图片已损坏。 在MessageHandler中,我检测到任何&#34; Corrupt JPEG数据&#34;消息并将全局变量corrupt_jpg_detected设置为true。

if(msg.contains("Corrupt JPEG data"))
  setCorrupt_jpg_detected(&corrupt_jpg_detected, true);

然后在我读取图像的代码中,我添加以下内容:

QImage img(path_to_my_image) //read image file => will sent "Corrupt JPEG data" error if image corrupted

if(corrupt_jpg_detected) "code to print in log file / inform user of image corruption, can include path_to_my_image" 

这有一个很大的弱点,如果你使用多线程加载图片(例如使用QtConcurrent::mapped)那么第一个线程测试if(corrupt_jpg_detected)将打印图像信息,这很可能不是遇到损坏图像的线程......

答案 1 :(得分:2)

JPEG数据的解码发生在名为“libjpeg”的外部库中,因此Qt类QPixmap和QImage对它没有任何作用,因为它们接收到由libjpeg解码的图像。如果libjpeg向QPixmap提供图像,那么QPixmap将其视为成功。

2009年有人要求Qt对此采取行动(见this post),但似乎没有就此问题采取任何措施。

这意味着您很可能自己独立,除非QPixmap和QImage将在未来版本中使用新功能进行扩展,否则只能通过调用这些类中的方法来验证jpeg图像的完整性。

我会建议以下之一:

  • 自己访问libjpeg
  • 检查图像最后一行的颜色。最低行的每个像素都不太可能与图像损坏的情况相同。这取决于您的应用程序,但如果您处理自然图像(照片),那么这是我建议的解决方案。