c++ - How to correctly use Qt QML Image Provider -


i developing cross-platform application receives images via rest api on c++ side , sends them qml via imageprovider, seems causing memory leaks. speed @ memory leaks proportional size of image , update interval.

i tried disabling caching of qml image did not change thing. tried forcing garbage collection running gc() on image updates still no luck.

to sure not caused bad coding, etc. have created minimal demo, based on qt example: http://doc.qt.io/qt-5/qquickimageprovider.html

the addition have increased image sizes , implemented means of swapping red coloured image yellow coloured image. once run application image change colour every second , memory keep increasing. image has 10000x10000 dimension such can see increase clearly. if image 10x10 or other size memory leak still occurs.

i have managed replicate problem on android phone, macbook pc running fedora.

please let me know if see reason why occurring , if bug workaround can use send images qml. need send these images received via rest api around 30fps.

any appreciated! complete solution below. both image , pixmap providers cause same issue. if want test original qt code change qquickimageprovider::image qquickimageprovider::pixmap in main.cpp.

main.cpp

#include <qguiapplication> #include <qqmlapplicationengine> #include <qqmlcomponent> #include <qthread>  #include "imageprovider.h"  class mythread : public qthread { public:     mythread(qobject* object) : m_object(object)     {     }      virtual void run()     {         qvariant colour = "red";          while (isrunning())         {             qmetaobject::invokemethod(                 m_object, "updateviewport", q_arg(qvariant, colour));              if (colour == "red")             {                 colour = "yellow";             }             else             {                 colour = "red";             }              qthread::sleep(1);         }     }  private:     qobject* m_object; };  int main(int argc, char* argv[]) {     qcoreapplication::setattribute(qt::aa_enablehighdpiscaling);     qguiapplication app(argc, argv);      qqmlapplicationengine engine;     engine.addimageprovider(qlatin1string("imageprovider"),                             new imageprovider(qquickimageprovider::image));     qqmlcomponent component(&engine, "qrc:/main.qml");     qobject* object = component.create();     mythread* mythread = new mythread(object);     mythread->start();      return app.exec(); } 

imageprovider.h

#ifndef image_provider_h #define image_provider_h  #include <qquickimageprovider> #include <qpixmap> #include <qpainter>  class imageprovider : public qobject, public qquickimageprovider {     q_object public:     explicit imageprovider(imagetype type, flags flags = 0);     qpixmap requestpixmap(const qstring& id,                           qsize* size,                           const qsize& requestedsize);     qimage requestimage(const qstring& id,                         qsize* size,                         const qsize& requestedsize); }; #endif // image_provider_h 

imageprovider.cpp

#include "imageprovider.h"  using namespace std;  imageprovider::imageprovider(imagetype type, flags flags)     : qquickimageprovider(type, flags) { }  qpixmap imageprovider::requestpixmap(const qstring& id,                                      qsize* size,                                      const qsize& requestedsize) {     int width = 10000;     int height = 10000;      if (size)     {         *size = qsize(width, height);     }      qpixmap pixmap(requestedsize.width() > 0 ? requestedsize.width() : width,                    requestedsize.height() > 0 ? requestedsize.height() :                                                 height);     pixmap.fill(qcolor(id).rgba());     qpainter painter(&pixmap);     qfont f = painter.font();     f.setpixelsize(20);     painter.setfont(f);     painter.setpen(qt::black);     if (requestedsize.isvalid())         painter.scale(requestedsize.width() / width,                       requestedsize.height() / height);     painter.drawtext(qrectf(0, 0, width, height), qt::aligncenter, id);      return pixmap; }  qimage imageprovider::requestimage(const qstring& id,                                    qsize* size,                                    const qsize& requestedsize) {     return qimage(10000, 10000, qimage::format_argb32); } 

main.qml

import qtquick 2.7 import qtquick.controls 2.0 import qtquick.layouts 1.3  applicationwindow {     visible: true     width: 640     height: 480     title: qstr("memoryleakdemo")      function updateviewport(colour) {         image.source = "image://imageprovider/" + colour;     }      image {         id: image         cache: false     } } 

memoryleakdemo.pro

qt += qml quick  config += c++11  sources += main.cpp \     imageprovider.cpp  resources += qml.qrc  defines += qt_deprecated_warnings  qnx: target.path = /tmp/$${target}/bin else: unix:!android: target.path = /opt/$${target}/bin !isempty(target.path): installs += target  headers += imageprovider.h 

qt has confirmed bug fixed soon:

https://bugreports.qt.io/browse/qtbug-62600

in meantime, try apply te patches , compile framework source:

https://codereview.qt-project.org/#/c/200715/

hope helps!


Comments

Popular posts from this blog

Is there a better way to structure post methods in Class Based Views -

performance - Why is XCHG reg, reg a 3 micro-op instruction on modern Intel architectures? -

jquery - Responsive Navbar with Sub Navbar -