QImage copy on write - qt

is QImage based on QSharedData ? Do Qimage follow pimpl or copy on write ?
e.g. would copying(through copy con or assignment) an Qimage make a deep copy of pixels ?

QImage is copy on write. It will not copy pixels until you start modifying it.
For what it's worth when passing it into functions, I always use const QImage & anyway not to freak anyone out.

Related

OpenGL / QT : Need help in Converting from QImage to Opengl format and render the pixels

We are migrating from Old OpenGl to Modern OpenGL. I am trying to port two functions which uses QT/OpenGL and want to convert to Modern OpenGL. QImage content should be converted to OpenGL Format. Then I want to read the pixels of QImage and render in OpenGL. How to do this in Modern OpenGL. I know glcopypixels() / glDrawPixels() is deprecated. Any pointers? I have the following code but it is in old OpenGL. Basically the whole idea is writing to back buffer and restoring the back buffer and render pixels to avoid redraw. I am using QOpenglWidget Class given by QT Framework (QT 5.1). I have tried many things converting to OpenGL format from QImage. But it did not work. Need your help. Thanks in Advance.
QImage _savedBackBuffer;
void SaveBackBuffer()
{
glReadBuffer(GL_BACK);
QImage buf = this->grabFramebuffer();
_savedBackBuffer = convertToGLFormat(buf); // convertToGLFormat is not available in
QOpenGLWidget class
}
void restoreBackBuffer()
{
glDrawBuffer(GL_BACK);
**glDrawPixels**( _savedBackBuffer.width(), _savedBackBuffer.height(),
GL_RGBA, GL_UNSIGNED_BYTE, _savedBackBuffer.bits() ); ---> glDrawPixels is Deprecated. How to handle this call.
}
flush () {
glReadBuffer (GL_BACK);
glDrawBuffer(GL_FRONT);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
**glCopyPixels**(0, 0, _scrWidth, _scrHeight, GL_COLOR); // glCopyPixels Deprecated
...
glflush();
}
I have added below code to grab the Framebuffer. But still I am getting an Empty QImage. Anything wrong with my code.
saveBackBuffer()
{
_bSavingBackBuffer = true;
QString fileName("C:\\Users\\ey617e\\Desktop\\yourFile.png");
QFile file(fileName);
file.open(QIODevice::WriteOnly);
glReadBuffer(GL_BACK);
makeCurrent();
QOpenGLFramebufferObjectFormat format;
format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
QOpenGLFramebufferObject * fbo = new
QOpenGLFramebufferObject(_scrWidth, _scrHeight, format);
fbo->bind();
paintGL();
_savedBackBuffer = fbo->toImage();
_savedBackBuffer.save(file.fileName(), "PNG");
fbo->release();
}
paintGL()
{
QOpenGLPaintDevice fboPaintDev(_scrWidth, _scrHeight);
QPainter painter(&fboPaintDev);
painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
painter.beginNativePainting();
drawDisplayLists(_underIllusDisplayLists);
drawDisplayLists(_illusDisplayLists);
painter.endNativePainting();
painter.drawText(20, 40, "Foo");
painter.end();
}
You can create a QOpenGLTexture object directly from a QImage: https://doc.qt.io/qt-5/qopengltexture.html#QOpenGLTexture-1
You can then use that texture directly for any image related OpenGL operations.
Basically the whole idea is writing to back buffer and restoring the back buffer and render pixels to avoid redraw.
Don't do that! It will actually impair performance, since drawing on top of previously rendered content introduces implicit synchronization points, thereby eliminating options to render new contents in parallel to advancing the presentation swap chain.
As "counterintuitive" as it may sound, just redraw the whole thing, each and every frame. If your codebase is that old, then the complexity of what you're drawing very likely is going to be so low, that you could easily render thousands of frames per second.
On the other hand retaining the contents of the backbuffer constitutes a cache and thus introduces the complexity of deciding upon cache invalidation.
I bet, that just redrawing using modern methods (geometry in buffer objects, index buffers, untangling of sync points) and simplifying the rendering code path by mere elimination the code that's responsible for determining when to actually redraw portions of the picture will actually vastly outperform anything what you had before.

Display image using QImage without using pixmap in Qt?

I have a requirement to read pixel values from the picture displayed on the GraphicScene layout. How can I display image using QImage without using pixmap in Qt so that I am able to read the pixel values?
On most platforms, a QPixmap is a thin wrapper around a QImage. The conversions between the two are cheap - especially the pixmap-to-image conversion. Thus, you can use the QGraphicsPixmapItem and use item->pixmap().toImage() without much worry. To confirm that QPixmap is indeed a wrapper, the following check will do:
bool isPixmapThin(const QPixmap &pix) {
auto const a = pix.toImage();
auto const b = pix.toImage();
return a.bits() == b.bits();
}
In all cases, ensure that the image you take from the pixmap won't detach, i.e. always make it const (as in the code example above).

Qt: How to clean up a QImage from memory

How to clear or clean up a QIMage
Following method of mine get a const reference to a QIMage.
MyMethod(const QImage & img) {
// save it to a file
img.save("/path/to/save/the/qimage");
// now I want to clan up img from memory. How should I do it?
}
Question:
How should I clean up the QImage object from memory after use?
Note:
Note that it is a const & QImage. So, answer would involve casting the QImage into non-const?
Also, I am looking at trying to get a QImageData pointer to the data & delete it. Not sure if that is the correct approach here. Do suggest.
You need a non-const reference or a pointer. With a pointer the answer is obvious. With a reference you just assign a default-constructed QImage to it.
MyMethod(QImage & img) {
img.save("/path/to/save/the/qimage");
img = QImage();
}
However, this may still not clean up the memory occupied by the image, if there are additional QImage instances referencing that same image. To overcome this hurdle you need to avoid multiple QImage instances referencing the same image. A Qimage instance is like a shared pointer in this regard.
A const-cast would be considered to reveal a design flaw in your case. I'd recommend against it.

QXmlStreamWriter crashes when I try to write too many items

I am using QXmlStreamWriter to create an xml file with many items. At one point because there are too many elements probably I experience a crash.
Is there a way to perform a flush on the stream?
How else can I perform the writing so I do not experience a crash?
Found out that QByteArray doesn't support more than 2GB. That's why i had a crash. I used QXmlStreamWriter together with a QByteArray.
If I provide the file directly it works fine.
previous code:
QByteArray buffer;
QXmlStreamWriter stream(&buffer);
current code:
QFile* destFile
QXmlStreamWriter stream(destFile);

How to work with QGraphicsScene::addPixmap when it only accepts const QPixmap?

I'd like to display some QImage through QGraphicsScene, my code's very straightforward:
mainwindow.h
QImage *sourceImage;
QGraphicsView *imageView;
QGraphicsScene *imageScene;
mainwindow.cpp
imageScene = new QGraphicsScene;
imageView = new QGraphicsView;
imageView->setScene(imageScene);
sourceImage = new QImage;
sourceImage.load(":/targetimage.png");
imageScene.addPixmap(QPixmap::fromImage(sourceImage));
And then the complier points out exactly what I did wrong: QGraphicsScene::addPixmap accepts only const QPixmap as argument, and I was trying to convert QImage to const QPixmap, which is not allowed because QPixmap::fromImage within only accept const QImage, like a const hell.
The official documentation on this method doesn't make much sense to me either, if I'd like to make for example, an image viewer, and during runtime I'd sure load different images into QImage sourceImage, and how can I accomplish that using a const QImage?
This problem has been agonizing, thanks for any advice. Moreover could you light me a bit if there's any vision on the philosophical reason why guys in Qt make these methods const?
Try
imageScene.addPixmap(QPixmap::fromImage(*sourceImage));
Some advice:
there is no need to allocate the QImage on the heap (using new).
Use:
QImage sourceImage;
Then you do not need to dereference the pointer when calling QPixmap::fromImage
Just to clarify: the constness has nothing to do with the error.

Resources