How to create and use an image provider, more exactly a QQuickAsyncImageProvider.

Full example can be found at https://github.com/g-fb/qml-custom-image-provider.

Create the provider class

customimageprovider.h

#ifndef CUSTOMIMAGEPROVIDER_H
#define CUSTOMIMAGEPROVIDER_H

#include <QQuickAsyncImageProvider>

class CustomImageProvider : public QQuickAsyncImageProvider
{
public:
    explicit CustomImageProvider();
    QQuickImageResponse *requestImageResponse(const QString &id, const QSize &requestedSize) override;
};

class CustomImageResponse : public QQuickImageResponse
{
public:
    CustomImageResponse(const QString &id, const QSize &requestedSize);

    QQuickTextureFactory *textureFactory() const override;

private:
    QImage m_image;
};

#endif // CUSTOMIMAGEPROVIDER_H

customimageprovider.cpp

#include "customimageprovider.h"

#include <QTransform>

CustomImageProvider::CustomImageProvider()
    : QQuickAsyncImageProvider()
{

}

QQuickImageResponse *CustomImageProvider::requestImageResponse(const QString &id, const QSize &requestedSize)
{
    auto response = new CustomImageResponse(id, requestedSize);
    return response;
}

CustomImageResponse::CustomImageResponse(const QString &id, const QSize &requestedSize)
{
    QImage image{id};
    QImage scaled = image.scaled(requestedSize);
    QImage rotated = scaled.transformed(QTransform().rotate(180.0));
    m_image = rotated;

    Q_EMIT finished();
}

QQuickTextureFactory *CustomImageResponse::textureFactory() const
{
    return QQuickTextureFactory::textureFactoryForImage(m_image);
}

The important part is in the constructor of CustomImageResponse. There we create a QImage from the id, scale it to requestedSize, rotate the scaled image, assign the rotated image to m_image variable and emit the finished() signal.

⚠️ The id and requestedSize come from an Image component in qml.

Add the files to cmake

qt_add_qml_module(appexample_image_provider
    URI example_image_provider
    VERSION 1.0
    QML_FILES
        Main.qml
    SOURCES customimageprovider.h customimageprovider.cpp # <--
)

Add the provider to the QQmlApplicationEngine

main.cpp

#include "customimageprovider.h"
...
QQmlApplicationEngine engine;
engine.addImageProvider(QStringLiteral("provider_name"), new CustomImageProvider());
...

Use the provider

Main.qml


Window {
    ...
    Image {
        anchors.centerIn: parent
        source: "image://provider_name//path/to/image.jpg"
        width: 300
        height: 500
        sourceSize.width: 200
        sourceSize.height: 300
    }
}

The source is composed of multiple parts

  • image:// - the url scheme, tells the Image to use an image provider
  • provider_name - the name set when adding the provider to the QQmlApplicationEngine
  • / - separator between provider name and the id
  • /path/to/image.jpeg - the id passed to the image provider

The sourceSize is the size passed to the image provider (requestedSize).

In this example the id passed to the image provider is a local path, but it can be anything, for example it could be the id of a database record where images are stored as blobs.