Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    [SOLVED] QDeclarativeImageProvider and memory leaks with QImage

    QML and Qt Quick
    4
    9
    4992
    Loading More Posts
    • 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
      mbarclaygmail.com last edited by

      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 Reply Quote 0
      • T
        task_struct last edited by

        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 Reply Quote 0
        • L
          lgeyer last edited by

          [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 Reply Quote 0
          • M
            mbarclaygmail.com last edited by

            [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 Reply Quote 0
            • M
              mbarclaygmail.com last edited by

              [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 Reply Quote 0
              • M
                mbarclaygmail.com last edited by

                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 Reply Quote 0
                • L
                  lgeyer last edited by

                  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 Reply Quote 0
                  • M
                    mbarclaygmail.com last edited by

                    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 Reply Quote 0
                    • N
                      Numerator @mbarclaygmail.com last edited by Numerator

                      @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 Reply Quote 0
                      • First post
                        Last post