-
Suggestion
-
Resolution: Unresolved
-
P3: Somewhat important
-
None
-
4.6.2
-
None
How QtWebKit decodes images
From QImageDecoderQt.cpp
// Attempt to load the data QByteArray imageData = QByteArray::fromRawData(m_data->data(), m_data->size()); m_buffer = new QBuffer; m_buffer->setData(imageData); m_buffer->open(QBuffer::ReadOnly | QIODevice::Unbuffered); m_reader = new QImageReader(m_buffer, m_format);
QBuffer is a QIODevice which means that it has a read(char*,qint64)
function that is used to read from the QByteArray.
The QImageReader will then find and instanciate a QImageIOHandler which will deal
with the actual reading of the encoded data and creating the QImage.
The problem?
Accessing a QByteArray via a QIODevice-style interface is costly when the actual image
decoder library supports direct pointer access. Each read(char*,qint64) call
copies memory.
JPEG QImageIOHandler
We implement a jpeg_source_mgr that the libjpeg uses to access the encoded image data.
Currently, this is done in qt_fill_input_buffer and it reads/copies in chunks with
a maximum size of 4K. libjpeg takes pointers to input data, it is therefore
perfectly fine to give it the whole encoded image data without copying in chunks.
GIF QImageIOHandler
We don't use libgif but do it ourselves. This means we can definitely use pointer-style access
instead of QIODevice-style.
PNG QImageIOHandler
Unfortunately, libpng needs a custom read()-style function that we implement (iod_read_fn).
I've only looked briefly at libpng but it seems like we cannot use a pointer-access style method with it.
What we should do
- Investigate if this makes sense
- Implement QImageReader(QByteArray a, QByteArray format=QByteArray())
- Implement something like qimageiohandler.setSource(QByteArray a). The QImageIoHandler that does not support QByteArray-style access wraps it into a QBuffer(=QIODevice) internally
- Implement this way of reading for image decoders that are most relevant for QtWebKit: jpeg and gif
- Check if there is a way to do it for png too.
Since this is new API, this is earliest 4.8.
QtWebKit currently does not do progressive image rendering. The method I outlined here
only works for non-progressive rendering.