如何使用QML中的相机拍摄照片,但使用自定义尺寸,例如方形照片?我试图用QQuickImageProvider实现它,但我不明白它为什么不起作用。
QML代码
Camera {
id: camera
captureMode: Camera.CaptureStillImage
imageCapture {
onImageCaptured: {
manipulaImagem.imagem = preview;
previewImage.source = "image://ProvedorImagens/" + 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
}
我试图通过两种方式解决这个问题:
首先:
QImage manipulaImagem::requestImage(const QString &id, QSize *size, const QSize &requestedSize)
{
QUrl caminhoImagem(id);
QString imageId = caminhoImagem.path().remove(0, 1);
QImage imagem1(id);
if(imagem1.isNull())
{
qDebug() << "Erro";
}
else
{
qDebug() << "OK";
}
return imagem1;
}
我使用图像提供程序从QML调用此方法:previewImage.source =“image:// ProvedorImagens /”+ preview; 在这个使用QImage imagem1(id)或QImage imagem1(imageId)的函数中,两者都返回一个NULL图像。 它返回消息:QML图像:无法从提供者处获取图像:image:// provenorimagens / image:// camera / preview_1
另一种方式是另一种功能:
QImage manipulaImagem::recortarFotoPerfil(const QString &imagem)
{
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);
if(imagem1.isNull())
{
qDebug() << "Erro";
}
else
{
qDebug() << "OK";
}
return imagem1;
}
此函数获取图像,但当我返回它时,我收到一条消息: 错误:无法将QImage分配给QUrl
我直接从QML调用此函数: previewImage.source = manipulaImagem.recortarFotoPerfil(preview);
感谢您的帮助。
答案 0 :(得分:0)
回答我自己的问题 问题解决了。以下是逐步解决方案:
1 - 创建一个继承自class
和QQuickImageProvider
的{{1}},并在其中创建一个QObject
成员Image
,即要提供的图像。
(QImage)
实施class provedorImagem : public QObject, public QQuickImageProvider
方法。这是将图像返回到Qml
virtual requestImage
创建一个方法来加载提供者的图像以返回
QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize)
现在将其设置为void provedorImagem::carregaImagem(QImage imagemRecebida)
{
imagem = imagemRecebida;
}
文件
main.cpp
2 - 创建继承自provedorImagem *provedorImg = new provedorImagem;
engine.rootContext()->setContextProperty("ProvedorImagem", provedorImg);
。
class
QObject
在此类中,您必须实现一个方法,该方法将从class processaImagem : public QObject
提供程序获取图像,执行图像修改并返回修改后的图像。
PS:camera
是p_caminhoImagem
我在收到property
的{{1}}内创建的。{/ p>
processaImagem class
3 - 现在是主要部分。图像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;
}
接收修改后的图像,以便将其提供给QML。要做到这一点,QML文件必须可以访问提供程序requestImage
,因此,在processaImagem class
文件中只需将指针作为class pointer
main.cpp
并将property
注册为QML类型
engine.rootContext()->setContextProperty("ProvedorImagem", provedorImg);
现在我们将它链接到QML文件
中processaImagem class
4 - 完成了。现在只需要提供者提供图像:
qmlRegisterType<processaImagem>("ProcessaImagemQml", 1, 0, "ProcessaImagem");
以下是整个代码:
的main.cpp
ProvedorImagem.carregaImagem(processaImagem.carregaImagem());
main.qml
imagemPreview.source = "image://provedor/imagemEditada_" + camera.numeroImagem.toString();
processaimagem.h
#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();
}
processaimagem.cpp
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;
}
}
}
}
}
provedorimagem.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
provedorimagem.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();
}
}