PDA

View Full Version : QImage and threads



Persoontje
5th September 2009, 20:30
Hi,

I'm working on a raytracer. As that's a very cpu-heavy process, I'd like to run the raytracer itself in a seperate thread. Is it possible to write from the thread directly to a QImage (which is displayed in the gui), so you can see the picture being created? Or isn't that safe and do I have to pass the new pixel data via signals/slots to the gui thread?

And how do I display the QImage? With a QLabel (or is that only for QPixmap)

Thanks in advance for helping out a newbie =)

wysota
5th September 2009, 21:14
You can write to an image in a separate thread but you can't show it on the screen because it has to be converted to a pixmap first. But you can do calculations in the worker thead and every time a scanline is complete you can send it to the main thread (using signals and slots), assemble the image, convert it to pixmap and display on the screen (or better yet hold each scanline as a separate pixmap to avoid needless conversions from image to pixmap).

Persoontje
14th September 2009, 10:04
Thanks for your answer, sorry for my late reply :S

So I write in my worker thread each scanline to a qpixmap (size for instace 1024x1 pixel), then I send the qpixmap using a slot to the gui thread, which adds the qpixmap to the whole image?

And with what method of QPixmap can I add an other pixmap to the image. Or do I just have to use fill for every pixel?

Persoontje
14th September 2009, 16:48
I've written a little test application for it. The worker thread emits a signal with a QImage containing a row of the image. This signal is connected to this slot:



void DisplayImage::newData(int row, QImage newData)
{
int y = pixmap->height() - 1 - row; //if height is 400, y is in 0-399
//In the raytracer 0,0 is the bottomleft of the screen, not the topleft
painter.drawImage(0, y, newData);
displayLabel.setPixmap(*pixmap);
}


Is this the fastest way to do it, or can I optimize this?

Persoontje
17th September 2009, 16:16
I did some other test, and this works correctly, but it has a huge impact on the speed. When create a picture without setting the new QPixmap to the label, it renders much faster.



//displayLabel->setPixmap(displayPixmap);


(with this line commented out)

Does anybody know if there is a faster way to display the QPixmap or how to optimize this ?

wysota
17th September 2009, 17:09
Don't use a label. Use a custom widget and store each scanline as a separate pixmap as I suggested earlier.

Persoontje
17th September 2009, 18:00
Don't use a label. Use a custom widget and store each scanline as a separate pixmap as I suggested earlier.

Thanks for your answer. So I create a new Widget class, reimplement paintEvent and let the painter paint my scanlines on the widget?

wysota
17th September 2009, 20:13
Yes. And only paint those scanlines that need painting (observe the rectangle you get in the paint event).