首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >将QImage传递给QML

将QImage传递给QML
EN

Stack Overflow用户
提问于 2015-10-29 18:44:42
回答 2查看 8.3K关注 0票数 7

我正试图将一个QImage传递给QML。有人能帮我吗?代码在下面。

问题是,我所有使映像提供程序可用的尝试都失败了。我尝试在类中使用Q_PROPERTY和QImage成员,但是当我试图访问它以返回时,我的提供者总是返回一个空映像。

如何使QImage可供提供程序使用?

QML

代码语言:javascript
复制
Camera {
    id: camera

    captureMode: Camera.CaptureStillImage

    imageCapture {
        onImageCaptured: {
            manipulaImagem.imagem = preview;

            previewImage.source = manipulaImagem.recortarFotoPerfil(preview, viewfinder.mapRectToSource(Qt.rect(viewfinder.x, viewfinder.y, viewfinder.width, viewfinder.height)));
        }
    }
}
Image {
    id: previewImage

    fillMode: Image.PreserveAspectFit
    anchors.top: parent.top

    width: parent.width
    height: parent.width
}

CPP

代码语言:javascript
复制
QImage manipulaImagem::recortarFotoPerfil(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);
    QImage imagem1 = imageProvider->requestImage(imageId, &imageSize, imageSize);
    imagem1 = imageProvider->requestImage(imageId, &imageSize, imageSize);
    return imagem1;
}

当我使用它时,我收到以下消息:错误:不能将QImage分配给QUrl

我没有找到任何东西来帮助我解决这个问题。我怎么能这么做?

我尝试了一种不同的方法,如链接所建议的那样使用图像提供程序,但它仍然无法工作。

这是代码

.h

代码语言:javascript
复制
#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

代码语言:javascript
复制
#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

代码语言:javascript
复制
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
    }

此代码的输出是:

  • 加载图像确定
  • Imagem已加载
  • 请求图像:(图像为空)

QML图像:未能从提供者获得图像: image://provedorimagens/imagemEditada

当我调用函数时,映像不是null,但是当我试图使用提供程序返回QImage时,它不能返回映像。我不知道为什么,但是对于图像提供者来说,图像是空的。

我怎么能解决这个问题?

EN

Stack Overflow用户

回答已采纳

发布于 2015-11-12 17:03:47

回答我自己的问题解决了。下面是一步一步的解决方案:

1-创建一个继承自QQuickImageProviderQObjectImage,并在其中创建一个Image成员(QImage),该成员(QImage)是要提供的图像。

代码语言:javascript
复制
class provedorImagem : public QObject, public QQuickImageProvider

实现virtual requestImage方法。这是将图像返回给Qml的方法。

代码语言:javascript
复制
QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize)

创建一个方法来加载提供者的映像以返回

代码语言:javascript
复制
void provedorImagem::carregaImagem(QImage imagemRecebida)
{
    imagem = imagemRecebida;
}

现在将其设置为main.cpp文件中的引擎映像提供程序。

代码语言:javascript
复制
provedorImagem *provedorImg = new provedorImagem;
engine.rootContext()->setContextProperty("ProvedorImagem", provedorImg);

2-创建另一个从class继承的QObject

代码语言:javascript
复制
class processaImagem : public QObject

在这个类中,您必须实现一个方法,该方法将从camera提供程序获取映像,执行图像修改并返回修改后的映像。PS:p_caminhoImagem是我在接收camera preview pathprocessaImagem class中创建的一个camera preview path

代码语言:javascript
复制
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-现在是主要的部分。图像requestImage提供程序方法必须从processaImagem class接收修改后的映像,才能将其提供给QML。为此,提供程序class pointer必须可由QML文件访问,因此,在main.cpp文件中,只需将指针作为property提供给QML。

代码语言:javascript
复制
engine.rootContext()->setContextProperty("ProvedorImagem", provedorImg);

并将processaImagem class注册为QML类型。

代码语言:javascript
复制
qmlRegisterType<processaImagem>("ProcessaImagemQml", 1, 0, "ProcessaImagem");

现在我们将其链接到QML文件中。

代码语言:javascript
复制
ProvedorImagem.carregaImagem(processaImagem.carregaImagem());

4-完成。现在,只需从提供程序请求映像:

代码语言:javascript
复制
imagemPreview.source = "image://provedor/imagemEditada_" + camera.numeroImagem.toString();

以下是整个代码:

main.cpp

代码语言:javascript
复制
#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

代码语言:javascript
复制
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

代码语言:javascript
复制
#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

代码语言:javascript
复制
#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

代码语言:javascript
复制
#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

代码语言:javascript
复制
#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;
}
票数 9
EN
查看全部 2 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33422265

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档