Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Proper way to pass QImage from thread through signal?
Forum Updated to NodeBB v4.3 + New Features

Proper way to pass QImage from thread through signal?

Scheduled Pinned Locked Moved Solved General and Desktop
12 Posts 5 Posters 5.4k Views 3 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • SGaistS Offline
    SGaistS Offline
    SGaist
    Lifetime Qt Champion
    wrote on last edited by
    #2

    Hi,

    The calls to paintEvent are completely unrelated to your displayFrame slot being called. There are a lot of reasons for which paintEvent is called. If you want basic debugging, you should put your qDebug statement in the slot there.

    By the way, why not use the new syntax when connecting m_renderer ?

    Interested in AI ? www.idiap.ch
    Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

    1 Reply Last reply
    0
    • VRoninV Offline
      VRoninV Offline
      VRonin
      wrote on last edited by VRonin
      #3

      I'm sorry to spoil the party but I'm afraid it's a no-go.

      From https://doc.qt.io/qt-5/thread-basics.html#gui-thread-and-worker-thread

      All widgets and several related classes, for example QPixmap, don't work in secondary threads.

      QPainter::drawImage ultimately calls QPaintEngine::drawImage that creates a QPixmap from that image and draws it.

      P.S.

      • You call VWidget::requestRender when the timer timeouts but your code shows GLWidget::requestRender instead (class name is different)
      • VWidget::stopRendering() is currently a race condition. Renderer::m_exiting should be declared as type std::atomic_bool to make it safe

      "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
      ~Napoleon Bonaparte

      On a crusade to banish setIndexWidget() from the holy land of Qt

      1 Reply Last reply
      2
      • SGaistS Offline
        SGaistS Offline
        SGaist
        Lifetime Qt Champion
        wrote on last edited by
        #4

        @VRonin said in Proper way to pass QImage from thread through signal?:

        QPainter::drawImage ultimately calls QPaintEngine::drawImage that crates a QPixmap from that image and draws it.

        Nice one ! I forgot about that low level detail.

        Interested in AI ? www.idiap.ch
        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

        1 Reply Last reply
        0
        • W Offline
          W Offline
          wesblake
          wrote on last edited by
          #5

          So I can't do this?! I've tried EVERYTHING and always seem to run into an issue. :( I saw some examples where something similar was done, supposedly successfully. The GLWidget is a leftover but not that way in my code.
          I'm out of options.
          So what I have ultimately is a video relay app built on an SDK. The SDK supplies up to 3 raw images at a time, I need to display them on my video surface. Currently, the app uses 2 classes I wrote. On Mac and Linux, a QGLWidget based class, renders completely, using QPainter and QImage on a separate thread. Performs great, but has 3 issues. Known bug where styles are lost after some time on Windows, Mac is dropping OpenGL, and it's deprecated, running into issues with Catalina, works for now. For Windows, I use D2D but it's not threaded so there are some performance issues.
          So I'm looking for a replacement, preferably threaded, and preferably one widget for all OS now.
          I have tried and failed with (using Qt 5.12.X and 5.13.X):

          • QOpenGLWidget, ran into this bug preventing me from using it since we must run full screen: https://bugreports.qt.io/browse/QTBUG-49657
          • RHI, no idea where to start. Apparently it's beta, there's one example, and it uses QML while our app is a QWidget based desktop app.
          • Tried QWidget + QPainter with NO threading. I stopped half way because I got a test working and it seems it impacted UI performance enough it was a no go.
          • I feel like I've gone down many other rabbit holes too. QGraphicsView/Scene, etc. Each time I get half way and something just won't work.

          Any bright ideas for me then? I really thought I was close this time!

          1 Reply Last reply
          0
          • W Offline
            W Offline
            wesblake
            wrote on last edited by
            #6

            Actually, this should still be possible, this is where I started:
            https://doc.qt.io/qt-5/threads-modules.html

            "QPainter can be used in a thread to paint onto QImage, QPrinter, and QPicture paint devices. Painting onto QPixmaps and QWidgets is not supported. On macOS the automatic progress dialog will not be displayed if you are printing from outside the GUI thread."

            I put a qDebug in displayFrame and it is firing off around 50 times a second. So, I think I still am passing the QImage incorrectly?

            1 Reply Last reply
            0
            • SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on last edited by SGaist
              #7

              Your issue is specific to drawImage with the default paint engine. To test, create a simple QImage, fill it with one colour and draw a rect if another's colour on it.

              By the way, why are you loading your image and then calling drawImage ? Why not directly load the image itself in the target QImage ?

              Interested in AI ? www.idiap.ch
              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

              W 1 Reply Last reply
              1
              • A Offline
                A Offline
                Asperamanca
                wrote on last edited by
                #8

                Have you debugged the signal-slot connection? Do you arrive in the displayFrame slot? What size does the QImage you sent when emitting the signal as opposed the image you receive in the displayFrame slot?

                1 Reply Last reply
                2
                • SGaistS SGaist

                  Your issue is specific to drawImage with the default paint engine. To test, create a simple QImage, fill it with one colour and draw a rect if another's colour on it.

                  By the way, why are you loading your image and then calling drawImage ? Why not directly load the image itself in the target QImage ?

                  W Offline
                  W Offline
                  wesblake
                  wrote on last edited by
                  #9

                  @SGaist said in Proper way to pass QImage from thread through signal?:

                  Your issue is specific to drawImage with the default paint engine. To test, create a simple QImage, fill it with one colour and draw a rect if another's colour on it.

                  By the way, why are you loading your image and then calling drawImage ? Why not directly load the image itself in the target QImage ?

                  Because in my final code I won't be loading an image, I will be drawing the composite image. That was just a test with a known image so I could see if anything is getting through. I already tried the rectangles too and nothing comes through.

                  @Asperamanca I did by putting a qDebug in the slot and I see it getting called. I will add some more in and check image size, etc. Thanks.

                  VRoninV 1 Reply Last reply
                  0
                  • W wesblake

                    @SGaist said in Proper way to pass QImage from thread through signal?:

                    Your issue is specific to drawImage with the default paint engine. To test, create a simple QImage, fill it with one colour and draw a rect if another's colour on it.

                    By the way, why are you loading your image and then calling drawImage ? Why not directly load the image itself in the target QImage ?

                    Because in my final code I won't be loading an image, I will be drawing the composite image. That was just a test with a known image so I could see if anything is getting through. I already tried the rectangles too and nothing comes through.

                    @Asperamanca I did by putting a qDebug in the slot and I see it getting called. I will add some more in and check image size, etc. Thanks.

                    VRoninV Offline
                    VRoninV Offline
                    VRonin
                    wrote on last edited by
                    #10

                    @wesblake said in Proper way to pass QImage from thread through signal?:

                    I already tried the rectangles too and nothing comes through.

                    Change connect(m_renderer, SIGNAL(frameReady(QImage)), this, SLOT(displayFrame(QImage))); to connect(m_renderer, &Renderer::frameReady, this, &VWidget::displayFrame); so that we are sure the connection is working

                    change Renderer::render to

                    void Renderer::render()
                    {
                        if(m_exiting){
                            emit finished();
                            return;
                        }
                    const auto colors[] = {Qt::red,Qt::blue,Qt::black,Qt::green};
                        QImage videoFrame;
                    videoFrame.fill(colors[std::uniform_int_distribution<int>(0,3)(std::default_random_engine)]);
                         frameReady(videoFrame);
                    }
                    

                    and see if anything changed

                    nothing comes through.

                    Define "nothing comes through"

                    "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                    ~Napoleon Bonaparte

                    On a crusade to banish setIndexWidget() from the holy land of Qt

                    1 Reply Last reply
                    2
                    • W Offline
                      W Offline
                      wesblake
                      wrote on last edited by
                      #11

                      Thanks all for your help! How do I mark solved?
                      I feel dumb, it was simple. After adding in qDebug on the size of the image, both in Renderer and VWidget, both sides were 0.
                      So, it was simple, I was not initializing the QImage to paint into correctly in Renderer::render! I needed:

                      QImage videoFrame(m_glwidget->width(), m_glwidget->height(), QImage::Format_ARGB32_Premultiplied);

                      And now everything is working beautifully!

                      mrjjM 1 Reply Last reply
                      2
                      • W wesblake

                        Thanks all for your help! How do I mark solved?
                        I feel dumb, it was simple. After adding in qDebug on the size of the image, both in Renderer and VWidget, both sides were 0.
                        So, it was simple, I was not initializing the QImage to paint into correctly in Renderer::render! I needed:

                        QImage videoFrame(m_glwidget->width(), m_glwidget->height(), QImage::Format_ARGB32_Premultiplied);

                        And now everything is working beautifully!

                        mrjjM Offline
                        mrjjM Offline
                        mrjj
                        Lifetime Qt Champion
                        wrote on last edited by
                        #12

                        @wesblake
                        Hi. Good you found it.
                        you can mark it solved on your first post int eh Topic Tools button
                        alt text

                        1 Reply Last reply
                        0

                        • Login

                        • Login or register to search.
                        • First post
                          Last post
                        0
                        • Categories
                        • Recent
                        • Tags
                        • Popular
                        • Users
                        • Groups
                        • Search
                        • Get Qt Extensions
                        • Unsolved