C

Image decoder integration

Overview

For image assets that are in a custom format, that is not known to Qt Quick Ultralite, the image decoder provides an easy to implement API allowing these images to be decoded. The Qt Quick Ultralite engine automatically picks the right decoder depending on the image format.

Images can be loaded from SD card without pre-processing or even declaring it in the project. Regardless if the asset is stored in Flash or on SD card, there is only a single API to be implemented.

The custom image decoder is useful when assets are to be kept in a format that that is specific to your use case. The decoding is under full control of the implementer, which can make use of any hardware acceleration available on a device.

To load arbitrary image formats, an image decoder implementation has to be registered with the application in the initialization phase. Whenever an image from the resources or from disk (file://) is going to be shown Qt Quick Ultralite will check if it has the built-in asset format. If it doesn't, all registered image decoders are used to decode the image in the order they have been registered. The first decoder reporting it is able to decode an image is used. If case you have decodable images in the resources, the decoder registration has to happen before calling Qul::initPlatform().

Implementing an image decoder for Qt Quick Ultralite

Custom image decoders have to implement the Qul::PlatformInterface::ImageDecoder class. A example implementation for accelerated hardware JPEG decoders can be found in the imagedecoder.

The following code shows example implementations for this class:

class MyDecoder : public Qul::PlatformInterface::ImageDecoder
{
public:
    bool imageInformation(RequestDataCallback &callback,
                          int16_t *width,
                          int16_t *height,
                          Qul::PixelFormat *actualPixelFormat,
                          Qul::PixelFormat optimalOpaquePixelFormat,
                          Qul::PixelFormat optimalAlphaPixelFormat);
    int decodeImage(RequestDataCallback &callback,
                    unsigned char *outbuffer,
                    uint32_t outbufferSize,
                    Qul::PixelFormat pixelFormat,
                    uint32_t requiredBytesPerLine);
}
bool MyDecoder::imageInformation(RequestDataCallback &callback,
                                 int16_t *width,
                                 int16_t *height,
                                 Qul::PixelFormat *actualPixelFormat,
                                 Qul::PixelFormat optimalOpaquePixelFormat,
                                 Qul::PixelFormat optimalAlphaPixelFormat)
{
    unsigned char buffer[1024];
    uint32_t offset 0; // Start from beginning of the file

    callback.read(buffer, offset, 8)

    // Check if this decoder is able to decode the image
    if (buffer[0] != 0x89 || buffer[1] != 0x50 … ) { // PNG format header: 89 50 4E 47 0D 0A 1A 0A
        return false; // Return early when the format is unknown
    }

    // Read more data from the image to determine the size and pixel format.
    callback.read(buffer, offset, sizeof(buffer))
    *width = getImageWidth(buffer);
    *height = getImageHeight(buffer);
    *actualPixelFormat = getOptimalImageFormat(buffer, optimalOpaquePixelFormat, optimalAlphaPixelFormat);

    return true;
}
int MyDecoder::decodeImage(RequestDataCallback &callback,
                           unsigned char *outbuffer,
                           uint32_t outbufferSize,
                           Qul::PixelFormat pixelFormat,
                           uint32_t requiredBytesPerLine)
{
    unsigned char *allocatedBuffer = NULL;

    allocatedBuffer = callback.rawData();
    if (!allocatedBuffer) {
        // The data is not in addressable memory and might need to be fetched
        uint32_t bufferSize = callback.totalAvailableDataSize();
        allocatedBuffer = (unsigned char *) Qul::Platform::qul_malloc(bufferSize);
        callback.readData(allocatedBuffer, 0, bufferSize);
    }

    hardware_decode(allocatedBuffer, bufferSize, outbuffer, outbufferSize);
    Qul::Platform::qul_free(allocatedBuffer);

    return 0;
}

To make the implemented image decoder known to Qt Quick Ultralite, it has to be registered with the application.

static MyDecoder decoder;
Qul::Application::addImageDecoder(&decoder);

Available under certain Qt licenses.
Find out more.