Solved Access violation in QImage from QRenderCapture
-
Hi there,
I'm trying to use QRenderCapture to get QImage that I'll use later but when I access the QImage from the QRenderCaptureReply I get read access violation.
This happens only when I try to use the binary information of the actual image (Qimage::pixel(int x, int y), QImage::bits(), QImage::save(const QString &fileName)), when I try to access the metadata of the QImage it works properly (QImage::size(), QImage::width(), QImage::isNull()).
I tried this example https://code.woboq.org/qt5/qt3d/tests/manual/rendercapture-cpp/ and got it to work until I try to access the image data and once again it gives me read access violation.
Any ideas on how to fix the problem or at least where to look for a solution? -
As a last resort, I installed a new version of Qt (I was with 6.1.2 and now I'm with 6.2.0) and now it works properly. No more crashing and read access violations.
I guess it is some kind of a bug. -
Hi,
Can you provide a minimal compilable example that shows this ?
Which version of Qt are you using ?
On which platform ? -
I am using Qt 6.1.2 on Windows 10.
-
Here is my code:
main.cpp:
#include <windows.h> #include <QtWidgets/qapplication.h> #include "My3DWindow.h" int WINAPI WinMain( _In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nShowCmd ) { int temp = 0; QApplication app(temp, &lpCmdLine); My3dWindow myWindow; myWindow.start(); return app.exec(); }
My3dWindow.h:
#pragma once #include <Qt3DCore/QEntity> #include <Qt3DExtras/qt3dwindow.h> #include <Qt3DRender/QCamera> #include <Qt3DRender/QRenderCapture> class My3dWindow : public Qt3DExtras::Qt3DWindow { Q_OBJECT public: void start(); private: void createSceneGraph(); //1 void createCamera(); //2 void createFrameGraph(); //3 Qt3DCore::QEntity* rootEntity; Qt3DRender::QCamera* cameraObject; Qt3DRender::QRenderCapture* renderCapture; Qt3DRender::QRenderCaptureReply* reply; private slots: void onImageRendered(); private: void requestRenderCapture(); };
My3dWindow.cpp:
#include "My3dWindow.h" #include <Qt3DExtras/QCuboidMesh> #include <Qt3DExtras/QDiffuseSpecularMaterial> #include <Qt3DRender/QRenderSurfaceSelector> #include <Qt3DRender/QViewport> #include <Qt3DRender/QCameraSelector> #include <Qt3DRender/QClearBuffers> #include <Qt3DExtras/QOrbitCameraController> #include <Qt3DRender/QCameraLens> void My3dWindow::start() { reply = nullptr; createSceneGraph(); createCamera(); createFrameGraph(); this->show(); requestRenderCapture(); } void My3dWindow::createSceneGraph() { rootEntity = new Qt3DCore::QEntity(); Qt3DCore::QEntity* cubeEntity = new Qt3DCore::QEntity(rootEntity); Qt3DExtras::QCuboidMesh* cuboidMesh = new Qt3DExtras::QCuboidMesh(); cubeEntity->addComponent(cuboidMesh); Qt3DExtras::QDiffuseSpecularMaterial* material = new Qt3DExtras::QDiffuseSpecularMaterial(); QColor materialColor(200, 100, 50); material->setDiffuse(materialColor); material->setAmbient(materialColor); cubeEntity->addComponent(material); this->setRootEntity(rootEntity); } void My3dWindow::createCamera() { static constexpr QVector3D cameraUpVector(0.0f, 1.0f, 0.0f); static constexpr QVector3D cameraPosition(40.0f, 40.0f, 40.0f); static constexpr QVector3D cameraViewCenter(0.0f, 0.0f, 0.0f); static constexpr float cameraLinearSpeed = 50.0f; static constexpr float cameraLookSpeed = 180.0f; cameraObject = this->camera(); cameraObject->setProjectionType(Qt3DRender::QCameraLens::PerspectiveProjection); cameraObject->setUpVector(cameraUpVector); cameraObject->setPosition(cameraPosition); cameraObject->setViewCenter(cameraViewCenter); Qt3DExtras::QOrbitCameraController* camController = new Qt3DExtras::QOrbitCameraController(rootEntity); camController->setLinearSpeed(cameraLinearSpeed); camController->setLookSpeed(cameraLookSpeed); camController->setCamera(cameraObject); camController->setEnabled(true); } void My3dWindow::createFrameGraph() { Qt3DRender::QRenderSurfaceSelector* surfaceSelector = new Qt3DRender::QRenderSurfaceSelector; surfaceSelector->setSurface(this); /*surfaceSelector*/ { Qt3DRender::QViewport* viewport = new Qt3DRender::QViewport(surfaceSelector); viewport->setNormalizedRect(QRectF(0, 0, 1.0, 1.0)); /*viewport*/ { Qt3DRender::QCameraSelector* cameraSelector = new Qt3DRender::QCameraSelector(viewport); cameraSelector->setCamera(cameraObject); /*cameraSelector*/ { Qt3DRender::QClearBuffers* clearBuffers = new Qt3DRender::QClearBuffers(cameraSelector); clearBuffers->setBuffers(Qt3DRender::QClearBuffers::ColorDepthBuffer); clearBuffers->setClearColor(QColor(50, 50, 50)); /*clearBuffers*/ { renderCapture = new Qt3DRender::QRenderCapture(clearBuffers); } } } } this->setActiveFrameGraph(surfaceSelector); } void My3dWindow::requestRenderCapture() { if (!reply) { reply = renderCapture->requestCapture(); connect(reply, &Qt3DRender::QRenderCaptureReply::completed, this, &My3dWindow::onImageRendered); } } void My3dWindow::onImageRendered() { QImage* qimage = new QImage(reply->image()); qDebug() << "Image size in bytes:" << qimage->sizeInBytes(); qDebug() << "Width:" << qimage->width() << "Height:" << qimage->height(); QColor rgb = qimage->pixel(QPoint(0, 0)); qDebug() << "Color: " << " " << rgb.red() << " " << rgb.green() << " " << rgb.blue(); reply->deleteLater(); reply = nullptr; requestRenderCapture(); }
It stops as soon as it hits the "QColor rgb = qimage->pixel(QPoint(0, 0));" line, and it gives me the read access violation
-
@Argostin said in Access violation in QImage from QRenderCapture:
QImage* qimage = new QImage(reply->image());
Here you are creating an image on every function call.
@Argostin said in Access violation in QImage from QRenderCapture:
reply->deleteLater();
reply = nullptr;You create an image that does not copy the data, it stores the pointer to the data and finally you are deleting it.
-
Hi @ollarch
I don't think this is part of the main problem, because the program stops on the first iteration so the code:reply->deleteLater(); reply = nullptr;
isn't even executed.
But still, how do you suggest I should rework it?
-
Hi,
If the image have to be used after deleting the reply you need to copy it.
Have you checked the call stack on debugger just when it crash?
-
Here is the call stack:
Also, "RenderCapture" is the name of the project -
@Argostin
Prior to yourqimage->pixel()
what happens if you goqimage->copy()
? Does that violate too?Since
QPoint(0, 0)
is a nullQPoint
, humour me by trying some coordinates other than that? -
@JonB
Yes, qimage->copy() does violate in the same way and I've tried several different points but none of them worked.
Still, thanks for the suggestions. -
As a last resort, I installed a new version of Qt (I was with 6.1.2 and now I'm with 6.2.0) and now it works properly. No more crashing and read access violations.
I guess it is some kind of a bug. -
@Argostin LOL, well done!
-
@Argostin Good job!