Integrating with an external graphical package
-
I'm using the GraphicsMagick package (fork of ImageMagick) to handle my images, because of its greater range of supported image formats and operations. I'm looking for a way to integrate these images with Qt.
At the moment, to display such images in a QWidget I do by drawing on its native window handle, which I get using winId(). The image at this point has been loaded into memory by GraphicsMagick.
When stepping through the paint event, I first see my image (and only my image) displayed on the screen. Qt painted objects are not being displayed at all. When the paint event is finished, this is replaced on the screen by the display of the Qt objects I painted, but without my image.
I believe that I have run into a problem with the Qt double-buffering mechanism, so that I'm drawing on the screen buffer, while Qt draw-commands paint in the memory buffer, so my image is erased when the screen buffer is replaced by the memory buffer.
The brute-force method would be to save the image data in memory in some standard format such as pixel-data, then load this into a QPixmap. This will require wastefully keeping three copies of the image in memory and much extra processing.
Can I somehow draw directly on the memory buffer?
How can I mix external images with Qt widgets?I'm on Windows, but looking for a portable solution.
-
-
@kshegunov How can disabling automatic background help with the problem of painting a non-Qt image to the back/memory buffer?
I have since discovered a Windows-only possible solution in QtWin::fromHBITMAP() that returns a QPixmap.
But this will be my last solution, as I don't have any idea about how to port it later on to Linux, nor about its performance. -
@Harry123
The docs say:
"In addition, Windows are always filled with QPalette::Window, unless the WA_OpaquePaintEvent or WA_NoSystemBackground attributes are set."
So I gather it should help? -
@kshegunov I will try it tomorrow, but I don't have much hope of its helping, as any painting I do is on the wrong buffer. I don't think that these settings will disable double-buffering.
In desperation I have risked flickering by trying to set Qt::WA_PaintOnScreen, but this only caused multiple errors from QPainter, so I suppose it doesn't really work any more (or at least not on Windows).
-
Drawing using OS native commands will likely be a problem, it will not be portable, and could be an upgrade nightmare if there are changes in Qt.
I don't know GraphicsMagick and I never heard of it. Likely this can produce an in memory image that you could import into QPixmap (or QImage) and then you could draw this without having to touch the native API drawing commands.
QPixmap::loadFromData(...); http://doc.qt.io/qt-5/qpixmap.html#loadFromData
QImage::loadFromData(...); http://doc.qt.io/qt-4.8/qimage.html#loadFromData-2 -
@Rondog
GraphicsMagick is a more efficient fork of ImageMagick. If you know ImageMagick, both APIs are highly compatible.I'm looking for some more efficient solution than QPixmap::loadFromData, since as mentioned in the post, it will entail :
- Loading the image via GraphicsMagick
- Creating a memory area and storing the data pixels in it
- loadFromData to create a QPixmap
This means at least three memory-copies of the image in various formats (if not more, depending on the implementation of QPixmap and GraphicsMagick). For an image of hundreds of megabytes, performance will be poor.
It's a pity that Qt has no portable mechanism for integrating with other graphical packages than its own, or at least with the most prominent one which is ImageMagick/GraphicsMagick. I have changed the title of the post accordingly.
-
It's a pity that Qt has no portable mechanism for integrating with other graphical packages than its own, or at least with the most prominent one which is ImageMagick/GraphicsMagick. I have changed the title of the post accordingly.
Well, QImage can be attached to an existing buffer without copying it, so if you can create a shared buffer between the magic(k) you're using and a
QImage
object, then you should be good to go. -
Thanks for the tip - this looks like the best solution so far.
GraphicsMagick can expose the pixels cache of an image, so this will economize on memory copies, and is in addition a portable solution.