1

Since it seems I need to improve the performance of my code, I wanted to ask, how good is the performance of QGraphicsPixmapItem::setPixmap(*Qimage)? My Image is 1024x1024 px and is updated about every 2.5seconds. But I need it to be updated much faster (4096x every 2.5 seconds at best). Is it possible with QGraphicsPixmapItem::setPixmap(*Qimage)? I am filling every single pixel of QImage directly with an array: array[y*SCENEWIDTH+x] = color.

But with that speed QGraphicsPixmapItem::setPixmap(*Qimage) seems to freeze my GUI. Goal is to display huge ammounts of data incoming in polar coordinates (azimuth per azimuth) (radar video).

Any suggestions? Thank you!

honiahaka10
  • 772
  • 4
  • 9
  • 29
  • 1
    *But I need it to be updated much faster (4096x every 2.5 seconds at best)..* 4096 / 2.5 = 1638 times per second. You only need 60 frames per second for smooth graphics transitions, so why do you believe that you need to update the image so quickly? – TheDarkKnight Nov 18 '15 at 13:55
  • @TheDarkKnight Maybe he means 4096x4096 sized image should be updated once every 2.5 seconds. – thuga Nov 18 '15 at 14:02
  • @TheDarkKnight I also thought about that, well 4096 would be the perfect. Okay I agree with you, that I only need 60fps (and maybe a little more) but even with much slower speed (about 5fps) my GUI gets pretty slow and freezes for a short time. When I only remove `QGraphicsPixmapItem::setPixmap(*Qimage)` everything works perfectly, so i think the problem must be in here. – honiahaka10 Nov 18 '15 at 14:05
  • @thuga TheDarkKnight understands correctly, but you aren't wrong, I also will need to perform that for much larger images (4096x8192, or maybe even 16384x16384). – honiahaka10 Nov 18 '15 at 14:08
  • I suggest showing your code in the form of an [mcve](http://stackoverflow.com/help/mcve), which will give us a better idea of what you're doing and able to help us assist you. – TheDarkKnight Nov 18 '15 at 14:39
  • In the mean time, I can only guess as to the problem, but I'd derive my own class from QGraphicsItem with the QImage as a member of the class, then draw this in the item's paint function with a call to the painter's drawImage function. – TheDarkKnight Nov 18 '15 at 14:44
  • What kind of profiling have you done before jumping into optimization? – Vlad Feinstein Nov 18 '15 at 14:45
  • @TheDarkKnight I do not think a mcve will be possible, showing the same results with less code but I will try. (If I manage to create a mcve I cannot post before friday.) – honiahaka10 Nov 18 '15 at 14:49
  • @VladFeinstein What do you mean by profiling? Analyzing the performance of my program? I did not do anything like that (I would not even know how to do that). I can see that there are performance issues just by looking at the screen (also removing the setPixmap() function will remove the performance issues). – honiahaka10 Nov 18 '15 at 14:55

1 Answers1

1

Rather than using QGraphicsPixmapItem and setting the image every time, I suggest creating your own class derived from QGraphicsItem and updating a member QImage. Here's an example which shows a smooth transition of updating a 1024 x 1024 image (note that it uses C++ 11)

class MyImage : public QGraphicsItem
{
public:

    MyImage()
        :QGraphicsItem(NULL)
    {
        img = QImage(1024, 1024, QImage::Format_RGB32);
        static int red = 0;
        static int green = 0;
        static int blue = 0;
        img.fill(QColor(red++%255, green++%255, blue++%255));

        QTimer* pTimer = new QTimer;
        QObject::connect(pTimer, &QTimer::timeout, [=](){

            // C++ 11 connection to a lambda function, with Qt 5 connection syntax
            img.fill(QColor(red++%255, green++%255, blue++%255)); 
            update();
        });

        pTimer->start(1000 / 30); // 30 frames per second
    }

private:
    virtual QRectF boundingRect() const
    {
        return QRectF(0, 0, 1024, 1024);
    }

    QImage img;

    void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
    {
        painter->drawImage(0, 0, img);
    }
};

If you instantiate an instance of this class and add it to a QGraphicsScene, you should see a smooth transition of the image being drawn, changing colour from black through to white.

TheDarkKnight
  • 27,181
  • 6
  • 55
  • 85
  • Thank you I just wanted to try that but your `QObject::connect()` statement seems to make problems: No access of protected member QTimer::timeout and many Syntaxerrors. Also your connect statement looks pretty weird to me... When I try to make my own connect statement it does not work either `QObject::connect(pTimer, SIGNAL(timeout()), this, SLOT(updateImage()));` – honiahaka10 Nov 18 '15 at 15:34
  • The connect is the Qt 5 syntax with [C++11](http://stackoverflow.com/questions/19398438/c-qt-how-to-add-std-c11-to-the-makefile-which-is-generated-by-qmake/19398489#19398489), which allows connecting to a lambda function. Even if you don't use C++11, you really should adopt the Qt 5 connection syntax, as it provides compile-time checks, which are not available when using the old SIGNAL and SLOT macros. – TheDarkKnight Nov 18 '15 at 16:00
  • If your updateImage() connection doesn't work, you'll need to declare it as a slot and inherit from QGraphicsObject, instead of QGraphicsItem. QGraphicsObject gives the item signals and slots functionality. By using C++ 11 and the Qt 5 connection, you can connect to any function, even if it's not declared as a slot, which is why it works in the example above. – TheDarkKnight Nov 18 '15 at 16:04
  • Thank you `QGraphicsObject` works! I am using Qt4.8 so that was the problem. I now will try to implement your example into my code and look, whether it will fix my problem. – honiahaka10 Nov 19 '15 at 07:40
  • Great, let us know how you get on ;O) – TheDarkKnight Nov 19 '15 at 17:07
  • It seems to work, thank you! It would even work with `pTimer->start(1000 / (4096/2.5));` ;) But also i figured out, that `emit signal(this, "some other variables")` was also involved with that problem not only `setPixmap()` Using `emit signal("some other variables")` without `this` at the updaterate of 4096/2.5sec works fine. I do not think I will need this signal in the future anymore, but I still would like to know why `this` is causing that problem? – honiahaka10 Nov 20 '15 at 10:03