Reputation: 131
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
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