Trolltech Home | Qt-interest Home | Recent Threads | All Threads | Author | Date
All threads index page 3

Qt-interest Archive, September 2007
Image painting speed issues

Pages: Prev | 1 | 2 | Next

Message 1 in thread

I've got a program where I need to receive images (in TIFF format) over
a network socket and display them in my client.  The images are 512x512
and either 1 or 4 bytes per pixel depending on some other settings.  The
client/server setup is such that the server will send me images as fast
as I can accept them.

Right now I'm receiving the image on the socket, reading that into a
QByteArray, calling QPixmap::loadFromData(const QByteArray&) to get it
into a QPixmap, and then displaying it on a QLabel via
QLabel::setPixmap(const QPixmap&).  I've instrumented my application to
display the frame rate I'm getting and with this method I get about 6
Hz, which is too slow.  

I then modified my application so that with a checkbox on the GUI, I can
choose whether to display the images on my GUI, or just have my
application receive the images from the server, but not display them.
If I set it so I'm not displaying the images I receive the frames at
around 35 Hz.  If I set the checkbox back so that I'm displaying the
images, the frame rate drops back to 6 Hz.  So it appears the image
painting steps are taking up too much time and my client isn't able to
keep up with the server.

What can I do to speed this up?  I've tried searching on the list and
found some hints about QImage vs. QPixmap, as well as possibly using
OpenGL and painting my image as a texture.  The OpenGL hint looked
promising but assumed the developer knew how to do that, unfortunately
I'm completely OpenGl clueless at the moment. 

Using Qt 4.3 on both Windows and Linux.

Sean

--
 [ signature omitted ] 

Message 2 in thread

On 9/12/07, Murphy, Sean M. <sean.murphy@xxxxxxxxxx> wrote:
> I've got a program where I need to receive images (in TIFF format) over
> a network socket and display them in my client.  The images are 512x512
> and either 1 or 4 bytes per pixel depending on some other settings.  The
> client/server setup is such that the server will send me images as fast
> as I can accept them.
>
> Right now I'm receiving the image on the socket, reading that into a
> QByteArray, calling QPixmap::loadFromData(const QByteArray&) to get it
> into a QPixmap, and then displaying it on a QLabel via
> QLabel::setPixmap(const QPixmap&).  I've instrumented my application to
> display the frame rate I'm getting and with this method I get about 6
> Hz, which is too slow.
>
> I then modified my application so that with a checkbox on the GUI, I can
> choose whether to display the images on my GUI, or just have my
> application receive the images from the server, but not display them.
> If I set it so I'm not displaying the images I receive the frames at
> around 35 Hz.  If I set the checkbox back so that I'm displaying the
> images, the frame rate drops back to 6 Hz.  So it appears the image
> painting steps are taking up too much time and my client isn't able to
> keep up with the server.
>
> What can I do to speed this up?  I've tried searching on the list and
> found some hints about QImage vs. QPixmap, as well as possibly using
> OpenGL and painting my image as a texture.  The OpenGL hint looked
> promising but assumed the developer knew how to do that, unfortunately
> I'm completely OpenGl clueless at the moment.

Generally speaking, Qt should be able to handle that requirement
(512x512 @ 30FPS) on modern computers pretty easily. As I've posted a
few times before, I worked on an app that displayed 640x640 images (1
byte per pixel) at 40FPS using a simple QPainter::drawImage(QImage*)
call in a widget paintEvent(). This is with Qt 4 on Windows on a
pretty low-end system, graphics-wise (onboard Intel graphics, no fancy
acceleration). Drawing a QPixmap shouldn't be any slower, since the
main difference between that and QImage is that QPixmap is stored in a
platform native format.

For your situation, the first thing I'd try is replacing your QLabel /
setLabel() method with a subclassed QWidget and implement a
paintEvent() method that draws your QPixmap.

One guess as to the underlying problem is copy-on-write - not that
it's defective, but that you've created a situation where it's doing
unneeded work. If you're currently doing something like the following
pseudocode:

void showNetworkPictures()
{
    QPixmap picture(512,512);
    QLabel label;
    label.show();

    while (picture.loadFromData(/*network socket*/))
    {
       label.setPixmap(picture);
    }
}

Then I believe subsequent QPixmap::loadFromData() calls would cause
the label's instance of the QPixmap to become a copy instead of
sharing the original data (so that the QLabel can still access the
original pixmap data that was passed by value). This work is of course
wasted in this situation because as soon as the new pixmap is
obtained, you're only interested in drawing the new pixmap.

Switching over to the QPainter::drawPixmap() would avoid this issue.

-- 
 [ signature omitted ] 

Message 3 in thread

On 12.09.07 18:58:51, Andrew Medico wrote:
> Then I believe subsequent QPixmap::loadFromData() calls would cause
> the label's instance of the QPixmap to become a copy instead of
> sharing the original data (so that the QLabel can still access the
> original pixmap data that was passed by value). This work is of course
> wasted in this situation because as soon as the new pixmap is
> obtained, you're only interested in drawing the new pixmap.

The real problem in the OP's case is that he uses
QPixmap::loadFromData. Just as the ::load() method for QPixmap,
loadFromData uses QImage::load to load the data and then converts from
QImage to QPixmap. This conversion is slow (as stated in the docs). 

So on top of using a QWidget subclass and override its paintEvent method
the OP should use QImage::loadFromData() and directly paint the QImage
without the costly conversion to QPixmap.

Andreas

-- 
 [ signature omitted ] 

Message 4 in thread

On 9/12/07, Andreas Pakulat <apaku@xxxxxx> wrote:
> On 12.09.07 18:58:51, Andrew Medico wrote:
> > Then I believe subsequent QPixmap::loadFromData() calls would cause
> > the label's instance of the QPixmap to become a copy instead of
> > sharing the original data (so that the QLabel can still access the
> > original pixmap data that was passed by value). This work is of course
> > wasted in this situation because as soon as the new pixmap is
> > obtained, you're only interested in drawing the new pixmap.
>
> The real problem in the OP's case is that he uses
> QPixmap::loadFromData. Just as the ::load() method for QPixmap,
> loadFromData uses QImage::load to load the data and then converts from
> QImage to QPixmap. This conversion is slow (as stated in the docs).
>
> So on top of using a QWidget subclass and override its paintEvent method
> the OP should use QImage::loadFromData() and directly paint the QImage
> without the costly conversion to QPixmap.

I interpreted the "not displaying the images" statement to mean that
he's always calling QPixmap::loadFromData() (regardless of whether the
display is turned on or not), so that wouldn't factor into the 6Hz vs.
30Hz rate difference. My interpretation could be wrong, though.

-- 
 [ signature omitted ] 

Message 5 in thread

On 12.09.07 20:43:48, Andrew Medico wrote:
> On 9/12/07, Andreas Pakulat <apaku@xxxxxx> wrote:
> > On 12.09.07 18:58:51, Andrew Medico wrote:
> > > Then I believe subsequent QPixmap::loadFromData() calls would cause
> > > the label's instance of the QPixmap to become a copy instead of
> > > sharing the original data (so that the QLabel can still access the
> > > original pixmap data that was passed by value). This work is of course
> > > wasted in this situation because as soon as the new pixmap is
> > > obtained, you're only interested in drawing the new pixmap.
> >
> > The real problem in the OP's case is that he uses
> > QPixmap::loadFromData. Just as the ::load() method for QPixmap,
> > loadFromData uses QImage::load to load the data and then converts from
> > QImage to QPixmap. This conversion is slow (as stated in the docs).
> >
> > So on top of using a QWidget subclass and override its paintEvent method
> > the OP should use QImage::loadFromData() and directly paint the QImage
> > without the costly conversion to QPixmap.
> 
> I interpreted the "not displaying the images" statement to mean that
> he's always calling QPixmap::loadFromData() (regardless of whether the
> display is turned on or not), so that wouldn't factor into the 6Hz vs.
> 30Hz rate difference. My interpretation could be wrong, though.

Indeed, however the loadFromData is the only "slow" thing besides maybe
using a qlabel for displaying the pixmap. At least as far as I can see,
the implict sharing is no problem at all, as Bo already pointed out.

Lets see what the the Op really meant with "don't display the images".

Andreas

-- 
 [ signature omitted ] 

Message 6 in thread

You are correct, the original "not displaying the images" version did
NOT call loadFromData(), it just consumed all the data coming down the
TCP socket and threw it away.  I did some further tests where would
still I call loadFromData(), but still don't display the image onscreen,
and it is definitely the QPixmap::loadFromData() that slows stuff down.


If I switched to using a QImage and calling QImage::loadFromData(), I'm
able to create QImages at 35 Hz, so that looks promising.  I knew that
going from QImage to QPixmap was slow, I just didn't look into the Qt
source to see that QPixmap::loadFromData() actually does that
conversion.

So I think I should be able to do Andrew's original idea below of
inheriting from QWidget for my GUI object, adding a slot
updateFrame(const QImage&) and then overriding the paintEvent() function
to draw the QImage, thus avoiding the whole QImage->QPixmap slowdown.

Thanks for the tips!
Sean

-----Original Message-----
From: Andrew Medico [mailto:a.medico@xxxxxxxxx] 
Sent: Wednesday, September 12, 2007 8:44 PM
To: qt-interest@xxxxxxxxxxxxx
Subject: Re: Image painting speed issues

On 9/12/07, Andreas Pakulat <apaku@xxxxxx> wrote:
> On 12.09.07 18:58:51, Andrew Medico wrote:
> > Then I believe subsequent QPixmap::loadFromData() calls would cause 
> > the label's instance of the QPixmap to become a copy instead of 
> > sharing the original data (so that the QLabel can still access the 
> > original pixmap data that was passed by value). This work is of 
> > course wasted in this situation because as soon as the new pixmap is

> > obtained, you're only interested in drawing the new pixmap.
>
> The real problem in the OP's case is that he uses 
> QPixmap::loadFromData. Just as the ::load() method for QPixmap, 
> loadFromData uses QImage::load to load the data and then converts from

> QImage to QPixmap. This conversion is slow (as stated in the docs).
>
> So on top of using a QWidget subclass and override its paintEvent 
> method the OP should use QImage::loadFromData() and directly paint the

> QImage without the costly conversion to QPixmap.

I interpreted the "not displaying the images" statement to mean that
he's always calling QPixmap::loadFromData() (regardless of whether the
display is turned on or not), so that wouldn't factor into the 6Hz vs.
30Hz rate difference. My interpretation could be wrong, though.

--
 [ signature omitted ] 

Message 7 in thread

Ok, I've now modified my setup to use a QImage instead of QPixmap, and
I've created a new widget which paints the image to the screen.  I'm
still getting a really slow frame rate, although now it really is when
I'm displaying the images.  The relevant code is below.  Note that now
I'm always populating the QImage from the TIFF, even if I don't intend
to ever show it.  I got 35 Hz when I don't show the image, 7 Hz when I
do.

What am I missing?
Sean

---tcp socket class---
  // this code is connected to the TCP socket's readyRead() signal
  QByteArray tiffBuffer;
  tiffBuffer = read(hdr.sizeOfMessage);  // read TIFF into QByteArray
  QImage tiffImage;
  tiffImage.loadFromData(tiffBuffer); // create QImage from TIFF
  if (emitImages)  // false = 35 Hz, true = 7 Hz
  {
    if (guiWidget) // pointer to my GUI widget
    {
	guiWidget->slotUpdateFrame(tiffImage); // draw to screen
    }
  }
---end socket code--- 

Here's my ImageRendererclass:
---image renderer---
  ImageRenderer::ImageRenderer(QWidget *parent)
	: QWidget(parent)
  {
    resize(parent->width(), parent->height());
  }

  ImageRenderer::~ImageRenderer()
  {
  }

  void ImageRenderer::slotUpdateFrame(const QImage& newImage)
  {
    image = newImage;  // this should use implicit sharing
    repaint();
  }

  void ImageRenderer::slotClearImage()
  {
    image = QImage();
    repaint();
  }

  void ImageRenderer::paintEvent(QPaintEvent* event)
  {
    QPainter painter(this);
    painter.drawImage(QPoint(0,0), image);
  }
---end image renderer---


-----Original Message-----
From: Murphy, Sean M. [mailto:sean.murphy@xxxxxxxxxx] 
Sent: Thursday, September 13, 2007 12:37 PM
To: Andrew Medico; qt-interest@xxxxxxxxxxxxx
Subject: RE: Image painting speed issues

You are correct, the original "not displaying the images" version did
NOT call loadFromData(), it just consumed all the data coming down the
TCP socket and threw it away.  I did some further tests where would
still I call loadFromData(), but still don't display the image onscreen,
and it is definitely the QPixmap::loadFromData() that slows stuff down.


If I switched to using a QImage and calling QImage::loadFromData(), I'm
able to create QImages at 35 Hz, so that looks promising.  I knew that
going from QImage to QPixmap was slow, I just didn't look into the Qt
source to see that QPixmap::loadFromData() actually does that
conversion.

So I think I should be able to do Andrew's original idea below of
inheriting from QWidget for my GUI object, adding a slot
updateFrame(const QImage&) and then overriding the paintEvent() function
to draw the QImage, thus avoiding the whole QImage->QPixmap slowdown.

Thanks for the tips!
Sean

-----Original Message-----
From: Andrew Medico [mailto:a.medico@xxxxxxxxx]
Sent: Wednesday, September 12, 2007 8:44 PM
To: qt-interest@xxxxxxxxxxxxx
Subject: Re: Image painting speed issues

On 9/12/07, Andreas Pakulat <apaku@xxxxxx> wrote:
> On 12.09.07 18:58:51, Andrew Medico wrote:
> > Then I believe subsequent QPixmap::loadFromData() calls would cause 
> > the label's instance of the QPixmap to become a copy instead of 
> > sharing the original data (so that the QLabel can still access the 
> > original pixmap data that was passed by value). This work is of 
> > course wasted in this situation because as soon as the new pixmap is

> > obtained, you're only interested in drawing the new pixmap.
>
> The real problem in the OP's case is that he uses 
> QPixmap::loadFromData. Just as the ::load() method for QPixmap, 
> loadFromData uses QImage::load to load the data and then converts from

> QImage to QPixmap. This conversion is slow (as stated in the docs).
>
> So on top of using a QWidget subclass and override its paintEvent 
> method the OP should use QImage::loadFromData() and directly paint the

> QImage without the costly conversion to QPixmap.

I interpreted the "not displaying the images" statement to mean that
he's always calling QPixmap::loadFromData() (regardless of whether the
display is turned on or not), so that wouldn't factor into the 6Hz vs.
30Hz rate difference. My interpretation could be wrong, though.

--
 [ signature omitted ] 

Message 8 in thread

Murphy, Sean M. wrote:
> Ok, I've now modified my setup to use a QImage instead of QPixmap, and
> I've created a new widget which paints the image to the screen.  I'm
> still getting a really slow frame rate, although now it really is when
> I'm displaying the images.  The relevant code is below.  Note that now
> I'm always populating the QImage from the TIFF, even if I don't intend
> to ever show it.  I got 35 Hz when I don't show the image, 7 Hz when I
> do.
>
> What am I missing?
> Sean
>
> ---tcp socket class---
>   // this code is connected to the TCP socket's readyRead() signal
>   QByteArray tiffBuffer;
>   tiffBuffer = read(hdr.sizeOfMessage);  // read TIFF into QByteArray
>   QImage tiffImage;
>   tiffImage.loadFromData(tiffBuffer); // create QImage from TIFF
>   if (emitImages)  // false = 35 Hz, true = 7 Hz
>   {
>     if (guiWidget) // pointer to my GUI widget
>     {
> 	guiWidget->slotUpdateFrame(tiffImage); // draw to screen
>     }
>   }
> ---end socket code--- 
>
> Here's my ImageRendererclass:
> ---image renderer---
>   ImageRenderer::ImageRenderer(QWidget *parent)
> 	: QWidget(parent)
>   {
>     resize(parent->width(), parent->height());
>   }
>
>   ImageRenderer::~ImageRenderer()
>   {
>   }
>
>   void ImageRenderer::slotUpdateFrame(const QImage& newImage)
>   {
>     image = newImage;  // this should use implicit sharing
>     repaint();
>   }
>
>   void ImageRenderer::slotClearImage()
>   {
>     image = QImage();
>     repaint();
>   }
>
>   void ImageRenderer::paintEvent(QPaintEvent* event)
>   {
>     QPainter painter(this);
>     painter.drawImage(QPoint(0,0), image);
>   }
> ---end image renderer---
>
>
> -----Original Message-----
> From: Murphy, Sean M. [mailto:sean.murphy@xxxxxxxxxx] 
> Sent: Thursday, September 13, 2007 12:37 PM
> To: Andrew Medico; qt-interest@xxxxxxxxxxxxx
> Subject: RE: Image painting speed issues
>
> You are correct, the original "not displaying the images" version did
> NOT call loadFromData(), it just consumed all the data coming down the
> TCP socket and threw it away.  I did some further tests where would
> still I call loadFromData(), but still don't display the image onscreen,
> and it is definitely the QPixmap::loadFromData() that slows stuff down.
>
>
> If I switched to using a QImage and calling QImage::loadFromData(), I'm
> able to create QImages at 35 Hz, so that looks promising.  I knew that
> going from QImage to QPixmap was slow, I just didn't look into the Qt
> source to see that QPixmap::loadFromData() actually does that
> conversion.
>
> So I think I should be able to do Andrew's original idea below of
> inheriting from QWidget for my GUI object, adding a slot
> updateFrame(const QImage&) and then overriding the paintEvent() function
> to draw the QImage, thus avoiding the whole QImage->QPixmap slowdown.
>
> Thanks for the tips!
> Sean
>
> -----Original Message-----
> From: Andrew Medico [mailto:a.medico@xxxxxxxxx]
> Sent: Wednesday, September 12, 2007 8:44 PM
> To: qt-interest@xxxxxxxxxxxxx
> Subject: Re: Image painting speed issues
>
> On 9/12/07, Andreas Pakulat <apaku@xxxxxx> wrote:
>   
>> On 12.09.07 18:58:51, Andrew Medico wrote:
>>     
>>> Then I believe subsequent QPixmap::loadFromData() calls would cause 
>>> the label's instance of the QPixmap to become a copy instead of 
>>> sharing the original data (so that the QLabel can still access the 
>>> original pixmap data that was passed by value). This work is of 
>>> course wasted in this situation because as soon as the new pixmap is
>>>       
>
>   
>>> obtained, you're only interested in drawing the new pixmap.
>>>       
>> The real problem in the OP's case is that he uses 
>> QPixmap::loadFromData. Just as the ::load() method for QPixmap, 
>> loadFromData uses QImage::load to load the data and then converts from
>>     
>
>   
>> QImage to QPixmap. This conversion is slow (as stated in the docs).
>>
>> So on top of using a QWidget subclass and override its paintEvent 
>> method the OP should use QImage::loadFromData() and directly paint the
>>     
>
>   
>> QImage without the costly conversion to QPixmap.
>>     
>
> I interpreted the "not displaying the images" statement to mean that
> he's always calling QPixmap::loadFromData() (regardless of whether the
> display is turned on or not), so that wouldn't factor into the 6Hz vs.
> 30Hz rate difference. My interpretation could be wrong, though.
>
> --
> Andrew Medico <a.medico@xxxxxxxxx>
>
> --
> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx with
> "unsubscribe" in the subject or the body.
> List archive and information: http://lists.trolltech.com/qt-interest/
>
> --
> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx with
> "unsubscribe" in the subject or the body.
> List archive and information: http://lists.trolltech.com/qt-interest/
>
> --
> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx with "unsubscribe" in the subject or the body.
> List archive and information: http://lists.trolltech.com/qt-interest/
>
>
>   
Have you tried using callgrind(valgrind toolkit) on linux? It can be
immensely illuminating as to where cycles are being consumed. :)

-- 
 [ signature omitted ] 

Message 9 in thread

On 9/13/07, Murphy, Sean M. <sean.murphy@xxxxxxxxxx> wrote:
> Ok, I've now modified my setup to use a QImage instead of QPixmap, and
> I've created a new widget which paints the image to the screen.  I'm
> still getting a really slow frame rate, although now it really is when
> I'm displaying the images.  The relevant code is below.  Note that now
> I'm always populating the QImage from the TIFF, even if I don't intend
> to ever show it.  I got 35 Hz when I don't show the image, 7 Hz when I
> do.

I get 100FPS from similar code (linked below) displaying a
512x512x32bit QImage. It simply does a QImage::fill() with a random
color between frames so loading TIFFs will be somewhat slower, but the
Qt graphics code should have no problem with >7FPS. This is running on
my MacBook - 2.0 GHz Core Duo, 2GB RAM, and Intel GMA 950 graphics.

As for why your app is still slow, I'm not sure. As Russ said, try
profiling it and see where the time is actualy going.

Compilable example: http://andrew-medico.com/misc/image.zip

-- 
 [ signature omitted ] 

Message 10 in thread

I don't seem to be able to run valgrind on it at the moment, I'm on a
64bit machine and apparently the version of valgrind on here only
handles 32-bit executables.  Can valgrind be run on 64-bit machines?

I don't get why mine would be slower than yours, once I've got a QImage
haven't I already done the TIFF conversion, since I'm now doing
QImage::loadFromData(myTiff)?  So then I wouldn't think that painting a
solid color QImage would be any faster/slower than an actual image.
Right now my code always creates the QImage from the TIFF, and then
depending on a bool paints it to the screen.  If I set the bool not to
paint it I get 35 Hz, so the QImage::loadFromData() function doesn't
seem to be chewing up much time, but as soon as I flip that bool to
actually show the image, the frame rate plummets.

This one is totally driving me nuts!
Sean

-----Original Message-----
From: Andrew Medico [mailto:a.medico@xxxxxxxxx] 
Sent: Friday, September 14, 2007 12:09 AM
To: qt-interest@xxxxxxxxxxxxx
Subject: Re: Image painting speed issues [still no luck]

On 9/13/07, Murphy, Sean M. <sean.murphy@xxxxxxxxxx> wrote:
> Ok, I've now modified my setup to use a QImage instead of QPixmap, and

> I've created a new widget which paints the image to the screen.  I'm 
> still getting a really slow frame rate, although now it really is when

> I'm displaying the images.  The relevant code is below.  Note that now

> I'm always populating the QImage from the TIFF, even if I don't intend

> to ever show it.  I got 35 Hz when I don't show the image, 7 Hz when I

> do.

I get 100FPS from similar code (linked below) displaying a 512x512x32bit
QImage. It simply does a QImage::fill() with a random color between
frames so loading TIFFs will be somewhat slower, but the Qt graphics
code should have no problem with >7FPS. This is running on my MacBook -
2.0 GHz Core Duo, 2GB RAM, and Intel GMA 950 graphics.

As for why your app is still slow, I'm not sure. As Russ said, try
profiling it and see where the time is actualy going.

Compilable example: http://andrew-medico.com/misc/image.zip

--
 [ signature omitted ] 

Message 11 in thread

Murphy, Sean M. wrote:

> I don't seem to be able to run valgrind on it at the moment, I'm on a
> 64bit machine and apparently the version of valgrind on here only
> handles 32-bit executables.  Can valgrind be run on 64-bit machines?
> 
> I don't get why mine would be slower than yours, once I've got a QImage
> haven't I already done the TIFF conversion, since I'm now doing
> QImage::loadFromData(myTiff)?  So then I wouldn't think that painting a
> solid color QImage would be any faster/slower than an actual image.
> Right now my code always creates the QImage from the TIFF, and then
> depending on a bool paints it to the screen.  If I set the bool not to
> paint it I get 35 Hz, so the QImage::loadFromData() function doesn't
> seem to be chewing up much time, but as soon as I flip that bool to
> actually show the image, the frame rate plummets.

You should note that when you display a QImage in a Widget it is converted
to a Pixmap to show it on the screen. You have moved the conversion work
from the QPixmap::loadFromData() method to the drawImage() call.

You did not explain how your setup looks like. If you are displaying on a
remote X11 Server 6Hz is not too slow.

Christoph

--
 [ signature omitted ] 

Message 12 in thread

The 6 Hz speed is sitting at the actual machine, not over remote X display.  The problem is Qt's TIFF parser is really really slow.  I took Andrew's modification of my code, and changed it so instead of filling a QImage with random colors, I made it so I could load an image once from a file and then try to draw it over and over at 100 Hz.  I then used an image editor to draw an image and then saved it as a jpeg, tiff, png, and maybe a couple other formats.  If I load any of the images that aren't the TIFF I get pretty good speed, around 60-70 Hz.  If I load the TIFF one, the speed plummets to 6-7 Hz.  All of these use QFile to load the image into a QByteArray, then at an attempted 100 Hz rate, I call QImage::loadFromData() and then QPainter.drawImage() to paint the QImage onscreen.

I'm at home right now and the code is at work, so I'll post my example tomorrow.  

In my specific case, the TIFFs I'm decoding all have the same format, the image data inside the TIFF is just in a bitmap type format, so I may just end up writing my own parser and see if that speeds things up.  I'm not sure why the version of libtiff used in Qt is so slow.

Sean

-----Original Message-----
From: Christoph Bartoschek [mailto:bartoschek@xxxxxx]
Sent: Sat 9/15/2007 5:11 AM
To: qt-interest@xxxxxxxxxxxxx
Subject: RE: Image painting speed issues [still no luck]
 
Murphy, Sean M. wrote:

> I don't seem to be able to run valgrind on it at the moment, I'm on a
> 64bit machine and apparently the version of valgrind on here only
> handles 32-bit executables.  Can valgrind be run on 64-bit machines?
> 
> I don't get why mine would be slower than yours, once I've got a QImage
> haven't I already done the TIFF conversion, since I'm now doing
> QImage::loadFromData(myTiff)?  So then I wouldn't think that painting a
> solid color QImage would be any faster/slower than an actual image.
> Right now my code always creates the QImage from the TIFF, and then
> depending on a bool paints it to the screen.  If I set the bool not to
> paint it I get 35 Hz, so the QImage::loadFromData() function doesn't
> seem to be chewing up much time, but as soon as I flip that bool to
> actually show the image, the frame rate plummets.

You should note that when you display a QImage in a Widget it is converted
to a Pixmap to show it on the screen. You have moved the conversion work
from the QPixmap::loadFromData() method to the drawImage() call.

You did not explain how your setup looks like. If you are displaying on a
remote X11 Server 6Hz is not too slow.

Christoph

--
 [ signature omitted ] 

Message 13 in thread

Hi,

> The 6 Hz speed is sitting at the actual machine, not over remote X
> display.  The problem is Qt's TIFF parser is really really slow.  I took
> Andrew's modification of my code, and changed it so instead of filling a
> QImage with random colors, I made it so I could load an image once from
> a file and then try to draw it over and over at 100 Hz.  I then used an
> image editor to draw an image and then saved it as a jpeg, tiff, png,
> and maybe a couple other formats.  If I load any of the images that
> aren't the TIFF I get pretty good speed, around 60-70 Hz.  If I load the
> TIFF one, the speed plummets to 6-7 Hz.  All of these use QFile to load
> the image into a QByteArray, then at an attempted 100 Hz rate, I call
> QImage::loadFromData() and then QPainter.drawImage() to paint the QImage
> onscreen.

What's the size of the TIFF files you're trying to load, compared to the size
of files in other formats?

> In my specific case, the TIFFs I'm decoding all have the same format,
> the image data inside the TIFF is just in a bitmap type format, so I may
> just end up writing my own parser and see if that speeds things up.  I'm
> not sure why the version of libtiff used in Qt is so slow.

Qt is using the standard libtiff library. It could be that Qt is not calling
libtiff in the most speed efficient way, I don't know. It will be easier to
tell when you post your code. Have you built Qt in debug mode?

--
 [ signature omitted ] 

Message 14 in thread

Here's the test.  To answer your questions Dimitri, as you'll see when
you open this up, the images are the same pixel size (512x512), but the
file sizes in bytes are obviously different.  

I'm using Qt 4.3.0 and it was configured with the following options, so
I shouldn't be using debug versions:
  ./configure -qt-gif -qt-libtiff -qt-libjpeg

You'll see huge speed differences between running this and viewing the
tiff file vs. any of the other three.  Just build the application and
run it, it will prompt for an image file, choose one of the 4 images
included, then every 10 seconds a qDebug() statement will print out the
current frame rate to the command line.

Sean

-----Original Message-----
From: Dimitri [mailto:dimitri@xxxxxxxxxxxxx] 
Sent: Sunday, September 16, 2007 11:54 PM
To: qt-interest@xxxxxxxxxxxxx
Subject: Re: Image painting speed issues [still no luck]

Hi,

> The 6 Hz speed is sitting at the actual machine, not over remote X 
> display.  The problem is Qt's TIFF parser is really really slow.  I 
> took Andrew's modification of my code, and changed it so instead of 
> filling a QImage with random colors, I made it so I could load an 
> image once from a file and then try to draw it over and over at 100 
> Hz.  I then used an image editor to draw an image and then saved it as

> a jpeg, tiff, png, and maybe a couple other formats.  If I load any of

> the images that aren't the TIFF I get pretty good speed, around 60-70 
> Hz.  If I load the TIFF one, the speed plummets to 6-7 Hz.  All of 
> these use QFile to load the image into a QByteArray, then at an 
> attempted 100 Hz rate, I call
> QImage::loadFromData() and then QPainter.drawImage() to paint the 
> QImage onscreen.

What's the size of the TIFF files you're trying to load, compared to the
size of files in other formats?

> In my specific case, the TIFFs I'm decoding all have the same format, 
> the image data inside the TIFF is just in a bitmap type format, so I 
> may just end up writing my own parser and see if that speeds things 
> up.  I'm not sure why the version of libtiff used in Qt is so slow.

Qt is using the standard libtiff library. It could be that Qt is not
calling libtiff in the most speed efficient way, I don't know. It will
be easier to tell when you post your code. Have you built Qt in debug
mode?

--
 [ signature omitted ] 

Attachment: imageTest.tar.gz
Description: imageTest.tar.gz


Message 15 in thread

Hi,

> Here's the test.  To answer your questions Dimitri, as you'll see when
> you open this up, the images are the same pixel size (512x512), but the
> file sizes in bytes are obviously different.  
> [...]
> You'll see huge speed differences between running this and viewing the
> tiff file vs. any of the other three.  Just build the application and

There are many issues here:
1) Loading the file into memory.
2) Transforming the data loaded into memory into QImage.
3) Transforming the Qimage into a pixmap.
4) Displaying the pixmap repeatedly.

About issue 1:
You're loading the file only once, so file size is not related to the drop in
frame rate. Nevertheless note that the TIFF file weighs 771 KB against only 30
KB and 51 KB for the JPEG and PNG files, so it should load slower.

About issue 2:
It could be that the TIFF reader is indeed less efficient, I don't know.

About issue 3:
The resulting QImage may be different (24-bit vs. color-mapped 8-bit for
example) which could also have an impact.

About issue 4:
Maybe the QPixmaps are also somehow different (alpha channel) ?

You need to identify whether the difference in frame rate is related to issues
2, 3 or 4.

--
 [ signature omitted ] 

Pages: Prev | 1 | 2 | Next