Pregunta

My current code follows this: Disk > bytearray > QImage (or 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));

Step 1 takes 0.5s
Step 2 takes 3.0s - decoding jpeg is the slowest step
Step 3 takes 0.1s

Apparently, decoding jpeg data is the slowest step. How do I make it faster?

Is there a third party library that can transform bytearray of jpeg data to bytearray of ppm that can be loaded to QImage faster?

Btw, Using QPixmap takes the same time as QImage.

¿Fue útil?

Solución

I was able to reduce QImage load time significantly using libjpeg-turbo. Here are the steps

  • Step 1: Load .jpeg in memory filebuffer
  • Step 2a: Use tjDecompress2() to decompress filebuffer to uncompressedbuffer
  • Step 2b: Use QImage(uncompressedbuffer, int width, int height, Format pixfmt) to load the QImage
  • Step 3: Render

Step 2a and 2b combined offers atleast 3x speedup compared to QImage::loadFromData()

Notes

  • PixelFormat used in libjpeg's tjDecompress2() should match with format specified in step 2b
  • You can derive the width and height used in step 2b using tjDecompressHeader2()

Otros consejos

I think your question is more addressing a end result of a design issue rather than the design issue itself. Here are my thoughts related to the loading times of jpegs or images in general in GUIs.

Loading of data from a harddrive is a common bottleneck of software design. You have to get the harddrive to spin to that location and pull it out and copy it to the ram. Then when you are ready, you have the ram push it to the video buffer or maybe to the graphics card.

An SSD will be much faster, but demanding this of your end user is not practical in most situations. Loading the image once on startup and never closing your program is a way to avoid hitting this delay multiple times.

It is a big reason why lots of programs have a loading bar or a splash screen when it is starting up, so that it doesn't have a slow user experience when pulling up data.

Some other ways that programs handle longer processes are with the classic hour glass, or the spinning beach ball, or the "wait a bit" gifs are common.

Probably the best example of handing lots of large jpegs is google maps or some of the higher quality photo manager programs such as Picasa.

Google maps stores many different resolutions of the same area, and tiles and then load then specific to the resolution that can be viewed. Picasa "processes" all the images it finds, and stores a few different thumbnails for each one that can be loaded much faster than the full resolution image (in most cases).

My suggestion would be to either store a copy of your jpeg at a lower resolution, load that one, and then after it is loaded, replace it with the high resolution one when it is loaded, or to look into breaking your image into tiles and load them as needed.

On another related note, if you UI is getting slowed down by the jpeg loading, move the loading part into a thread and keep your UI responsive!

Hope that helps.

You asked about third-party software - -

ImageMagick can do this task quickly (even with larger files):

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

While you have the filestream open, you can do numerous operations... Hope that helps, Gette

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top