Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-9095

Add QByteArray API to QImageReader / QImageIOHandler and improve decoder plugins

XMLWordPrintable

    • Icon: Suggestion Suggestion
    • Resolution: Unresolved
    • Icon: P3: Somewhat important 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

      1. Investigate if this makes sense
      2. Implement QImageReader(QByteArray a, QByteArray format=QByteArray())
      3. Implement something like qimageiohandler.setSource(QByteArray a). The QImageIoHandler that does not support QByteArray-style access wraps it into a QBuffer(=QIODevice) internally
      4. Implement this way of reading for image decoders that are most relevant for QtWebKit: jpeg and gif
      5. 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.

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

            Unassigned Unassigned
            mgoetz Markus Goetz (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:

                There are no open Gerrit changes