C

Qt Quick Ultralite image_loading Example

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

#include "myimageloader.h"
#include <qul/application.h>
#include <platforminterface/allocator.h>

Qul::SharedImage MyImageProvider::requestImage(const char *imageName, size_t imageNameLength)
{
    if (imageNameLength < 8)
        return Qul::SharedImage();

    // Parse the image name to determine the colors to use for the image
    colors[0] = imageName[5] - '0';
    colors[1] = imageName[6] - '0';
    colors[2] = imageName[7] - '0';

    loadSteps = 3;
    currentLoadStep = 0;

    // Create the image and mark it as being-written-to
    Qul::Image img(120, 120, Qul::PixelFormat_RGB16);
    sharedImage = img;
    img.beginWrite();

    // Start the image loading process.
    //
    // Here, we start a timer that fills the image data step by step.
    // When multithreading is available, this could start a real asynchronous task.
    //
    // When done, post an event to trigger endWrite().
    // (postEvent() is safe to call asynchronously, while endWrite() is not)
    Timeout timeout;
    timeout.object = this;

    m_asyncLoadTimer.setInterval(300);
    m_asyncLoadTimer.onTimeout(timeout);
    m_asyncLoadTimer.start();

    // Return the unfinished image. Since beginWrite() was called on it, nothing
    // will be drawn to the screen yet.
    return sharedImage;
}

// This function will be called on timer's timeout
void MyImageProvider::Timeout::operator()()
{
    // Fill a segment of the image with a solid color
    assert(object->sharedImage.image());
    Qul::Image &image = *(object->sharedImage).image();
    uint16_t *pixelBegin = reinterpret_cast<uint16_t *>(
        image.bits() + image.bytesPerLine() * image.height() * object->currentLoadStep / object->loadSteps);
    uint16_t *pixelEnd = reinterpret_cast<uint16_t *>(
        image.bits() + image.bytesPerLine() * image.height() * (object->currentLoadStep + 1) / object->loadSteps);
    const uint32_t color = (0xFF / 2 * object->colors[object->currentLoadStep]) << (object->currentLoadStep * 8);
    const uint16_t colorRGB16 = ((color >> 3) & 0x001f) | ((color >> 5) & 0x07e0) | ((color >> 8) & 0xf800);
    std::fill(pixelBegin, pixelEnd, colorRGB16);

    object->currentLoadStep++;
    if (object->currentLoadStep == object->loadSteps) {
        object->m_asyncLoadTimer.stop();
        object->postEvent(Qul::PlatformInterface::qul_new<MyImageLoadedEvent>(image));
    }
}

void MyImageProvider::onEvent(MyImageLoadedEvent *const &event)
{
    // Causes the finished image to become visible.
    event->sharedImage.image()->endWrite();
    Qul::PlatformInterface::qul_delete(event);
}

void MyImageProvider::onEventDiscarded(MyImageLoadedEvent *const &event)
{
    // Causes the finished image to become visible.
    event->sharedImage.image()->endWrite();
    Qul::PlatformInterface::qul_delete(event);
}