PDA

View Full Version : Save Image of QGLWidget to file



ToddAtWSU
2nd March 2010, 01:21
I am trying to save the contents of a custom QGLWidget to a file and am not having any luck. I am running on Solaris 10 and in 8-bit color due to legacy software on the system. I am currently using Qt 4.5.1. My QGLWidget subclass is called Plot and my class member is mpPlot. Here is my code in MainWindow which is a subclass of QMainWindow.


void MainWindow::save( )
{
QString filename = QFileDialog::getSaveFileName( this, "Save File", getenv( "HOME" ), "JPEG Image (*.jpg *.jpeg) );
if( !filename.endsWith( ".jpg" ) && !filename.endsWith( ".jpeg" ) )
{
filename.append( ".jpg" );
}

//QImage image = mpPlot->grabFrameBuffer( );
//QPixmap image = mpPlot->renderPixmap( );
QPixmap image = QPixmap::grabWidget( mpPlot );
if( !image.save( filename, "JPG" ) )
{
QMessageBox::warning( this, "Save Image", "Error saving image." );
}
}

As you can see in my code, I have tried three different methods of saving, and all three produce the QMessageBox. I have tried JPG, JPEG, and PNG but none of these work. Any idea why this won't work. We use similar code on another application in Windows XP running the same version of Qt. Thanks for your help!

chaoticbob
2nd March 2010, 05:06
...for renderPixmap - did you specify a w/h? I believe it default to 0, 0 otherwise.

ToddAtWSU
2nd March 2010, 14:11
...for renderPixmap - did you specify a w/h? I believe it default to 0, 0 otherwise.

You are correct that it defaults to 0,0, but this is what I want. According to the docs for QGLWidget::renderPixmap it defaults to 0,0 which creates a QPixmap of the same size as the widget. I want the image to be the same size as the widget so I use the default values of 0,0. Any other ideas?

Thanks!

ToddAtWSU
2nd March 2010, 17:35
I have added the line
glReadBuffer( GL_COLOR_BUFFER_BIT ); to the code before creating the QImage or QPixmap. After the creation I have added a qDebug statement to print out the value of isNull( ) on the image object. The results from grabFrameBuffer( ) and grabWidget( ) return true for isNull. The return object for renderPixmap however returns false for isNull( ) which is great. I print out its width and height as well as the QGLWidget's width and height, and they match identically. But the save( filename ) function still returns false and does not work. I have tried it with the "JPG" and "JPEG" strings for the 2nd argument or tried it without the 2nd argument and it always fails. I have tried running this in 24-bit color thinking the colormap was the issue, but this fails as well. Any ideas? Thanks again!

norobro
2nd March 2010, 19:25
Interesting problem. This might be a wild goose chase but ....
From QPixMap.cpp:
bool QPixmap::save(const QString &fileName, const char *format, int quality) const
{
if (isNull())
return false; // nothing to save
QImageWriter writer(fileName, format);
return doImageIO(&writer, quality);
}

bool QPixmap::doImageIO(QImageWriter *writer, int quality) const
{
if (quality > 100 || quality < -1)
qWarning("QPixmap::save: quality out of range [-1,100]");
if (quality >= 0)
writer->setQuality(qMin(quality,100));
return writer->write(toImage());
}
And from the QImageWriter docs:
If any error occurs when writing the image, write() will return false. You can then call error() to find the type of error that occurred, or errorString() to get a human readable description of what went wrong.So maybe the following would give you a clue:
QImageWriter writer(fileName, "JPG");
writer.write(toImage());
qDebug()<< writer.errorString();

ToddAtWSU
3rd March 2010, 17:36
I solved my problem. I am statically linking Qt into my projects so when we deliver them to the customer we don't have to worry about including all the dynamic libraries. So in my .h file after #include <QtGui> I needed to include Q_IMPORT_PLUGIN<qjpeg> or any other image libraries I need so that the compiler knows to grab the plugin libraries. Once I added this it works fine. Thanks for your suggestion though, that seems like a great idea to try out if I have issues again with images.