Ответ на мой вопрос Проблема решена. Вот шаг за шагом решение:
1 - Создание class
, который наследуется от QQuickImageProvider
и QObject
и внутри него создать Image
элемент (QImage)
это изображение, которое будет предусмотрено.
class provedorImagem : public QObject, public QQuickImageProvider
Внедрение метода virtual requestImage
. Это метод, который возвращает изображение в QML
QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize)
Создайте метод загрузки изображения провайдера вернуть
void provedorImagem::carregaImagem(QImage imagemRecebida)
{
imagem = imagemRecebida;
}
Теперь установить его в качестве поставщика двигателей изображения в файле main.cpp
provedorImagem *provedorImg = new provedorImagem;
engine.rootContext()->setContextProperty("ProvedorImagem", provedorImg);
2 - Создайте еще class
, который наследует от QObject
.
class processaImagem : public QObject
Внутри этого класса необходимо реализовать метод, который получит изображение от camera
поставщика, выполнять изменения изображений и возвращает измененное изображение. PS: p_caminhoImagem
- это property
, который я создал внутри processaImagem class
, который принимает 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 class
, чтобы предоставить его QML. Для того, чтобы сделать это поставщик class pointer
должен быть доступен в файле QML, так, в файле main.cpp
просто сделать указатель доступным для QML как property
engine.rootContext()->setContextProperty("ProvedorImagem", provedorImg);
и зарегистрировать processaImagem class
как тип QML
qmlRegisterType<processaImagem>("ProcessaImagemQml", 1, 0, "ProcessaImagem");
Теперь мы связываем его внутри QML файл
ProvedorImagem.carregaImagem(processaImagem.carregaImagem());
4 - Это сделано. Теперь просто запросить изображение от поставщика:
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
#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;
}
Вы должны реализовать собственный поставщик изображения для того, чтобы использовать 'QImage' в QML.У меня есть пример, заданный в этом ответе: http://stackoverflow.com/questions/27429371/qml-and-c-image-interoperability/27429586#27429586 просто измените его для 'QImage' вместо' QPixmap' – dtech
Возможный дубликат из [Qt/QML: отправить QImage из C++ в QML и отобразить QImage On GUI] (http://stackoverflow.com/questions/20691414/qt-qml-send-qimage-from-c-to-qml-and- display-the-qimage-on-gui) – hyde
Проблема в том, что все мои попытки сделать изображение доступным для поставщика изображений не удались. Я попытался использовать Q_PROPERTY и член QImage внутри класса, но мой провайдер всегда возвращает нулевое изображение, когда я пытаюсь получить к нему доступ, чтобы вернуться. – GuiDupas