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. Connecting QQuickImageProvider
QtWS25 Last Chance

Connecting QQuickImageProvider

Scheduled Pinned Locked Moved Solved QML and Qt Quick
15 Posts 2 Posters 4.8k 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.
  • guidupasG Offline
    guidupasG Offline
    guidupas
    wrote on last edited by
    #1

    Hello all!

    I have to connect a QQuickImageProvider with a class to pass an image that the image provider must return, but I am not finding a way to do that. Could someone help me?

    Code below

    main.cpp

    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
    
    #include <QtQml>
    
    #include "processaimagem.h"
    #include "provedorimagem.h"
    
    int main(int argc, char *argv[])
    {
        QGuiApplication app(argc, argv);
    
        qmlRegisterType<processaImagem>("ProcessaImagemQml", 1, 0, "ProcessaImagem");
    
        QQmlApplicationEngine engine;
    
        provedorImagem *provedorImg = new provedorImagem;
    
        //------------  I have to create a connection here between the provider slot and a signal in processaImagem with the image to provide  -----------------
    
        engine.addImageProvider("provedor", provedorImg);
    
        engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    
        return app.exec();
    }
    

    processaImagem.h

    #ifndef PROCESSAIMAGEM_H
    #define PROCESSAIMAGEM_H
    
    #include <QObject>
    #include <QImage>
    #include <QQmlEngine>
    #include <QQmlContext>
    #include <QQuickImageProvider>
    
    #include "provedorimagem.h"
    
    class processaImagem : public QObject
    {
        Q_OBJECT
    
    public slots:
        QString recebeImagem(const QString &caminho);
    
    public:
        processaImagem(QObject *parent = 0);
    
        QImage carregaImagem(const QString &caminho);
    
    signals:
        void enviaImagem(QImage);
    };
    
    #endif // PROCESSAIMAGEM_H
    

    processaImagem.cpp

    #include "processaimagem.h"
    
    #include <QDebug>
    
    processaImagem::processaImagem(QObject *parent)
    {
    
    }
    
    QString processaImagem::recebeImagem(const QString &caminho)
    {
        QImage imagem = this->carregaImagem(caminho);
    
        QString caminhoRetorno;
    
        if(imagem.isNull())
        {
            qDebug() << "Erro ao receber a imagem";
        }
        else
        {
            qDebug() << "Imagem recebida";
            caminhoRetorno = "image://provedor/imagemEditada";
        }
    
        return caminhoRetorno;
    }
    
    QImage processaImagem::carregaImagem(const QString &caminho)
    {
        QUrl caminhoImagem(caminho);
        QQmlEngine *engine = QQmlEngine::contextForObject(this)->engine();
        QQmlImageProviderBase *imageProviderBase = engine->imageProvider(caminhoImagem.host());
        QQuickImageProvider *imageProvider = static_cast<QQuickImageProvider*>(imageProviderBase);
    
        QSize imageSize;
        QString imageId = caminhoImagem.path().remove(0, 1);
        QImage imagem = imageProvider->requestImage(imageId, &imageSize, imageSize);
    
        if(imagem.isNull())
        {
            qDebug() << "Erro ao carregar a imagem";
            imagem = QImage();
        }
        else
        {
            qDebug() << "Imagem carregada";
        }
    
        return imagem;
    }
    

    provedorimagem.h

    #ifndef PROVEDORIMAGEM_H
    #define PROVEDORIMAGEM_H
    
    #include <QImage>
    #include <QQuickImageProvider>
    
    class provedorImagem : public QQuickImageProvider
    {
    public:
        provedorImagem();
    
        QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize);
    
        void carregaImagem();
    
    public slots:
        void carregaImagem(QImage imagemRecebida);
    
    private:
        QImage imagem;
    };
    
    #endif // PROVEDORIMAGEM_H
    

    provedorimagem.cpp

    #include "provedorimagem.h"
    
    #include <QDebug>
    
    provedorImagem::provedorImagem() : QQuickImageProvider(QQuickImageProvider::Image)
    {
    
    }
    
    QImage provedorImagem::requestImage(const QString &id, QSize *size, const QSize &requestedSize)
    {
        if(imagem.isNull())
        {
            qDebug() << "Erro ao prover a imagem";
        }
        else
        {
            qDebug() << "Imagem provida";
        }
    
        return imagem;
    }
    
    void provedorImagem::carregaImagem(QImage imagemRecebida)
    {
        imagem = imagemRecebida;
    }
    

    Att.
    Guilherme Cortada Dupas

    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi,

      Why not just emit a signal from the provider and connect it to whatever class you need ?

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      0
      • guidupasG Offline
        guidupasG Offline
        guidupas
        wrote on last edited by
        #3

        @SGaist Hello. Thanks for the reply.

        Because what I need is a slot in the provider to receive an QImage and return it from the provider to QML.

        Att.
        Guilherme Cortada Dupas

        1 Reply Last reply
        0
        • SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote on last edited by
          #4

          Can you describe your use case ?

          Interested in AI ? www.idiap.ch
          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

          1 Reply Last reply
          0
          • guidupasG Offline
            guidupasG Offline
            guidupas
            wrote on last edited by
            #5

            Answering my own question
            Problem solved. Here is the solution step by step:

            1 - Create a class that inherits from QQuickImageProvider and QObject and inside it create a Image member (QImage) that is the image to be provided.

            class provedorImagem : public QObject, public QQuickImageProvider
            

            Implement the virtual requestImage method. This is the method that will return the image to Qml

            QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize)
            

            Create a method to load the provider’s image to return

            void provedorImagem::carregaImagem(QImage imagemRecebida)
            {
                imagem = imagemRecebida;
            }
            

            Now set it as the engine image provider in the main.cpp file

            provedorImagem *provedorImg = new provedorImagem;
            engine.rootContext()->setContextProperty("ProvedorImagem", provedorImg);
            

            2 - Create another class that inherits from QObject.

            class processaImagem : public QObject
            

            Inside this class you must implement a method that will get the image from camera provider, perform the image modifications and return the modified image.
            PS: The p_caminhoImagem is a property that I created inside the processaImagem class that receives the camera preview path.

            QImage processaImagem::carregaImagem()
            {
                QUrl caminhoImagem(p_caminhoImagem);
                QQmlEngine *engine = QQmlEngine::contextForObject(this)->engine();
                QQmlImageProviderBase *imageProviderBase = engine->imageProvider(caminhoImagem.host());
                QQuickImageProvider *imageProvider = static_cast<QQuickImageProvider*>(imageProviderBase);
            
            
                QSize imageSize;
                QString imageId = caminhoImagem.path().remove(0, 1);
                QImage imagem = imageProvider->requestImage(imageId, &imageSize, imageSize);
            
                if(imagem.isNull())
                {
                    imagem = QImage();
                }
                else
                {
                    //Perform the modifications
                }
            
                return imagem;
            }
            

            3 - Now is the main part. The image requestImage provider method must receive the modified image from the processaImagem class to provide it to QML. To do it the provider class pointer must be accessible to the QML file, so, in the main.cpp file just make the pointer available to QML as a property

            engine.rootContext()->setContextProperty("ProvedorImagem", provedorImg);
            

            and register the processaImagem class as a QML type

            qmlRegisterType<processaImagem>("ProcessaImagemQml", 1, 0, "ProcessaImagem");
            

            Now we link it inside the QML file

            ProvedorImagem.carregaImagem(processaImagem.carregaImagem());
            

            4 - It is done. Now just request the image from the provider:

            imagemPreview.source = "image://provedor/imagemEditada_" + camera.numeroImagem.toString();
            

            Att.
            Guilherme Cortada Dupas

            1 Reply Last reply
            0
            • SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on last edited by
              #6

              But why not do the processing directly in the image provider ?

              Interested in AI ? www.idiap.ch
              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

              1 Reply Last reply
              0
              • guidupasG Offline
                guidupasG Offline
                guidupas
                wrote on last edited by
                #7

                Can be done directly in the image provider, but it still needs to have a class to send the image to the image provider.

                Att.
                Guilherme Cortada Dupas

                1 Reply Last reply
                0
                • SGaistS Offline
                  SGaistS Offline
                  SGaist
                  Lifetime Qt Champion
                  wrote on last edited by
                  #8

                  Why not grab the image in the image provider ?

                  Interested in AI ? www.idiap.ch
                  Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                  1 Reply Last reply
                  0
                  • guidupasG Offline
                    guidupasG Offline
                    guidupas
                    wrote on last edited by
                    #9

                    @SGaist How?

                    Att.
                    Guilherme Cortada Dupas

                    1 Reply Last reply
                    0
                    • SGaistS Offline
                      SGaistS Offline
                      SGaist
                      Lifetime Qt Champion
                      wrote on last edited by
                      #10

                      Unless I'm mistaken all what your processaImagem does is get the image from the image provider, apply some modification and set it again on the image provider, right ?

                      Interested in AI ? www.idiap.ch
                      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                      1 Reply Last reply
                      0
                      • guidupasG Offline
                        guidupasG Offline
                        guidupas
                        wrote on last edited by
                        #11

                        Yes, but are the camera image provider and my own image provider the same?

                        Att.
                        Guilherme Cortada Dupas

                        1 Reply Last reply
                        0
                        • SGaistS Offline
                          SGaistS Offline
                          SGaist
                          Lifetime Qt Champion
                          wrote on last edited by
                          #12

                          Are you using the Camera QML type to grab the image from the camera ?

                          Interested in AI ? www.idiap.ch
                          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                          1 Reply Last reply
                          0
                          • guidupasG Offline
                            guidupasG Offline
                            guidupas
                            wrote on last edited by
                            #13

                            Yes, and after that I am performing some modifications and return a square image.

                            Att.
                            Guilherme Cortada Dupas

                            1 Reply Last reply
                            0
                            • SGaistS Offline
                              SGaistS Offline
                              SGaist
                              Lifetime Qt Champion
                              wrote on last edited by
                              #14

                              In that case, why not use a ShaderEffect to "cut" your image square ?

                              Interested in AI ? www.idiap.ch
                              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                              1 Reply Last reply
                              0
                              • guidupasG Offline
                                guidupasG Offline
                                guidupas
                                wrote on last edited by
                                #15

                                @SGaist
                                Because I didnt know that ShaderEffect can "cut" an image. I read the documentation and I could not find how to do it with ShaderEffect.

                                Now I am interested about how to perform the image modifications directly in the provider. How can I pass the image without other class to do it?

                                Another thing, the modifications performed in the image include rotate the image in case of wrong image orientation.

                                Att.
                                Guilherme Cortada Dupas

                                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