Qml ImageProvider & crashes



  • 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


  • Moderators

    @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?


  • Moderators

    @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 );
    


  • @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 :)


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.