C

Qt Quick Ultralite imagedecoder Example

// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial

#include <platforminterface/log.h>
#include <platforminterface/imagedecoder.h>
#include <stdint.h>

bool probeJpeg(const unsigned char *data, uint32_t size)
{
    // Detect JPG images
    // FF D8 FF E0 xx xx 4A 46
    // FF D8 FF E1 xx xx 45 78
    // FF D8 FF E8 xx xx 53 50

    if (size < 8)
        return false;

    if (data[0] != 0xff || data[1] != 0xd8 || data[2] != 0xff)
        return false;

    if (data[3] == 0xe0 && data[6] == 0x4a && data[7] == 0x46)
        return true;
    else if (data[3] == 0xe1 && data[6] == 0x45 && data[7] == 0x78)
        return true;
    else if (data[3] == 0xe8 && data[6] == 0x53 && data[7] == 0x50)
        return true;

    return false;
}

bool jpegInformation(Qul::PlatformInterface::ImageDecoder::RequestDataCallback &callback,
                     int16_t *width,
                     int16_t *height,
                     Qul::PixelFormat *actualPixelFormat,
                     Qul::PixelFormat optimalOpaquePixelFormat,
                     Qul::PixelFormat optimalAlphaPixelFormat)
{
    QUL_UNUSED(optimalOpaquePixelFormat);
    QUL_UNUSED(optimalAlphaPixelFormat);

    {
        unsigned char buffer[8];
        if (callback.readData(buffer, 0, sizeof(buffer)) != sizeof(buffer))
            return false;
        if (!probeJpeg(buffer, sizeof(buffer)))
            return false;
    }

    uint32_t offset = 0;

    while (1) {
        unsigned char marker;
        do {
            if (callback.readData(&marker, offset, sizeof(marker)) != sizeof(marker))
                return false;
            offset += sizeof(marker);
        } while (marker == 0xff); // Ignore start and padding bytes

        if (marker > 0xd0 && marker <= 0xd8)
            continue;
        if (marker == 0xd9)
            return false;   // EOI without finding a size block
        if (marker == 0x01) // TEM
            continue;

        if (marker == 0xc0) {
            unsigned char buffer[8];

            if (callback.readData(buffer, offset, sizeof(buffer)) != sizeof(buffer))
                return false;
            offset += sizeof(buffer);

            *height = buffer[3];
            *height <<= 8;
            *height += buffer[4];

            *width = buffer[5];
            *width <<= 8;
            *width += buffer[6];

            *actualPixelFormat = Qul::PixelFormat_ARGB32; // FIXME
            return true;
        }
        unsigned char buffer[2];
        if (callback.readData(buffer, offset, sizeof(buffer)) != sizeof(buffer))
            return false;
        offset += sizeof(buffer);
        uint32_t len = buffer[0];
        len <<= 8;
        len += buffer[1];
        len -= 2; // The two bytes from the length itself need to be subtracted

        offset += len; /* Discard data */
    }
}