将 QImage 传递给 QML [英] Pass QImage to QML
问题描述
我正在尝试将 QImage 传递给 QML.有人可以帮助我吗?代码如下.
I am trying to pass a QImage to QML. Could someone help me? The code is below.
问题是我为图像提供者提供图像的所有尝试都失败了.我尝试在类中使用 Q_PROPERTY 和 QImage 成员,但是当我尝试访问它以返回时,我的提供程序总是返回一个空图像.
The problem is 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.
如何使 QImage 可供提供者使用?
How can I make the QImage available for the provider?
QML
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
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
When I use this I receive the following message: Error: Cannot assign QImage to QUrl
我没有找到任何东西可以帮助我解决这个问题.我该怎么做?
I did not find anything to help me to solve this. How can I do that?
我已尝试使用链接建议的图像提供程序的不同方法,但仍然无法正常工作
I have tried a different approach using the image provider as suggested by the links, but it still not working
这里是代码
.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
}
这段代码的输出是:
加载图片正常
Loading image OK
Imagem 已加载
请求图片:(图片为空)
Request image: (image is null)
QML 图像:无法从提供者获取图像:image://provedorimagens/imagemEditada
QML Image: Failed to get image from provider: image://provedorimagens/imagemEditada
发生的情况是,当我调用函数时,图像不为空,但是当我尝试使用提供程序返回 QImage 时,它无法返回图像.我不知道为什么,但是对于图像提供者来说,图像是空的.
What happens is that 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.
我该如何解决?
推荐答案
回答我自己的问题问题解决了.这是一步一步的解决方案:
Answering my own question Problem solved. Here is the solution step by step:
1 - 创建一个继承自 QQuickImageProvider
和 QObject
的 class
并在其中创建一个 Image
成员 (QImage)
就是要提供的图片.
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
实现 virtual requestImage
方法.这是将图像返回到 Qml 的方法
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;
}
现在将其设置为 main.cpp
文件中的引擎映像提供程序
Now set it as the engine image provider in the main.cpp
file
provedorImagem *provedorImg = new provedorImagem;
engine.rootContext()->setContextProperty("ProvedorImagem", provedorImg);
2 - 创建另一个继承自 QObject
的 class
.
2 - Create another class
that inherits from QObject
.
class processaImagem : public QObject
在这个类中,您必须实现一个方法,该方法将从 camera
提供程序获取图像,执行图像修改并返回修改后的图像.PS:p_caminhoImagem
是我在processaImagem 类
中创建的property
,它接收相机预览路径
.
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 - 现在是主要部分.图像 requestImage
提供程序方法必须从 processaImagem 类
接收修改后的图像,以将其提供给 QML.为此,QML 文件必须可以访问提供程序 class pointer
,因此,在 main.cpp
文件中,只需将指针作为 property 提供给 QML
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);
并将 processaImagem 类
注册为 QML 类型
and register the processaImagem class
as a QML type
qmlRegisterType<processaImagem>("ProcessaImagemQml", 1, 0, "ProcessaImagem");
现在我们将它链接到 QML 文件中
Now we link it inside the QML file
ProvedorImagem.carregaImagem(processaImagem.carregaImagem());
4 - 完成了.现在只需向提供者请求图像:
4 - It is done. Now just request the image from the provider:
imagemPreview.source = "image://provedor/imagemEditada_" + camera.numeroImagem.toString();
这是完整的代码:
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
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
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
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
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;
}
这篇关于将 QImage 传递给 QML的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!