将JPEG文件最快地渲染到QWidget上的方法是什么?

3

我的当前代码遵循以下流程:磁盘 > 字节数组 > QImage(或QPixmap)> Painter

// Step 1: disk to qbytearray
QFile file("/path/to/file");
file.open(QIODevice::ReadOnly);
QByteArray blob = file.readAll();
file.close();

// Step 2: bytearray to QImage
this->mRenderImg = new QImage();
this->mRenderImg->loadFromData(blob, "JPG");

// Step 3: render
QPainter p(this);
QRect target; // draw rectangle
p.drawImage(target, *(this->mRenderImg));

第一步需要0.5秒
第二步需要3.0秒 - 解码jpeg是最慢的一步
第三步需要0.1秒

显然,解码jpeg数据是最慢的一步。我该如何使其更快?

是否有第三方库可以将jpeg数据的字节数组转换为ppm数据的字节数组,以便更快地加载到QImage中?

顺便说一下,使用QPixmapQImage所需的时间相同。


дҪ еңЁpaintEventдёӯи§Јз ҒJPEGеҗ—пјҹиҝҷжҳҜеҝ…иҰҒзҡ„еҗ—пјҹдҪ е°қиҜ•дҪҝз”ЁQLabelе’ҢQLabel::setPixmapдәҶеҗ—пјҹ - Pavel Strakhov
我的目标是将从磁盘读取.jpg图像文件并加载到QImage(或QPixmap)所需的时间最小化。一旦QImage被加载,无论是在QLabel还是任何其他小部件上,渲染它都非常快速。 我提到渲染部分的原因是为了表明我可以接受不使用Qt提供的类(如QImageQPixmap)的解决方案。 - S B
1
不需要使用 QByteArrayQImage 步骤。您可以通过将文件名传递给其构造函数来直接创建 QPixmapQPixmap pixmap("/path/to/file"); - Pavel Strakhov
@PavelStrakhov QPixmap px("path/to/file") 只是缩短了代码,但需要与步骤1和2的时间相同。我已经测试过了。在我的问题中,我故意将这两个步骤分开,因为由于磁盘延迟,我不认为步骤1有任何优化的空间。但我看到步骤2有优化的空间。 - S B
3个回答

2
我成功地使用libjpeg-turbo减少了QImage加载时间。以下是步骤:
  • 第一步:在内存中加载.jpeg格式的文件 filebuffer
  • 第二步a:使用tjDecompress2()filebuffer解压缩为uncompressedbuffer
  • 第二步b:使用QImage(uncompressedbuffer,int width,int height,Format pixfmt)加载QImage
  • 第三步:渲染

QImage :: loadFromData()相比,步骤2a和2b组合至少可以提供3倍的加速效果

注意事项

  • libjpeg的 tjDecompress2()中使用的PixelFormat应与步骤2b指定的格式匹配
  • 您可以使用tjDecompressHeader2()推导出步骤2b中使用的widthheight

1
我认为你的问题更多地涉及设计问题的最终结果,而不是设计问题本身。以下是我对GUI中JPEG或图像加载时间的想法。
从硬盘加载数据是软件设计的常见瓶颈。您必须让硬盘旋转到该位置并将其取出并复制到RAM中。然后当您准备好时,您可以让RAM将其推送到视频缓冲区或可能是图形卡。
SSD会快得多,但在大多数情况下,要求终端用户这样做是不切实际的。在启动时加载图像并永远不关闭程序是避免多次触发此延迟的方法。
这是为什么很多程序在启动时都有一个加载条或闪屏的重要原因,以便在拉取数据时不会出现缓慢的用户体验。
程序处理较长进程的其他方式包括经典的沙漏、旋转的海滩球或常见的“等一下”gif。
处理大量大型JPEG的最佳例子可能是Google Maps或一些高质量的照片管理程序,例如Picasa。
Google 地图存储同一区域的许多不同分辨率,并且加载特定于可视化分辨率的瓦片。Picasa "处理" 所有找到的图像,并为每个图像存储几个不同的缩略图,这些缩略图比完整分辨率图像(在大多数情况下)可以更快地加载。

我的建议是将您的 jpeg 副本以较低分辨率存储,加载该副本,然后在加载高分辨率图像时替换它,或者研究将图像分成瓦片并根据需要加载它们。

另外一个相关的注意事项是,如果您的 UI 被 jpeg 加载拖慢了,请将加载部分移到线程中,保持 UI 的响应性!

希望这有所帮助。


我已经有了沙漏/旋转器和线程,所以UI冻结不是一个问题。话虽如此,在我们的情况下,更快地加载图像将具有其他与性能相关的好处。现在,将文件加载到QImage可以分解为两个步骤——从磁盘读取(我的问题中的第1步)和从该数据初始化QImage对象(第2步)。我知道第1步无法优化,因为它涉及磁盘io延迟,但第2步可能可以优化。因此,这个问题。 - S B
我们无法控制用户的数据。因此,这些选项很遗憾地关闭了。 - S B

-2

你问了关于第三方软件的问题 - -

ImageMagick可以快速完成这个任务(即使是较大的文件):

convert 1.jpg 2.jpg 3.jpg outputfilenamehere.ppm

当你打开文件流时,你可以进行许多操作......希望这能帮到你, Gette


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