rickbsgu
2011-02-28 14:40:04 UTC
Hi, all -
Need to save a scene to an image file. I'm presuming a couple of things:
* The way to do this is with a QGLPixelBufferSurface
* QGLView sets up a QGLWidgetSurface somewhere, and that surface can be
switched.
* within the paintGL func, I can push a QGLPixelBufferSurface onto the
QGLPainter, draw to that, and then pop it off to resume normal widget rendering.
So, here's what I've done (in my QGLView-derived class):
1. create a member QGLPixelBufferSurface and set a QGLPixelBuffer in that (on
request to save.)
2. set a flag so that the next render will know we're to render to a pixel
buffer
3. call 'update()' to force a re-render.
4. In the 'paint' function, I call 'pushSurface' on the QGLPainter to push the
QGLPixelBufferSurface onto the painter, draw, and then pop the
QGLPixelBufferSurface back off.
5. after rendering, a signal is called to notify the caller that the rendering
is done - that slot extracts the image from the member QGLPixelBufferSurface,
saves it, and cleans up.
It crashes with a 'bad memory access' when the QGLPainter is trying to draw the
glElements in qglindexbuffer (trying to draw the QGLSceneNode).
I suspect that some aspect of my initial presumptions are incorrect.
Here are the code snippets.
Any thoughts appreciated.
(slot that receives 'save' request)
-----------------------------------------
void ModelView::saveToImage()
{
savePath = QFileDialog::getSaveFileName(parentWidget(), "Save Image as...",
".", "PNG (*.png)");
if (!savePath.isEmpty())
{
drawToBuffer = true;
bSurface = new QGLPixelBufferSurface();
bSurface->setPixelBuffer(new QGLPixelBuffer(QSize(250, 250)));
connect(this, SIGNAL(drawToPBufDone()), this, SLOT(onDrawToPBufDone()),
Qt::QueuedConnection);
this->update();
}
}
(slot called after the draw is done)
------------------------------------
void ModelView::onDrawToPBufDone()
{
drawToBuffer = false;
disconnect(this, SIGNAL(drawToPBufDone()), this, SLOT(onDrawToPBufDone()));
QImage img = bSurface->pixelBuffer()->toImage();
delete bSurface;
img.save(savePath, "PNG");
QMessageBox::information(parentWidget(), "Information", "Image saved...");
}
(paint routine)
----------------
<...>
if (drawToBuffer)
painter->pushSurface(bSurface);
<... draw stuff ...>
if (drawToBuffer)
{
painter->popSurface();
emit drawToPBufDone();
}
________________________________
A mind is not a vessel to be filled,
it is a fire to be ignited.
-- Plutarch
Need to save a scene to an image file. I'm presuming a couple of things:
* The way to do this is with a QGLPixelBufferSurface
* QGLView sets up a QGLWidgetSurface somewhere, and that surface can be
switched.
* within the paintGL func, I can push a QGLPixelBufferSurface onto the
QGLPainter, draw to that, and then pop it off to resume normal widget rendering.
So, here's what I've done (in my QGLView-derived class):
1. create a member QGLPixelBufferSurface and set a QGLPixelBuffer in that (on
request to save.)
2. set a flag so that the next render will know we're to render to a pixel
buffer
3. call 'update()' to force a re-render.
4. In the 'paint' function, I call 'pushSurface' on the QGLPainter to push the
QGLPixelBufferSurface onto the painter, draw, and then pop the
QGLPixelBufferSurface back off.
5. after rendering, a signal is called to notify the caller that the rendering
is done - that slot extracts the image from the member QGLPixelBufferSurface,
saves it, and cleans up.
It crashes with a 'bad memory access' when the QGLPainter is trying to draw the
glElements in qglindexbuffer (trying to draw the QGLSceneNode).
I suspect that some aspect of my initial presumptions are incorrect.
Here are the code snippets.
Any thoughts appreciated.
(slot that receives 'save' request)
-----------------------------------------
void ModelView::saveToImage()
{
savePath = QFileDialog::getSaveFileName(parentWidget(), "Save Image as...",
".", "PNG (*.png)");
if (!savePath.isEmpty())
{
drawToBuffer = true;
bSurface = new QGLPixelBufferSurface();
bSurface->setPixelBuffer(new QGLPixelBuffer(QSize(250, 250)));
connect(this, SIGNAL(drawToPBufDone()), this, SLOT(onDrawToPBufDone()),
Qt::QueuedConnection);
this->update();
}
}
(slot called after the draw is done)
------------------------------------
void ModelView::onDrawToPBufDone()
{
drawToBuffer = false;
disconnect(this, SIGNAL(drawToPBufDone()), this, SLOT(onDrawToPBufDone()));
QImage img = bSurface->pixelBuffer()->toImage();
delete bSurface;
img.save(savePath, "PNG");
QMessageBox::information(parentWidget(), "Information", "Image saved...");
}
(paint routine)
----------------
<...>
if (drawToBuffer)
painter->pushSurface(bSurface);
<... draw stuff ...>
if (drawToBuffer)
{
painter->popSurface();
emit drawToPBufDone();
}
________________________________
A mind is not a vessel to be filled,
it is a fire to be ignited.
-- Plutarch