QImage in QML

In this post I’ll show how to provide QImage from C++ code to QML

All we know, that Image {} element in QML supports only source property, which takes an URL as input. So how to put an QImage (or QPixmap or texture) to Image {}?

Answer is: QQuickImageProvider (in Qt 5)

First of all you have to create a so called image provider class, derived from QQuickImageProvider:

#include <QQuickImageProvider>

QT_BEGIN_NAMESPACE

class ImageProvider : public QQuickImageProvider
{
public:
explicit ImageProvider();
virtual QImage requestImage(const QString &id, QSize *size, const QSize& requestedSize);
};

You have to reimplement method requestImage(). It takes an string id as input as well as requested image size.
String id is an unique id, generated in your QML code. We will come there later
If Image {} element request specific image size, you’ll get the size in requestedSize parameter. Just check it is it valid or not. If so, you have to resize your original image and return resized version. Also, you have to return new image size in the size parameter

Before using your image provider, you have to register it in QML engine:

ImageProvider *imageProvider = new ImageProvider;
QQmlApplicationEngine engine(QUrl("qml/main.qml"));
engine.addImageProvider("images", imageProvider);

in this case, “images” is an identifier for your image provider
Note: if you want to register several identifiers for several providers, you have to create separate object for each identifier:

QQmlApplicationEngine engine(QUrl("qml/main.qml"));

ImageProvider *imageProvider = new ImageProvider;
engine.addImageProvider("images", imageProvider);

ImageProvider *imageProvider1 = new ImageProvider;
engine.addImageProvider("images1", imageProvider1);

 

And, finally, last step. Adding Image element to QML code:

Image {
source: "image://images/" + id
cache: false
}

 

Take a look at source property.
In that URL image means that you will use an image provider. Then, images is provider identifier and id is the string value, which will be passed to your requestImage() implementation

Its important to turn cache off if you gonna to reuse an image id

That’s it. Hope this will help to someone

Last note: with the QQuickImageProvider class you can pass not only QImage but also QPixmaps and OpenGL textures to Image element

 

Very last note: do not try to use QSharedPointer<QImage>

11 thoughts on “QImage in QML

  1. bruce

    Thanks this is nice but I think a lot of folks struggle with how to provide the “id” component needed by “source:” from C++. Does this come from a slot on the C++ side? If so, can you show a simple example? Say I’ve got: QImage img; already in C++, how then do we pass img as an id?

  2. admin Post author

    Well, you can create a property, holding an id and then pass it to QML. Look at articles, describing QML < -> C++ bindings

  3. Pingback: Trackback

  4. Pingback: TrackBack

  5. Daniel

    Can anybody tell me why any numeric value I pass as part of an ‘id’ string gets increased by 250?

    Similar to the example in the post, I add an id number to the end of my image request id. If I pass an integer 3, and convert that back to an integer in the QQuickImageProvider, I get 253. If I pass an integer of 7, I get back 257, etc. If I pass a double of 3.1415, the QQuickImageProvider tells me the id is actually 253.1415. This is on Qt 5.4.1.

  6. admin Post author

    Daniel

    id is string value, but you, it seems, operate with it as with integer
    Can you please share your code?

  7. Daniel

    I do treat it as a string. I assemble the ID as a string including certain numeric values, all parts separated by ‘%’ characters, which I later want the ImageProvider to parse again. For example “image://name/123%3.1415”. I then use
    QStringList list = id.split(‘%’);
    to separate the ID into its component parts. I then use lines such as
    int dimension = list[1].toFloat()-250;
    to retrieve the numeric values I put in the ID. I have to add the -250 to get the value I actually put in the ID.
    I convert the number I want to pass to a string and append it to the ID I pass to the ImageProvider. However, in the string that the ImageProvider actually receives, all numeric parts, still cleanly separated by the ‘%’ signs, have increased by 250.0

  8. Daniel

    Copy-paste-edit mistake; of course the dimension line would be something like
    float dimension = list[1].toFloat()-250.0;

  9. admin Post author

    Daniel

    May be it make sense to share larger piece of code

  10. Prof Rivkin

    I tried this method to no avail using Qt 5.5.1 on Linux (Ubuntu 14.04)
    I get the runtime error from QML of
    qrc:/MainForm.ui.qml:27:9: QML Image: Failed to get image from provider: image://images/0
    the ID of 0 is just fine and correct, that is not the issue.
    One odd thing I see is when debugging into requestImage() where I create on the stack a QImage named qImage, the debugger says “(invalid)”

    Any thoughts appreciated.

Leave a Reply

Your email address will not be published. Required fields are marked *