Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. [SOLVED] QDeclarativeImageProvider and memory leaks with QImage
QtWS25 Last Chance

[SOLVED] QDeclarativeImageProvider and memory leaks with QImage

Scheduled Pinned Locked Moved QML and Qt Quick
9 Posts 4 Posters 5.5k Views
  • 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.
  • M Offline
    M Offline
    mbarclaygmail.com
    wrote on last edited by
    #1

    Hello,

    I have a 3rd party library that is generating pixel buffers. I create a QImage with the buffer and return it to the GUI using QDeclarativeImageProvider. I am using QImage so the buffers can be generated asynchronously. The problem is: QImage doesn't take ownership of the buffer. But I'm returning a QImage to the GUI, and there's no telling how many times it will be copied as its passed around the QDeclarative library. How do I know when QImage is done referencing my buffer so I can delete it? Or, is it possible to create a QImage that owns its buffer and will release it automatically?

    Thanks,
    Matt

    1 Reply Last reply
    0
    • T Offline
      T Offline
      task_struct
      wrote on last edited by
      #2

      Hello,

      QImage uses "implicit data sharing":http://qt-project.org/doc/qt-4.8/implicit-sharing.html#implicit-data-sharing so you will only one copy of data. When last QImage that uses this data is destroyed data buffer will be released.

      "Most good programmers do programming not because they expect to get paid or get adulation by the public, but because it is fun to program."

      • Linu...
      1 Reply Last reply
      0
      • L Offline
        L Offline
        lgeyer
        wrote on last edited by
        #3

        [quote author="MattB" date="1332203247"]Or, is it possible to create a QImage that owns its buffer and will release it automatically?[/quote]
        Subclass QImage and reimplement its destructor, which will delete the user-supplied buffer.

        [quote author="task_struct" date="1332246203"]Hello,
        QImage uses "implicit data sharing":http://qt-project.org/doc/qt-4.8/implicit-sharing.html#implicit-data-sharing so you will only one copy of data. When last QImage that uses this data is destroyed data buffer will be released.[/quote]
        This is not true for QImage using a user-supplied buffer.

        1 Reply Last reply
        0
        • M Offline
          M Offline
          mbarclaygmail.com
          wrote on last edited by
          #4

          [quote author="Lukas Geyer" date="1332247257"][quote author="MattB" date="1332203247"]Or, is it possible to create a QImage that owns its buffer and will release it automatically?[/quote]
          Subclass QImage and reimplement its destructor, which will delete the user-supplied buffer.[/quote]

          Won't this lead to the buffer being lost/deleted prematurely?

          @
          MyQImage MyProvider::requestImage(QString id, QSize *size, QSize requestedSize) {
          ...
          ...

          // Let's pretend this creates an 800x600 Image buffer
          uchar* data = generateSomeImageData();
          
          MyQImage image(data, 800, 600, QImage::Format_ARGB32);
          
          return image;
          

          }
          @

          Qt is expecting a QImage back from this method. If Qt does:

          @QImage image = provider->requestImage(id, &size, requestedSize);@

          Won't my custom data in MyQImage get sliced?

          Here's the line that's causing me problems:

          http://qt.gitorious.org/qt/qt/blobs/4.7/src/gui/image/qimage.cpp#line901

          I wonder if I can just do:

          @image->data_ptr()->own_data = true;@

          That should cause QImageData to delete the buffer when it destructs:

          http://qt.gitorious.org/qt/qt/blobs/4.7/src/gui/image/qimage.cpp#line263

          And that should happen when all QImage's that share the data have destructed.

          1 Reply Last reply
          0
          • M Offline
            M Offline
            mbarclaygmail.com
            wrote on last edited by
            #5

            [quote author="MattB" date="1332256874"]
            I wonder if I can just do:

            @image->data_ptr()->own_data = true;@
            [/quote]

            Heh, no I can't. That's not part of the Qt API (defined in qimage_p.h). Better drink some more coffee... :)

            1 Reply Last reply
            0
            • M Offline
              M Offline
              mbarclaygmail.com
              wrote on last edited by
              #6

              OK, looks like I found a solution:

              @MyQImage MyProvider::requestImage(QString id, QSize *size, QSize requestedSize) {
              ...
              ...

              // Let's pretend this creates an 800x600 Image buffer
              uchar* data = generateSomeImageData();
              
              QImage *source = new QImage(data, 800, 600, QImage::Format_ARGB32);
              QImage image(800, 600, QImage::Format_ARGB32);
              QPainter painter(&image);
              painter.drawImage(QPoint(0,0), *source);
              
              delete source;
              delete data;
              
              return image;
              

              }
              @

              My memory profile looks correct using this solution.

              1 Reply Last reply
              0
              • L Offline
                L Offline
                lgeyer
                wrote on last edited by
                #7

                Well, that's cheap ;-) I thought that's exactly the behaviour you want to prevent - having an additional buffer - and you want to re-use the already existing buffer.

                If you just want to construct a QImage from some binary data use QImage::fromData() instead.

                [quote author="MattB" date="1332256874"]And that should happen when all QImage's that share the data have destructed.
                [/quote]
                Use QImage::isDetached() when deconstructing a QImage to find out if its buffer is still shared with another instance or if it is safe to delete the buffer.

                1 Reply Last reply
                0
                • M Offline
                  M Offline
                  mbarclaygmail.com
                  wrote on last edited by
                  #8

                  Ideally, yes, I would avoid the buffer copy, but QImage::fromData() wants a buffer in one of the formats specified by QImageReader::supportedImageFormats() . None of those formats worked with my data, so I'm stuck with the QPainter approach.

                  N 1 Reply Last reply
                  0
                  • M mbarclaygmail.com

                    Ideally, yes, I would avoid the buffer copy, but QImage::fromData() wants a buffer in one of the formats specified by QImageReader::supportedImageFormats() . None of those formats worked with my data, so I'm stuck with the QPainter approach.

                    N Offline
                    N Offline
                    Numerator
                    wrote on last edited by Numerator
                    #9

                    @mbarclaygmail-com In Qt5 QImage has a clean up function.

                    You can provide a function pointer cleanupFunction along with an extra pointer cleanupInfo that will be called when the last copy is destroyed.

                    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