在QWidget上渲染jpeg文件的最快方法是什么



我当前的代码如下:Disk>byterarray>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));

步骤1需要0.5秒
步骤2需要3.0秒-解码jpeg是最慢的步骤
第3步需要0.1秒

显然,解码jpeg数据是最慢的步骤。如何使它更快?

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

顺便说一句,使用QPixmap需要与QImage相同的时间。

我能够使用libjpeg-turbo显著减少QImage加载时间。以下是的步骤

  • 步骤1:在内存filebuffer中加载.jpeg
  • 步骤2a:使用tjDecompress2()filebuffer解压缩为uncompressedbuffer
  • 步骤2b:使用QImage(uncompressedbuffer, int width, int height, Format pixfmt)加载QImage
  • 步骤3:渲染

QImage::loadFromData()相比,步骤2a和2b的组合速度至少提高了3倍

票据

libjpeg的tjDecompress2()中使用的PixelFormat应与步骤2b中指定的格式匹配
  • 可以使用tjDecompressHeader2()导出步骤2b中使用的widthheight
  • 我认为你的问题更多的是解决设计问题的最终结果,而不是设计问题本身。以下是我对GUI中jpegs或图像的加载时间的看法。

    从硬盘加载数据是软件设计的常见瓶颈。你必须让硬盘驱动器旋转到那个位置,然后将其拉出并复制到ram。然后当你准备好了,你让ram把它推到视频缓冲区,或者可能推到显卡。

    SSD会更快,但在大多数情况下,要求最终用户这样做是不现实的。在启动时加载一次映像,并且永远不要关闭程序,这是避免多次遇到此延迟的一种方法。

    这也是为什么很多程序在启动时都有加载栏或启动屏幕的一个重要原因,这样在提取数据时就不会有缓慢的用户体验。

    程序处理较长过程的其他一些方法是使用经典的沙漏、旋转的沙滩球或"等一等"gif。

    处理大量大型jpeg的最好例子可能是谷歌地图或一些更高质量的照片管理程序,如Picasa。

    谷歌地图存储了同一区域的许多不同分辨率,然后根据可以查看的分辨率加载。Picasa"处理"它找到的所有图像,并为每个图像存储一些不同的缩略图,这些缩略图的加载速度比全分辨率图像快得多(在大多数情况下)。

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

    另一个相关的注意事项是,如果你的UI因jpeg加载而变慢,请将加载部分移动到线程中,并保持你的UI响应!

    希望能有所帮助。

    您询问了有关第三方软件的问题--

    ImageMagick可以快速完成此任务(即使使用较大的文件):

    在此处转换1.jpg 2.jpg 3.jpg输出文件名.ppm

    当您打开文件流时,您可以执行许多操作。。。希望能有所帮助,Gette

    相关内容