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. Qml ImageProvider & crashes

Qml ImageProvider & crashes

Scheduled Pinned Locked Moved Solved QML and Qt Quick
4 Posts 3 Posters 1.6k 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.
  • J.HilkJ Offline
    J.HilkJ Offline
    J.Hilk
    Moderators
    wrote on last edited by
    #1

    Hi everyone,

    I'm currently broadening my Qt knowledge of QML.

    For that purpose, I created a simple program. On QML side, a Window with a single Image in it and a cpp backend, that loads/creates images.

    To pass the cpp-QImages to QML I need my own ImageProvider class, derived from QQuickImageProvider, thats at least what the docs say.

    And it works, I'm able to pass images from cpp to qml, BUT when I close the program, it crashes.

    Heres the ImageProvider class

    #ifndef SPIMAGEPROVIDER_H
    #define SPIMAGEPROVIDER_H
    
    #include <QObject>
    #include <QImage>
    #include <QQuickImageProvider>
    
    class SpImageProvider : public QObject, public QQuickImageProvider
    {
        Q_OBJECT
    public:
        SpImageProvider();
    
        QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize) override;
    
    public slots:
        void updateImage(const QImage &image);
    
    signals:
        void imageChanged();
    
    private:
        QImage image;
        QImage no_image;
    };
    
    #endif // SPIMAGEPROVIDER_H
    
    #include "spimageprovider.h"
    
    SpImageProvider::SpImageProvider() : QQuickImageProvider(QQuickImageProvider::Image)
    {
        no_image = QImage(200,200,QImage::Format_RGB32);
        no_image.fill(QColor("black"));
    }
    
    QImage SpImageProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize)
    {
        Q_UNUSED(id);
    
        if(image.isNull())
            image = no_image;
    
        if(size){
            *size = image.size();
        }
    
        if(requestedSize.width() > 0 && requestedSize.height() > 0) {
            image = image.scaled(requestedSize.width(), requestedSize.height(), Qt::KeepAspectRatio);
        }
        return image;
    }
    
    void SpImageProvider::updateImage(const QImage &image)
    {
        if(this->image != image) {
            this->image = image;
            emit imageChanged();
        }
    }
    

    the main consists of this

    int main(int argc, char *argv[])
    {
        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    
        QGuiApplication app(argc, argv);
    
        SpImageProvider liveImageProvider;
    
        QQmlApplicationEngine engine;
        engine.addImageProvider("live", &liveImageProvider);
        engine.load(QUrl(QLatin1String("qrc:/main.qml")));
    
        if (engine.rootObjects().isEmpty())
            return -1;
    
        return app.exec();
    }
    

    Crashlog
    0_1529645057272_d224ba3b-be79-4866-93a0-cfce6b8f6414-image.png
    0_1529645093503_313acdd8-36ad-4c32-a595-198294e9aaae-image.png

    0_1529645124986_5e75d258-ecc7-4fb8-a304-ee5f60ca1ef1-image.png

    if i do not add the image provider to the engine, the program does not crash on exit
    engine.addImageProvider("live", &liveImageProvider);

    Am I Missing something in my code, or is this a bug I should report?

    Greetings


    Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


    Q: What's that?
    A: It's blue light.
    Q: What does it do?
    A: It turns blue.

    raven-worxR 1 Reply Last reply
    0
    • sierdzioS Offline
      sierdzioS Offline
      sierdzio
      Moderators
      wrote on last edited by
      #2

      @J.Hilk said in Qml ImageProvider & crashes:

      To pass the cpp-QImages to QML I need my own ImageProvider class, derived from QQuickImageProvider, thats at least what the docs say

      You can pass image paths to QML and then no ImageProvider is necessary.

      Regarding the crash: why do you set up the SpImageProvider as QObject? And why it is not being initialized in your constructor?

      (Z(:^

      1 Reply Last reply
      1
      • J.HilkJ J.Hilk

        Hi everyone,

        I'm currently broadening my Qt knowledge of QML.

        For that purpose, I created a simple program. On QML side, a Window with a single Image in it and a cpp backend, that loads/creates images.

        To pass the cpp-QImages to QML I need my own ImageProvider class, derived from QQuickImageProvider, thats at least what the docs say.

        And it works, I'm able to pass images from cpp to qml, BUT when I close the program, it crashes.

        Heres the ImageProvider class

        #ifndef SPIMAGEPROVIDER_H
        #define SPIMAGEPROVIDER_H
        
        #include <QObject>
        #include <QImage>
        #include <QQuickImageProvider>
        
        class SpImageProvider : public QObject, public QQuickImageProvider
        {
            Q_OBJECT
        public:
            SpImageProvider();
        
            QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize) override;
        
        public slots:
            void updateImage(const QImage &image);
        
        signals:
            void imageChanged();
        
        private:
            QImage image;
            QImage no_image;
        };
        
        #endif // SPIMAGEPROVIDER_H
        
        #include "spimageprovider.h"
        
        SpImageProvider::SpImageProvider() : QQuickImageProvider(QQuickImageProvider::Image)
        {
            no_image = QImage(200,200,QImage::Format_RGB32);
            no_image.fill(QColor("black"));
        }
        
        QImage SpImageProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize)
        {
            Q_UNUSED(id);
        
            if(image.isNull())
                image = no_image;
        
            if(size){
                *size = image.size();
            }
        
            if(requestedSize.width() > 0 && requestedSize.height() > 0) {
                image = image.scaled(requestedSize.width(), requestedSize.height(), Qt::KeepAspectRatio);
            }
            return image;
        }
        
        void SpImageProvider::updateImage(const QImage &image)
        {
            if(this->image != image) {
                this->image = image;
                emit imageChanged();
            }
        }
        

        the main consists of this

        int main(int argc, char *argv[])
        {
            QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
        
            QGuiApplication app(argc, argv);
        
            SpImageProvider liveImageProvider;
        
            QQmlApplicationEngine engine;
            engine.addImageProvider("live", &liveImageProvider);
            engine.load(QUrl(QLatin1String("qrc:/main.qml")));
        
            if (engine.rootObjects().isEmpty())
                return -1;
        
            return app.exec();
        }
        

        Crashlog
        0_1529645057272_d224ba3b-be79-4866-93a0-cfce6b8f6414-image.png
        0_1529645093503_313acdd8-36ad-4c32-a595-198294e9aaae-image.png

        0_1529645124986_5e75d258-ecc7-4fb8-a304-ee5f60ca1ef1-image.png

        if i do not add the image provider to the engine, the program does not crash on exit
        engine.addImageProvider("live", &liveImageProvider);

        Am I Missing something in my code, or is this a bug I should report?

        Greetings

        raven-worxR Offline
        raven-worxR Offline
        raven-worx
        Moderators
        wrote on last edited by
        #3

        @J.Hilk
        i guess you are not supposed to create the image provider instance on the stack.
        Probably the QQmlEngine already deletes it and then it crashes when the runtime tries to delete it again when it goes out of scope.
        So try:

        engine.addImageProvider("live", new SpImageProvider );
        

        --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
        If you have a question please use the forum so others can benefit from the solution in the future

        J.HilkJ 1 Reply Last reply
        1
        • raven-worxR raven-worx

          @J.Hilk
          i guess you are not supposed to create the image provider instance on the stack.
          Probably the QQmlEngine already deletes it and then it crashes when the runtime tries to delete it again when it goes out of scope.
          So try:

          engine.addImageProvider("live", new SpImageProvider );
          
          J.HilkJ Offline
          J.HilkJ Offline
          J.Hilk
          Moderators
          wrote on last edited by J.Hilk
          #4

          @raven-worx

          You're right, that is indeed the problem, originally I had it created on the heap, but wraped in a QScopedPointer which also results in a crash.

          But with a simple

          SpImageProvider *liveImageProvider(new SpImageProvider());
          engine.addImageProvider("live", liveImageProvider);
          

          it works fine.

          Seriously frustrating issue 😒

          @sierdzio said in Qml ImageProvider & crashes:

          @J.Hilk said in Qml ImageProvider & crashes:

          To pass the cpp-QImages to QML I need my own ImageProvider class, derived from QQuickImageProvider, thats at least what the docs say

          You can pass image paths to QML and then no ImageProvider is necessary.

          Regarding the crash: why do you set up the SpImageProvider as QObject? And why it is not being initialized in your constructor?

          I know that, but the goal is to do some image manipulation after loading and than passing it along to the QML part to display it.

          why do you set up the SpImageProvider as QObject

          The image loader/processor and the image provider are each their own instance inside main and to pass new images from the loader/processor to the provider I connect them via Signal/Slot -> QObject inherritence requiered

          And why it is not being initialized in your constructor?

          True, I should look into that/fix it :)


          Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


          Q: What's that?
          A: It's blue light.
          Q: What does it do?
          A: It turns blue.

          1 Reply Last reply
          0
          • B bidjiz referenced this topic on

          • Login

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