Saturday, July 4, 2009

Qt-Embedded: Capturing screen with QPixmap

I've been working on a product manual lately. I needed to include several LCD screenshots into it so I tried to come up with an easy way to capture snapshots from our Qt/Embedded app.
Qt/Embedded provides a nice method to save window/framebuffer contents directly to an image file. However, I wanted to send the 'take-snapshot' command from a tty console (telnet/serial/etc) since there weren't any other buttons on the system to trigger that.
A QTimer is set up. Periodically it checks the file /tmp/doCapture. If it exists a snapshot is taken and an image file is saved. Its filename is taken from the contents of /tmp/doCapture. After saving the image /tmp/doCapture is deleted.
Here is the code, which should be placed in the main window, whose width and height cover the whole screen:


mainWindow::mainWindow()
{
// captureTimer should be declared in mainWindow's class definition
captureTimer = new QTimer(this);
connect( captureTimer, SIGNAL(timeout()), this, SLOT(captureTimerEvent()) );

captureTimer->start(1000); //check interval
}

void mainWindow::captureTimerEvent()
{
QString tmpFile = QString("/tmp/doCapture");

if ( !QFile::exists(tmpFile) )
return;

QFile f(tmpFile);
if ( !f.open( QIODevice::ReadWrite ) )
return;

char buf[200];
if ( f.readLine( buf, sizeof(buf) - 4 ) == -1 )
return;

buf[strlen(buf)-1] = '\0'; //remove \n created by 'echo'-- not safe!

strcat( buf, ".png" );

//capture
QPixmap p = QPixmap::grabWindow( this->winId() );

if ( p.save( buf ) )
printf("------- GRAB OK\n");
else
printf("------- ERR GRAB!\n");

/* delete file */
f.remove();
}


This way, all I have to do to take a snapshot is to write:

echo pngfilename > /tmp/doCapture