4

Using Qt 4.8rc1, I have a QImage that I want to convert to a png file. It seems like it is taking longer than it should to convert to png format: ~70ms for an 800x800 empty png. Is there a way I can make this more efficient, or am I just inherently limited by png/zlib?

Here is the benchmark I am running:

#include <QtGui>
#include <QTimer>


int
main(int argc, char *argv[]) {
  int times = 1000;
  QString format("png");

  QByteArray ba;
  QBuffer* buffer = new QBuffer(&ba);
  buffer->open(QIODevice::WriteOnly);

  QTime timer;
  timer.start();

  while(times--) {
    QImage image(800, 800, QImage::Format_RGB32);
    image.save(buffer, format.toAscii(), -1);
  }

  int elapsed = timer.elapsed();

  qDebug() << "Completed 1000 runs in" << elapsed << "ms. (" <<  (elapsed / 1000) << "ms / render )";
}
Michael Nutt
  • 178
  • 1
  • 8

1 Answers1

3

The third argument of QImage::save(const QString & fileName, const char * format = 0, int quality = -1 ) might help you. The documentation says the following:

The quality factor must be in the range 0 to 100 or -1. Specify 0 to obtain small compressed files, 100 for large uncompressed files, and -1 (the default) to use the default settings.

If you are lucky then by changing the value of quality you can change how much time zlib spends on trying to compress the image data. I would call QImage::save() with various quality values and see if execution time changes or not.

Though the Qt doc says that quality must be in the range 0 to 100 and specify 0 to obtain small compressed files, 100 for large uncompressed files the zlib manual shows different range:

// Compression levels.
#define Z_NO_COMPRESSION         0
#define Z_BEST_SPEED             1
#define Z_BEST_COMPRESSION       9
#define Z_DEFAULT_COMPRESSION  (-1)

Try values based on both ranges.

Bill
  • 11,595
  • 6
  • 44
  • 52
  • 1
    Thanks, this pointed me in the right direction. The compression level helped some, but the thing that made the most impact was to set the PNG filter to none. (`png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, PNG_FILTER_NONE);`) Unfortunately that isn't modifiable through QImage and it looks like I have to create my own QImageWriter. – Michael Nutt Nov 07 '11 at 00:41
  • You're welcome. QPNGImageWriter (`https://qt.gitorious.org/qt/qt/blobs/4.7/src/gui/image/qpnghandler.cpp#line695`) does not seem to call png_set_filter(). Does not it mean that PNG filter is none? – Bill Nov 07 '11 at 07:27
  • I can't figure out from the docs, but from my tests it's much (3-4x) faster when explicitly setting it to none so it must default to one of the other filters. – Michael Nutt Nov 08 '11 at 03:35