Pass QImage to QML

后端 未结 1 914
抹茶落季
抹茶落季 2021-02-10 01:28

I am trying to pass a QImage to QML. Could someone help me? The code is below.

The problem is that all my attempts to make the image available for the image provider fai

1条回答
  •  傲寒
    傲寒 (楼主)
    2021-02-10 01:55

    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(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("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 
    #include 
    
    #include 
    
    #include "processaimagem.h"
    #include "provedorimagem.h"
    
    int main(int argc, char *argv[])
    {
        QGuiApplication app(argc, argv);
    
        qmlRegisterType("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 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    #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 
    
    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(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 
    #include 
    #include 
    
    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 
    
    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;
    }
    

    0 讨论(0)
提交回复
热议问题