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. [SOLVED] QML Camera - take a Square photo
Forum Updated to NodeBB v4.3 + New Features

[SOLVED] QML Camera - take a Square photo

Scheduled Pinned Locked Moved QML and Qt Quick
26 Posts 2 Posters 9.4k Views 2 Watching
  • 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 guidupas

    @p3c0 Hello!

    The problem is exactly that, all my attempts to make the image available for the image provider fail. I have tried using a Q_PROPERTY and a QImage member inside the class, but my provider always returns a null image when I try to access it to return.

    p3c0P Offline
    p3c0P Offline
    p3c0
    Moderators
    wrote on last edited by
    #16

    @guidupas But you already have the QImage (as per this error Error: Cannot assign QImage to QUrl in class manipulaImagem) as well as QQuickImageProvider instance. Is it not possible to send the image using this instance ?

    157

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

      @p3c0 I thing it can be possible but I am not figuring out how. Take a look at this code and I think you will understand what I am talking about.

      .h

      #ifndef MANIPULAIMAGEM_H
      #define MANIPULAIMAGEM_H
      
      #include <QObject>
      #include <QImage>
      #include <QQuickImageProvider>
      #include <QQmlEngine>
      #include <QQmlContext>
      
      class manipulaImagem : public QObject, public QQuickImageProvider
      {
          Q_OBJECT
      
      public slots:
          QString recortarFotoPerfil(const QString &imagem, QRect rectRecorte);
      
      public:
          manipulaImagem(QObject *parent = 0);
      
          QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize);
      
      private:
          void alocaImagem(const QString &imagem, QRect rectRecorte);
      
          QImage imagemEditada;
      };
      
      #endif // MANIPULAIMAGEM_H
      
      

      .cpp

      #include "manipulaimagem.h"
      
      #include <QDebug>
      
      manipulaImagem::manipulaImagem(QObject *parent) : QQuickImageProvider(QQmlImageProviderBase::Image)
      {
      
      }
      
      QImage manipulaImagem::requestImage(const QString &id, QSize *size, const QSize &requestedSize)
      {
          if(imagemEditada.isNull())
          {
              qDebug() << "Request image: (image is null)";
          }
          else
          {
              qDebug() << "Request image: image is OK";
          }
      
          return imagemEditada;
      }
      
      void manipulaImagem::alocaImagem(const QString &imagem, QRect rectRecorte)
      {
          QUrl caminhoImagem(imagem);
          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);
          imagemEditada = imageProvider->requestImage(imageId, &imageSize, imageSize);
      
          if(imagemEditada.isNull())
          {
              qDebug() << "Loading image failed";
          }
          else
          {
              qDebug() << "Loading image OK";
          }
      }
      
      QString manipulaImagem::recortarFotoPerfil(const QString &imagem, QRect rectRecorte)
      {
          this->alocaImagem(imagem, rectRecorte);
      
          QString a = "image://ProvedorImagens/imagemEditada";
      
          if(imagemEditada.isNull())
          {
              qDebug() << "Imagem is null";
          }
          else
          {
              qDebug() << "Imagem is loaded";
          }
      
          return a;
      }
      

      .qml

      ManipulaImagem {
              id: manipulaImagem
      }
      
      Camera {
                      id: camera
      
                      captureMode: Camera.CaptureStillImage
      
                      imageCapture {
                          onImageCaptured: {
                              previewImage.source = manipulaImagem.recortarFotoPerfil(preview, viewfinder.mapRectToSource(Qt.rect(viewfinder.x, viewfinder.y, viewfinder.width, viewfinder.height)));
                          }
                      }
                  }
      
      Rectangle {
              id: previewRectangle
      
              visible: false
      
              anchors.fill: parent
      
              Image {
                  id: previewImage
      
                  fillMode: Image.PreserveAspectFit
                  
                  anchors.top: parent.top
      
                  width: parent.width
                  height: parent.width
              }
          }
      

      Now take a look at the output:

      Loading image OK
      Imagem is loaded
      Request image: (image is null)
      QML Image: Failed to get image from provider: image://provedorimagens/imagemEditada

      How you can see when I call the functions the image is not null, but when I try to return the QImage using the provider it cant return the image. I dont know why but for the image provider the image is null.

      Att.
      Guilherme Cortada Dupas

      p3c0P 1 Reply Last reply
      0
      • guidupasG guidupas

        @p3c0 I thing it can be possible but I am not figuring out how. Take a look at this code and I think you will understand what I am talking about.

        .h

        #ifndef MANIPULAIMAGEM_H
        #define MANIPULAIMAGEM_H
        
        #include <QObject>
        #include <QImage>
        #include <QQuickImageProvider>
        #include <QQmlEngine>
        #include <QQmlContext>
        
        class manipulaImagem : public QObject, public QQuickImageProvider
        {
            Q_OBJECT
        
        public slots:
            QString recortarFotoPerfil(const QString &imagem, QRect rectRecorte);
        
        public:
            manipulaImagem(QObject *parent = 0);
        
            QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize);
        
        private:
            void alocaImagem(const QString &imagem, QRect rectRecorte);
        
            QImage imagemEditada;
        };
        
        #endif // MANIPULAIMAGEM_H
        
        

        .cpp

        #include "manipulaimagem.h"
        
        #include <QDebug>
        
        manipulaImagem::manipulaImagem(QObject *parent) : QQuickImageProvider(QQmlImageProviderBase::Image)
        {
        
        }
        
        QImage manipulaImagem::requestImage(const QString &id, QSize *size, const QSize &requestedSize)
        {
            if(imagemEditada.isNull())
            {
                qDebug() << "Request image: (image is null)";
            }
            else
            {
                qDebug() << "Request image: image is OK";
            }
        
            return imagemEditada;
        }
        
        void manipulaImagem::alocaImagem(const QString &imagem, QRect rectRecorte)
        {
            QUrl caminhoImagem(imagem);
            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);
            imagemEditada = imageProvider->requestImage(imageId, &imageSize, imageSize);
        
            if(imagemEditada.isNull())
            {
                qDebug() << "Loading image failed";
            }
            else
            {
                qDebug() << "Loading image OK";
            }
        }
        
        QString manipulaImagem::recortarFotoPerfil(const QString &imagem, QRect rectRecorte)
        {
            this->alocaImagem(imagem, rectRecorte);
        
            QString a = "image://ProvedorImagens/imagemEditada";
        
            if(imagemEditada.isNull())
            {
                qDebug() << "Imagem is null";
            }
            else
            {
                qDebug() << "Imagem is loaded";
            }
        
            return a;
        }
        

        .qml

        ManipulaImagem {
                id: manipulaImagem
        }
        
        Camera {
                        id: camera
        
                        captureMode: Camera.CaptureStillImage
        
                        imageCapture {
                            onImageCaptured: {
                                previewImage.source = manipulaImagem.recortarFotoPerfil(preview, viewfinder.mapRectToSource(Qt.rect(viewfinder.x, viewfinder.y, viewfinder.width, viewfinder.height)));
                            }
                        }
                    }
        
        Rectangle {
                id: previewRectangle
        
                visible: false
        
                anchors.fill: parent
        
                Image {
                    id: previewImage
        
                    fillMode: Image.PreserveAspectFit
                    
                    anchors.top: parent.top
        
                    width: parent.width
                    height: parent.width
                }
            }
        

        Now take a look at the output:

        Loading image OK
        Imagem is loaded
        Request image: (image is null)
        QML Image: Failed to get image from provider: image://provedorimagens/imagemEditada

        How you can see when I call the functions the image is not null, but when I try to return the QImage using the provider it cant return the image. I dont know why but for the image provider the image is null.

        p3c0P Offline
        p3c0P Offline
        p3c0
        Moderators
        wrote on last edited by p3c0
        #18

        @guidupas Strange.. According to the order of the execution of the code, imagemEditada should not be null when the image is requested by Image element. May be I'm too missing something.

        157

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

          @p3c0 I found the error. I am targeting the wrong pointer. Actually I need to connect the provider pointer im main.cpp and I am creating a new pointer to the provider.

          Att.
          Guilherme Cortada Dupas

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

            @p3c0 Could you take a look at this topic? I need some help to do exactly that connection between the provider pointer with a signal that send to it the QImage.
            https://forum.qt.io/topic/60383/connecting-qquickimageprovider

            Att.
            Guilherme Cortada Dupas

            1 Reply Last reply
            0
            • guidupasG guidupas

              @p3c0 I found the error. I am targeting the wrong pointer. Actually I need to connect the provider pointer im main.cpp and I am creating a new pointer to the provider.

              p3c0P Offline
              p3c0P Offline
              p3c0
              Moderators
              wrote on last edited by p3c0
              #21

              @guidupas said:

              @p3c0 I found the error. I am targeting the wrong pointer. Actually I need to connect the provider pointer im main.cpp and I am creating a new pointer to the provider.

              Well then pass the right pointer ?

              To use signals and slots you will need the right pointer too.

              157

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

                @p3c0 I found the right pointer. It is in the main.cpp
                Now, how can I connect a slot inside this pointer to a signal in processaImagem.cpp?
                main.cpp

                #include <QGuiApplication>
                #include <QQmlApplicationEngine>
                
                #include <QtQml>
                
                #include "manipulaxml.h"
                #include "caminhoimagens.h"
                #include "manipulaimagem.h"
                
                int main(int argc, char *argv[])
                {
                    QGuiApplication app(argc, argv);
                
                    qmlRegisterType<manipulaXml>("ManipXML", 1, 0, "ManipulaXML");
                    qmlRegisterType<caminhoImagens>("PathImagens", 1, 0, "CaminhoImagens");
                    qmlRegisterType<manipulaImagem>("ManipImagem", 1, 0, "ManipulaImagem");
                
                    QQmlApplicationEngine engine;
                
                    manipulaImagem *imageProvider = new manipulaImagem;
                    engine.addImageProvider("ProvedorImagens", imageProvider);
                
                    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
                
                    return app.exec();
                }
                

                Att.
                Guilherme Cortada Dupas

                p3c0P 1 Reply Last reply
                0
                • guidupasG guidupas

                  @p3c0 I found the right pointer. It is in the main.cpp
                  Now, how can I connect a slot inside this pointer to a signal in processaImagem.cpp?
                  main.cpp

                  #include <QGuiApplication>
                  #include <QQmlApplicationEngine>
                  
                  #include <QtQml>
                  
                  #include "manipulaxml.h"
                  #include "caminhoimagens.h"
                  #include "manipulaimagem.h"
                  
                  int main(int argc, char *argv[])
                  {
                      QGuiApplication app(argc, argv);
                  
                      qmlRegisterType<manipulaXml>("ManipXML", 1, 0, "ManipulaXML");
                      qmlRegisterType<caminhoImagens>("PathImagens", 1, 0, "CaminhoImagens");
                      qmlRegisterType<manipulaImagem>("ManipImagem", 1, 0, "ManipulaImagem");
                  
                      QQmlApplicationEngine engine;
                  
                      manipulaImagem *imageProvider = new manipulaImagem;
                      engine.addImageProvider("ProvedorImagens", imageProvider);
                  
                      engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
                  
                      return app.exec();
                  }
                  
                  p3c0P Offline
                  p3c0P Offline
                  p3c0
                  Moderators
                  wrote on last edited by
                  #23

                  @guidupas Don't register the manipulaImagem class. Instead set it as a context property too as you already have that instance.
                  manipulaImagem *imageProvider = new manipulaImagem
                  In this way you access the same instance from QML for both Image and as context property.

                  157

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

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

                    Here is the entire code:

                    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;
                    
                        engine.rootContext()->setContextProperty("ProvedorImagem", provedorImg);
                    
                        engine.addImageProvider("provedor", provedorImg);
                    
                        engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
                    
                        return app.exec();
                    }
                    

                    main.qml

                    import QtQuick 2.4
                    import QtQuick.Window 2.2
                    import QtQuick.Controls 1.3
                    import QtMultimedia 5.4
                    
                    import ProcessaImagemQml 1.0
                    
                    Window {
                        visible: true
                    
                        width: 360
                        height: 640
                    
                        maximumHeight: 640
                        minimumHeight: 640
                    
                        maximumWidth: 360
                        minimumWidth: 360
                    
                        title: "Camera Preview Test"
                    
                        Rectangle {
                            id: principal
                    
                            anchors.fill: parent
                    
                            ProcessaImagem {
                                id: processaImagem
                    
                                caminhoImagem: camera.caminhoPreview
                                caminhoSalvar: camera.caminhoSalvar
                                rectRecorte: camera.rectRecorte
                                tamanhoImagem: camera.tamanhoImagem
                                anguloOrientacaoCamera: camera.orientation
                                posicaoCamera: camera.position
                    
                                onCaminhoImagemChanged: {
                                    rectRecorte = cameraView.mapRectToSource(Qt.rect(cameraView.x, cameraView.y, cameraView.width, cameraView.height));
                                    tamanhoImagem = Qt.size(cameraView.sourceRect.width, cameraView.sourceRect.height);
                                    ProvedorImagem.carregaImagem(processaImagem.carregaImagem());
                                }
                    
                                onCaminhoSalvarChanged: {
                                    removeImagemSalva();
                                }
                            }
                    
                            Rectangle {
                                id: cameraRectangle
                    
                                width: parent.width
                                height: parent.width
                    
                                anchors.top: parent.top
                    
                                color: "lightGrey"
                    
                                visible: true
                    
                                Camera {
                                    id: camera
                    
                                    property string caminhoPreview: ""
                                    property string caminhoSalvar: ""
                                    property int numeroImagem: 0
                    
                                    captureMode: Camera.CaptureStillImage
                    
                                    imageCapture {
                                        onImageCaptured: {
                                            camera.caminhoPreview = preview;
                    
                                            camera.stop();
                    
                                            imagemPreview.source = "image://provedor/imagemEditada_" + camera.numeroImagem.toString();
                    
                                            camera.numeroImagem = camera.numeroImagem + 1;
                    
                                            imagemPreviewRectangle.visible = true;
                    
                                            cameraRectangle.visible = false;
                                        }
                    
                                        onImageSaved: {
                                            camera.caminhoSalvar = path;
                                        }
                                    }
                                }
                    
                                VideoOutput {
                                    id: cameraView
                    
                                    visible: true
                    
                                    focus: visible
                    
                                    anchors.fill: parent
                    
                                    source: camera
                                    orientation: camera.orientation
                                    fillMode: VideoOutput.PreserveAspectCrop
                                }
                            }
                    
                            Rectangle {
                                id: imagemPreviewRectangle
                    
                                width: parent.width
                                height: parent.width
                    
                                anchors.top: parent.top
                    
                                color: "lightGrey"
                    
                                visible: false
                    
                                Image {
                                    id: imagemPreview
                    
                                    fillMode: Image.PreserveAspectFit
                                    
                                    anchors.fill: parent
                                }
                            }
                    
                            Rectangle {
                                id: controleRectangle
                    
                                width: parent.width
                                height: parent.height - cameraRectangle.height
                    
                                color: "grey"
                    
                                anchors.top: cameraRectangle.bottom
                    
                                Button {
                                    id: tirarFotoButton
                    
                                    text: "Tirar foto"
                    
                                    anchors.left: parent.left
                                    anchors.top: parent.top
                    
                                    onClicked: {
                                        camera.imageCapture.capture();
                                    }
                                }
                    
                                Button {
                                    id: novaFotoButton
                    
                                    text: "Tirar nova foto"
                    
                                    anchors.right: parent.right
                                    anchors.top: parent.top
                    
                                    onClicked: {
                                        camera.start();
                    
                                        imagemPreviewRectangle.visible = false;
                    
                                        cameraRectangle.visible = true;
                                    }
                                }
                            }
                        }
                    }
                    

                    processaimagem.h

                    #ifndef PROCESSAIMAGEM_H
                    #define PROCESSAIMAGEM_H
                    
                    #include <QObject>
                    #include <QImage>
                    #include <QQmlEngine>
                    #include <QQmlContext>
                    #include <QQuickImageProvider>
                    #include <QFile>
                    
                    #include "provedorimagem.h"
                    
                    class processaImagem : public QObject
                    {
                        Q_OBJECT
                    
                        Q_PROPERTY(QString caminhoImagem READ caminhoImagem WRITE setCaminhoImagem NOTIFY caminhoImagemChanged)
                        Q_PROPERTY(QString caminhoSalvar READ caminhoSalvar WRITE setCaminhoSalvar NOTIFY caminhoSalvarChanged)
                        Q_PROPERTY(QRect rectRecorte READ rectRecorte WRITE setRectRecorte NOTIFY rectRecorteChanged)
                        Q_PROPERTY(QSize tamanhoImagem READ tamanhoImagem WRITE setTamanhoImagem NOTIFY tamanhoImagemChanged)
                        Q_PROPERTY(int anguloOrientacaoCamera READ anguloOrientacaoCamera WRITE setAnguloOrientacaoCamera NOTIFY anguloOrientacaoCameraChanged)
                        Q_PROPERTY(int posicaoCamera READ posicaoCamera WRITE setPosicaoCamera NOTIFY posicaoCameraChanged)
                    
                    public slots:
                        QImage carregaImagem();
                        void removeImagemSalva();
                    
                    public:
                        processaImagem(QObject *parent = 0);
                    
                        QString caminhoImagem() const;
                        void setCaminhoImagem(const QString valor);
                    
                        QString caminhoSalvar() const;
                        void setCaminhoSalvar(const QString valor);
                    
                        QRect rectRecorte() const;
                        void setRectRecorte(const QRect valor);
                    
                        QSize tamanhoImagem() const;
                        void setTamanhoImagem(const QSize valor);
                    
                        int anguloOrientacaoCamera() const;
                        void setAnguloOrientacaoCamera(const int valor);
                    
                        int posicaoCamera() const;
                        void setPosicaoCamera(const int valor);
                    
                    private:
                        QString p_caminhoImagem = "";
                        QString p_caminhoSalvar = "";
                        QRect p_rectRecorte = QRect(0, 0, 0, 0);
                        QSize p_tamanhoImagem = QSize(0, 0);
                        int p_anguloOrientacaoCamera = 0;
                        int p_posicaoCamera = 0;
                    
                    signals:
                        void caminhoImagemChanged();
                        void caminhoSalvarChanged();
                        void rectRecorteChanged();
                        void tamanhoImagemChanged();
                        void anguloOrientacaoCameraChanged();
                        void posicaoCameraChanged();
                    };
                    
                    #endif // PROCESSAIMAGEM_H
                    

                    processaimagem.cpp

                    #include "processaimagem.h"
                    
                    #include <QDebug>
                    
                    processaImagem::processaImagem(QObject *parent)
                    {
                    
                    }
                    
                    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())
                        {
                            qDebug() << "Erro ao carregar a imagem";
                            imagem = QImage();
                        }
                        else
                        {
                            if((p_anguloOrientacaoCamera == 90) || (p_anguloOrientacaoCamera == 270))
                            {
                                int larguraImagem = p_tamanhoImagem.width();
                                int alturaImagem = p_tamanhoImagem.height();
                    
                                p_tamanhoImagem.setWidth(alturaImagem);
                                p_tamanhoImagem.setHeight(larguraImagem);
                    
                                int recorteX = p_rectRecorte.x();
                                int recorteY = p_rectRecorte.y();
                                int recorteLargura = p_rectRecorte.width();
                                int recorteAltura = p_rectRecorte.height();
                    
                                p_rectRecorte.setRect(recorteY, recorteX, recorteAltura, recorteLargura);
                    
                                if(imagem.size().width() > imagem.size().height())
                                {
                                    QTransform rotacao;
                                    rotacao.rotate(360 - p_anguloOrientacaoCamera);
                                    imagem = imagem.transformed(rotacao);
                    
                                    qDebug() << "Rodou";
                                }
                            }
                    
                            if(imagem.width() != p_tamanhoImagem.width())
                            {
                                imagem = imagem.scaled(p_tamanhoImagem);
                            }
                    
                            imagem = imagem.copy(p_rectRecorte);
                        }
                    
                        return imagem;
                    }
                    
                    void processaImagem::removeImagemSalva()
                    {
                        QFile::remove(p_caminhoSalvar);
                    }
                    
                    QString processaImagem::caminhoImagem() const
                    {
                        return p_caminhoImagem;
                    }
                    
                    void processaImagem::setCaminhoImagem(const QString valor)
                    {
                        if (valor != p_caminhoImagem)
                        {
                            p_caminhoImagem = valor;
                            emit caminhoImagemChanged();
                        }
                    }
                    
                    QString processaImagem::caminhoSalvar() const
                    {
                        return p_caminhoSalvar;
                    }
                    
                    void processaImagem::setCaminhoSalvar(const QString valor)
                    {
                        if (valor != p_caminhoSalvar)
                        {
                            p_caminhoSalvar = valor;
                            emit caminhoSalvarChanged();
                        }
                    }
                    
                    QRect processaImagem::rectRecorte() const
                    {
                        return p_rectRecorte;
                    }
                    
                    void processaImagem::setRectRecorte(const QRect valor)
                    {
                        bool alterou = false;
                    
                        if (valor.x() != p_rectRecorte.x())
                        {
                            p_rectRecorte.setX(valor.x());
                            alterou = true;
                        }
                    
                        if (valor.y() != p_rectRecorte.y())
                        {
                            p_rectRecorte.setY(valor.y());
                            alterou = true;
                        }
                    
                        if (valor.width() != p_rectRecorte.width())
                        {
                            p_rectRecorte.setWidth(valor.width());
                            alterou = true;
                        }
                    
                        if (valor.height() != p_rectRecorte.height())
                        {
                            p_rectRecorte.setHeight(valor.height());
                            alterou = true;
                        }
                    
                        if(alterou)
                        {
                            emit rectRecorteChanged();
                        }
                    }
                    
                    QSize processaImagem::tamanhoImagem() const
                    {
                        return p_tamanhoImagem;
                    }
                    
                    void processaImagem::setTamanhoImagem(const QSize valor)
                    {
                        bool alterou = false;
                    
                        if (valor.width() != p_tamanhoImagem.width())
                        {
                            p_tamanhoImagem.setWidth(valor.width());
                            alterou = true;
                        }
                    
                        if (valor.height() != p_tamanhoImagem.height())
                        {
                            p_tamanhoImagem.setHeight(valor.height());
                            alterou = true;
                        }
                    
                        if(alterou)
                        {
                            emit tamanhoImagemChanged();
                        }
                    }
                    
                    int processaImagem::anguloOrientacaoCamera() const
                    {
                        return p_anguloOrientacaoCamera;
                    }
                    
                    void processaImagem::setAnguloOrientacaoCamera(const int valor)
                    {
                        if (valor != p_anguloOrientacaoCamera)
                        {
                            p_anguloOrientacaoCamera = valor;
                            emit anguloOrientacaoCameraChanged();
                        }
                    }
                    
                    int processaImagem::posicaoCamera() const
                    {
                        return p_posicaoCamera;
                    }
                    
                    void processaImagem::setPosicaoCamera(const int valor)
                    {
                        if (valor != p_posicaoCamera)
                        {
                            p_posicaoCamera = valor;
                            emit posicaoCameraChanged();
                        }
                    }
                    

                    provedorimagem.h

                    #ifndef PROVEDORIMAGEM_H
                    #define PROVEDORIMAGEM_H
                    
                    #include <QObject>
                    #include <QImage>
                    #include <QQuickImageProvider>
                    
                    class provedorImagem : public QObject, public QQuickImageProvider
                    {
                        Q_OBJECT
                    
                    public:
                        provedorImagem();
                    
                        QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize);
                    
                    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";
                        }
                    
                        return imagem;
                    }
                    
                    void provedorImagem::carregaImagem(QImage imagemRecebida)
                    {
                        imagem = imagemRecebida;
                    }
                    

                    Att.
                    Guilherme Cortada Dupas

                    p3c0P 1 Reply Last reply
                    0
                    • guidupasG guidupas

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

                      Here is the entire code:

                      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;
                      
                          engine.rootContext()->setContextProperty("ProvedorImagem", provedorImg);
                      
                          engine.addImageProvider("provedor", provedorImg);
                      
                          engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
                      
                          return app.exec();
                      }
                      

                      main.qml

                      import QtQuick 2.4
                      import QtQuick.Window 2.2
                      import QtQuick.Controls 1.3
                      import QtMultimedia 5.4
                      
                      import ProcessaImagemQml 1.0
                      
                      Window {
                          visible: true
                      
                          width: 360
                          height: 640
                      
                          maximumHeight: 640
                          minimumHeight: 640
                      
                          maximumWidth: 360
                          minimumWidth: 360
                      
                          title: "Camera Preview Test"
                      
                          Rectangle {
                              id: principal
                      
                              anchors.fill: parent
                      
                              ProcessaImagem {
                                  id: processaImagem
                      
                                  caminhoImagem: camera.caminhoPreview
                                  caminhoSalvar: camera.caminhoSalvar
                                  rectRecorte: camera.rectRecorte
                                  tamanhoImagem: camera.tamanhoImagem
                                  anguloOrientacaoCamera: camera.orientation
                                  posicaoCamera: camera.position
                      
                                  onCaminhoImagemChanged: {
                                      rectRecorte = cameraView.mapRectToSource(Qt.rect(cameraView.x, cameraView.y, cameraView.width, cameraView.height));
                                      tamanhoImagem = Qt.size(cameraView.sourceRect.width, cameraView.sourceRect.height);
                                      ProvedorImagem.carregaImagem(processaImagem.carregaImagem());
                                  }
                      
                                  onCaminhoSalvarChanged: {
                                      removeImagemSalva();
                                  }
                              }
                      
                              Rectangle {
                                  id: cameraRectangle
                      
                                  width: parent.width
                                  height: parent.width
                      
                                  anchors.top: parent.top
                      
                                  color: "lightGrey"
                      
                                  visible: true
                      
                                  Camera {
                                      id: camera
                      
                                      property string caminhoPreview: ""
                                      property string caminhoSalvar: ""
                                      property int numeroImagem: 0
                      
                                      captureMode: Camera.CaptureStillImage
                      
                                      imageCapture {
                                          onImageCaptured: {
                                              camera.caminhoPreview = preview;
                      
                                              camera.stop();
                      
                                              imagemPreview.source = "image://provedor/imagemEditada_" + camera.numeroImagem.toString();
                      
                                              camera.numeroImagem = camera.numeroImagem + 1;
                      
                                              imagemPreviewRectangle.visible = true;
                      
                                              cameraRectangle.visible = false;
                                          }
                      
                                          onImageSaved: {
                                              camera.caminhoSalvar = path;
                                          }
                                      }
                                  }
                      
                                  VideoOutput {
                                      id: cameraView
                      
                                      visible: true
                      
                                      focus: visible
                      
                                      anchors.fill: parent
                      
                                      source: camera
                                      orientation: camera.orientation
                                      fillMode: VideoOutput.PreserveAspectCrop
                                  }
                              }
                      
                              Rectangle {
                                  id: imagemPreviewRectangle
                      
                                  width: parent.width
                                  height: parent.width
                      
                                  anchors.top: parent.top
                      
                                  color: "lightGrey"
                      
                                  visible: false
                      
                                  Image {
                                      id: imagemPreview
                      
                                      fillMode: Image.PreserveAspectFit
                                      
                                      anchors.fill: parent
                                  }
                              }
                      
                              Rectangle {
                                  id: controleRectangle
                      
                                  width: parent.width
                                  height: parent.height - cameraRectangle.height
                      
                                  color: "grey"
                      
                                  anchors.top: cameraRectangle.bottom
                      
                                  Button {
                                      id: tirarFotoButton
                      
                                      text: "Tirar foto"
                      
                                      anchors.left: parent.left
                                      anchors.top: parent.top
                      
                                      onClicked: {
                                          camera.imageCapture.capture();
                                      }
                                  }
                      
                                  Button {
                                      id: novaFotoButton
                      
                                      text: "Tirar nova foto"
                      
                                      anchors.right: parent.right
                                      anchors.top: parent.top
                      
                                      onClicked: {
                                          camera.start();
                      
                                          imagemPreviewRectangle.visible = false;
                      
                                          cameraRectangle.visible = true;
                                      }
                                  }
                              }
                          }
                      }
                      

                      processaimagem.h

                      #ifndef PROCESSAIMAGEM_H
                      #define PROCESSAIMAGEM_H
                      
                      #include <QObject>
                      #include <QImage>
                      #include <QQmlEngine>
                      #include <QQmlContext>
                      #include <QQuickImageProvider>
                      #include <QFile>
                      
                      #include "provedorimagem.h"
                      
                      class processaImagem : public QObject
                      {
                          Q_OBJECT
                      
                          Q_PROPERTY(QString caminhoImagem READ caminhoImagem WRITE setCaminhoImagem NOTIFY caminhoImagemChanged)
                          Q_PROPERTY(QString caminhoSalvar READ caminhoSalvar WRITE setCaminhoSalvar NOTIFY caminhoSalvarChanged)
                          Q_PROPERTY(QRect rectRecorte READ rectRecorte WRITE setRectRecorte NOTIFY rectRecorteChanged)
                          Q_PROPERTY(QSize tamanhoImagem READ tamanhoImagem WRITE setTamanhoImagem NOTIFY tamanhoImagemChanged)
                          Q_PROPERTY(int anguloOrientacaoCamera READ anguloOrientacaoCamera WRITE setAnguloOrientacaoCamera NOTIFY anguloOrientacaoCameraChanged)
                          Q_PROPERTY(int posicaoCamera READ posicaoCamera WRITE setPosicaoCamera NOTIFY posicaoCameraChanged)
                      
                      public slots:
                          QImage carregaImagem();
                          void removeImagemSalva();
                      
                      public:
                          processaImagem(QObject *parent = 0);
                      
                          QString caminhoImagem() const;
                          void setCaminhoImagem(const QString valor);
                      
                          QString caminhoSalvar() const;
                          void setCaminhoSalvar(const QString valor);
                      
                          QRect rectRecorte() const;
                          void setRectRecorte(const QRect valor);
                      
                          QSize tamanhoImagem() const;
                          void setTamanhoImagem(const QSize valor);
                      
                          int anguloOrientacaoCamera() const;
                          void setAnguloOrientacaoCamera(const int valor);
                      
                          int posicaoCamera() const;
                          void setPosicaoCamera(const int valor);
                      
                      private:
                          QString p_caminhoImagem = "";
                          QString p_caminhoSalvar = "";
                          QRect p_rectRecorte = QRect(0, 0, 0, 0);
                          QSize p_tamanhoImagem = QSize(0, 0);
                          int p_anguloOrientacaoCamera = 0;
                          int p_posicaoCamera = 0;
                      
                      signals:
                          void caminhoImagemChanged();
                          void caminhoSalvarChanged();
                          void rectRecorteChanged();
                          void tamanhoImagemChanged();
                          void anguloOrientacaoCameraChanged();
                          void posicaoCameraChanged();
                      };
                      
                      #endif // PROCESSAIMAGEM_H
                      

                      processaimagem.cpp

                      #include "processaimagem.h"
                      
                      #include <QDebug>
                      
                      processaImagem::processaImagem(QObject *parent)
                      {
                      
                      }
                      
                      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())
                          {
                              qDebug() << "Erro ao carregar a imagem";
                              imagem = QImage();
                          }
                          else
                          {
                              if((p_anguloOrientacaoCamera == 90) || (p_anguloOrientacaoCamera == 270))
                              {
                                  int larguraImagem = p_tamanhoImagem.width();
                                  int alturaImagem = p_tamanhoImagem.height();
                      
                                  p_tamanhoImagem.setWidth(alturaImagem);
                                  p_tamanhoImagem.setHeight(larguraImagem);
                      
                                  int recorteX = p_rectRecorte.x();
                                  int recorteY = p_rectRecorte.y();
                                  int recorteLargura = p_rectRecorte.width();
                                  int recorteAltura = p_rectRecorte.height();
                      
                                  p_rectRecorte.setRect(recorteY, recorteX, recorteAltura, recorteLargura);
                      
                                  if(imagem.size().width() > imagem.size().height())
                                  {
                                      QTransform rotacao;
                                      rotacao.rotate(360 - p_anguloOrientacaoCamera);
                                      imagem = imagem.transformed(rotacao);
                      
                                      qDebug() << "Rodou";
                                  }
                              }
                      
                              if(imagem.width() != p_tamanhoImagem.width())
                              {
                                  imagem = imagem.scaled(p_tamanhoImagem);
                              }
                      
                              imagem = imagem.copy(p_rectRecorte);
                          }
                      
                          return imagem;
                      }
                      
                      void processaImagem::removeImagemSalva()
                      {
                          QFile::remove(p_caminhoSalvar);
                      }
                      
                      QString processaImagem::caminhoImagem() const
                      {
                          return p_caminhoImagem;
                      }
                      
                      void processaImagem::setCaminhoImagem(const QString valor)
                      {
                          if (valor != p_caminhoImagem)
                          {
                              p_caminhoImagem = valor;
                              emit caminhoImagemChanged();
                          }
                      }
                      
                      QString processaImagem::caminhoSalvar() const
                      {
                          return p_caminhoSalvar;
                      }
                      
                      void processaImagem::setCaminhoSalvar(const QString valor)
                      {
                          if (valor != p_caminhoSalvar)
                          {
                              p_caminhoSalvar = valor;
                              emit caminhoSalvarChanged();
                          }
                      }
                      
                      QRect processaImagem::rectRecorte() const
                      {
                          return p_rectRecorte;
                      }
                      
                      void processaImagem::setRectRecorte(const QRect valor)
                      {
                          bool alterou = false;
                      
                          if (valor.x() != p_rectRecorte.x())
                          {
                              p_rectRecorte.setX(valor.x());
                              alterou = true;
                          }
                      
                          if (valor.y() != p_rectRecorte.y())
                          {
                              p_rectRecorte.setY(valor.y());
                              alterou = true;
                          }
                      
                          if (valor.width() != p_rectRecorte.width())
                          {
                              p_rectRecorte.setWidth(valor.width());
                              alterou = true;
                          }
                      
                          if (valor.height() != p_rectRecorte.height())
                          {
                              p_rectRecorte.setHeight(valor.height());
                              alterou = true;
                          }
                      
                          if(alterou)
                          {
                              emit rectRecorteChanged();
                          }
                      }
                      
                      QSize processaImagem::tamanhoImagem() const
                      {
                          return p_tamanhoImagem;
                      }
                      
                      void processaImagem::setTamanhoImagem(const QSize valor)
                      {
                          bool alterou = false;
                      
                          if (valor.width() != p_tamanhoImagem.width())
                          {
                              p_tamanhoImagem.setWidth(valor.width());
                              alterou = true;
                          }
                      
                          if (valor.height() != p_tamanhoImagem.height())
                          {
                              p_tamanhoImagem.setHeight(valor.height());
                              alterou = true;
                          }
                      
                          if(alterou)
                          {
                              emit tamanhoImagemChanged();
                          }
                      }
                      
                      int processaImagem::anguloOrientacaoCamera() const
                      {
                          return p_anguloOrientacaoCamera;
                      }
                      
                      void processaImagem::setAnguloOrientacaoCamera(const int valor)
                      {
                          if (valor != p_anguloOrientacaoCamera)
                          {
                              p_anguloOrientacaoCamera = valor;
                              emit anguloOrientacaoCameraChanged();
                          }
                      }
                      
                      int processaImagem::posicaoCamera() const
                      {
                          return p_posicaoCamera;
                      }
                      
                      void processaImagem::setPosicaoCamera(const int valor)
                      {
                          if (valor != p_posicaoCamera)
                          {
                              p_posicaoCamera = valor;
                              emit posicaoCameraChanged();
                          }
                      }
                      

                      provedorimagem.h

                      #ifndef PROVEDORIMAGEM_H
                      #define PROVEDORIMAGEM_H
                      
                      #include <QObject>
                      #include <QImage>
                      #include <QQuickImageProvider>
                      
                      class provedorImagem : public QObject, public QQuickImageProvider
                      {
                          Q_OBJECT
                      
                      public:
                          provedorImagem();
                      
                          QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize);
                      
                      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";
                          }
                      
                          return imagem;
                      }
                      
                      void provedorImagem::carregaImagem(QImage imagemRecebida)
                      {
                          imagem = imagemRecebida;
                      }
                      
                      p3c0P Offline
                      p3c0P Offline
                      p3c0
                      Moderators
                      wrote on last edited by
                      #25

                      @guidupas That is what I said in earlier post :). Please make the post as solved if done.

                      157

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

                        @p3c0 Yes, but was not easy to figure out how to send the image to the provider.

                        By the way, thank you for all the help.

                        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