skadge
skadge

Reputation: 131

Back and forth between QML Canvas and C++

I am trying to implement a 'bucket fill' tool for a QML Canvas, using a flood fill algorithm. My initial implementation in pure QML/Javascript works well but is (expectedly) slow, and essentially unusable on mobile devices.

I would like instead to implement it in C++. Unfortunately, sharing the QML canvas content with C++ is not simple/not supported/not documented.

My current approach is convoluted, and certainly not efficient: I first serialize the canvas content using canvas.dataToUrl("image/bmp"), I pass the base64 encoded image to a C++ QML plugin that performs the fill:

void FloodFill::setImageData(const QString &data)
{
    QByteArray base64Data = data.mid(22).toUtf8();

    QImage image;
    image.loadFromData(QByteArray::fromBase64(base64Data), "BMP");

    fill(image);

    emit onCanvasFilled();
}

Then, at the next QML canvas repaint, I access the C++ QImage by re-encoding it in base64 on the C++ side, and then using the base64 string as an image source in QML.

In summary: canvas -> base64 encoding via toUrlData -> C++ -> decode into QImage -> flood fill -> re-encode into base64 string -> decode as QML image -> paint the QML image over the canvas.

This is clearly highly inefficient.

Ideally, I would like to access the memory address of the canvas' CanvasImageData from C++ to edit directly the pixels, without any copy.

The next best option would be to copy both ways a CanvasImageData (but the C++ type for CanvasImageData is unfortunately private).

Any other suggestions?

(I want to add that I've looked as well at the QImageProvider interface, but I do not see how I can make it work in this situation, as the image provider would have to be instanciated inside my QML plugin, and I do not see how I could then register the image provider with the QML engine).

Upvotes: 2

Views: 416

Answers (1)

skadge
skadge

Reputation: 131

@folibis suggestion of using a QQuickPaintedItem is the path I eventually took, and effectively solve my problem -- it is however unfortunate to have to essentially abandon the QML canvas object along the way.

Upvotes: 0

Related Questions