PDA

View Full Version : How to draw image from shared memory in QGraphicsView?



emmenlau
5th January 2019, 13:23
I have an application that renders many hundreds large images as QGraphicsItems in a QGraphicsView. Currently this works ok, but I'm concerned about the memory required by Qt to store the internal representation of the QGraphicsItems. I need to hold one pointer to the image in memory myself so I can perform analyses and transformations on the image. And I understand that Qt stores a second copy of the image as a QPixmap with the QGraphicsItems, is that correct?

How could I avoid this second copy? I'm willing to patch Qt or use a different rendering if that helps. I.e. I was wondering if I could instead draw OpenGL textures, and if these textures could share memory with a QImage? Did somebody try this, or does someone know how to render OpenGL textures that reference QImage memory (using shallow copy as described here: http://doc.qt.io/qt-5/implicit-sharing.html)?

Thanks for hints!

anda_skoa
5th January 2019, 14:14
Conversion from QImage to QPixmap might involve data duplication.

Essentially it depends first on the how the plugin for the current platform adapter treats QPixmaps vs QImage.
Secondly it depends on whether the format of the image is the different to the format required for the pixmap.

In the ideal case a QPixmap shared the same internal buffer as the QImage it has been created from (Qt Raster paint engine based backends, image format equal).


Having said that one thing that you could consider in any case is to create a QImage based GraphicsView item.
I.e. creating your own equivalent to QGraphicsPixmapItem but either storing a QImage per item or referencing the image in your internal "image storage".

Aside from giving you more control over image data copy and conversion, it would also allow you to make use of drawing time information such as "level of detail".

Cheers,
_

emmenlau
6th January 2019, 10:34
Thanks a lot for your help! What you say makes perfect sense, but two questions:


Do you know if there is a way to find out if QPixmap uses duplicate memory? Something like QPixmap::isShallow()?
If I use QImage as the memory format, how do I draw it? QPainter only draws QImage by converting it to QPixmap internally, which is slower and still wastes the memory. Is there a direct drawing method that uses the QImage memory buffer?

anda_skoa
7th January 2019, 18:12
Do you know if there is a way to find out if QPixmap uses duplicate memory? Something like QPixmap::isShallow()?

Not easily, no.

If you want to test for a single image just to check if your format/platform causes conversion, it might be possible to do QImage -> QPixmap -> QImage and compare the "bits()" pointer of the two images.

In any case you might want to check your application with a memory profiler such as Heaptrack (https://www.kdab.com/heaptrack-v1-0-0-release/).
E.g. measuring without creating pixmap items and then again with. Duplication of memory usage should be pretty obvious.



If I use QImage as the memory format, how do I draw it? QPainter only draws QImage by converting it to QPixmap internally, which is slower and still wastes the memory.

QPainter::drawImage() does not necessarily convert to QPixmap.

There are many fast paths that result in memory-copy/bit-blit operations

Cheers,
_