| Trolltech Home | Qt-interest Home | Recent Threads | All Threads | Author | Date | |
| All threads index page 3 | |
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 ]
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 ]
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 ]
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 ]
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 ]
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 ]
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 ]
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 ]
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 ]
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 ]
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 ]
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 ]
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 ]
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
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 ]