Katie image format optimization

from 2x faster to 3x compared to png, benchmark results bellow:
********* Start testing of tst_QImageReader *********
Config: Using QTest library 4.12.0, Katie 4.12.0
PASS  : tst_QImageReader::initTestCase()
RESULT   : tst_QImageReader::readImage():"bench.kat":
     0.452 msecs per iteration (total: 226, iterations: 500)
RESULT   : tst_QImageReader::readImage():"bench.pbm":
     0.026 msecs per iteration (total: 13, iterations: 500)
RESULT   : tst_QImageReader::readImage():"bench.png":
     1.82 msecs per iteration (total: 912, iterations: 500)
RESULT   : tst_QImageReader::readImage():"bench.ppm":
     0.588 msecs per iteration (total: 294, iterations: 500)
RESULT   : tst_QImageReader::readImage():"bench.svg":
     10.80 msecs per iteration (total: 5,400, iterations: 500)
RESULT   : tst_QImageReader::readImage():"bench.xpm":
     8.172 msecs per iteration (total: 4,086, iterations: 500)
PASS  : tst_QImageReader::readImage()
RESULT   : tst_QImageReader::setScaledSize():"bench.kat":
     1.95 msecs per iteration (total: 977, iterations: 500)
RESULT   : tst_QImageReader::setScaledSize():"bench.pbm":
     1.34 msecs per iteration (total: 671, iterations: 500)
RESULT   : tst_QImageReader::setScaledSize():"bench.png":
     3.328 msecs per iteration (total: 1,664, iterations: 500)
RESULT   : tst_QImageReader::setScaledSize():"bench.ppm":
     1.44 msecs per iteration (total: 720, iterations: 500)
RESULT   : tst_QImageReader::setScaledSize():"bench.svg":
     9.304 msecs per iteration (total: 4,652, iterations: 500)
RESULT   : tst_QImageReader::setScaledSize():"bench.xpm":
     9.730 msecs per iteration (total: 4,865, iterations: 500)
PASS  : tst_QImageReader::setScaledSize()
PASS  : tst_QImageReader::cleanupTestCase()
Totals: 4 passed, 0 failed, 0 skipped
********* Finished testing of tst_QImageReader *********

********* Start testing of tst_QImageWriter *********
Config: Using QTest library 4.12.0, Katie 4.12.0
PASS  : tst_QImageWriter::initTestCase()
RESULT   : tst_QImageWriter::writeImage():"kat":
     2.428 msecs per iteration (total: 1,214, iterations: 500)
RESULT   : tst_QImageWriter::writeImage():"png":
     7.798 msecs per iteration (total: 3,899, iterations: 500)
RESULT   : tst_QImageWriter::writeImage():"ppm":
     6.954 msecs per iteration (total: 3,477, iterations: 500)
PASS  : tst_QImageWriter::writeImage()
PASS  : tst_QImageWriter::cleanupTestCase()
Totals: 3 passed, 0 failed, 0 skipped
********* Finished testing of tst_QImageWriter *********

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
Ivailo Monev 2022-03-01 00:40:50 +02:00
parent 3337c33a86
commit f81903f64d
2 changed files with 31 additions and 5 deletions

View file

@ -72,7 +72,7 @@ bool QKatHandler::read(QImage *image)
return false;
}
qint64 format = 0;
qint8 format = 0;
qint64 width = 0;
qint64 height = 0;
qint64 uncompressedsize = 0;
@ -103,7 +103,7 @@ bool QKatHandler::read(QImage *image)
return false;
}
size_t decompsize = uncompressedsize;
const libdeflate_result decompresult = libdeflate_gzip_decompress(
const libdeflate_result decompresult = libdeflate_zlib_decompress(
decomp,
imagedata.constData(), imagedata.size(),
image->d->data, image->byteCount(),
@ -126,20 +126,46 @@ bool QKatHandler::write(const QImage &image)
if (image.isNull()) {
return false;
} else if (Q_UNLIKELY(image.height() >= INT_MAX || image.width() >= INT_MAX)) {
// the limit is actually lower but QImage::width() and QImage::height() return int and
// QImage can be fixed at some point, notably QImage::byteCount() return type change
qWarning("QKatHandler::write() Limitation in Katie");
return false;
}
const QImage image32 = image.convertToFormat(image.d->checkForAlphaPixels() ? QImage::Format_ARGB32 : QImage::Format_RGB16);
struct libdeflate_compressor* comp = libdeflate_alloc_compressor(m_complevel);
if (Q_UNLIKELY(!comp)) {
qWarning("QKatHandler::write() Could not allocate compressor");
return false;
}
const size_t boundresult = libdeflate_zlib_compress_bound(comp, image32.byteCount());
if (Q_UNLIKELY(boundresult <= 0)) {
qWarning("QKatHandler::write() Compression boundary is negative or zero");
libdeflate_free_compressor(comp);
return false;
}
QByteArray compressedimage(boundresult, Qt::Uninitialized);
const size_t compresult = libdeflate_zlib_compress(
comp,
reinterpret_cast<const char*>(image32.constBits()), image32.byteCount(),
compressedimage.data(), compressedimage.size()
);
libdeflate_free_compressor(comp);
if (Q_UNLIKELY(compresult <= 0)) {
qWarning("QKatHandler::write() Could not compress data");
return false;
}
QBuffer imagebuffer;
imagebuffer.open(QBuffer::ReadWrite);
QDataStream imagestream(&imagebuffer);
imagestream.writeRawData("KATIE", 5);
imagestream << (qint64) image32.format();
imagestream << (qint8) image32.format();
imagestream << (qint64) image32.width();
imagestream << (qint64) image32.height();
imagestream << (qint64) image32.byteCount();
imagestream << (QByteArray) qCompress(reinterpret_cast<const char*>(image32.constBits()), image32.byteCount(), m_complevel);
imagestream << (QByteArray) QByteArray::fromRawData(compressedimage.constData(), compresult);
if (Q_UNLIKELY(device()->write(imagebuffer.data(), imagebuffer.size()) != imagebuffer.size())) {
qWarning("QKatHandler::write() Could not write image");
@ -163,7 +189,7 @@ QVariant QKatHandler::option(QImageIOHandler::ImageOption option) const
return QVariant();
}
qint64 format = 0;
qint8 format = 0;
qint64 width = 0;
qint64 height = 0;
imagestream >> format;