QML相机 - 拍摄广场照片

时间:2015-10-29 12:53:13

标签: qt qml qimage

如何使用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);

感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

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

1 - 创建一个继承自classQQuickImageProvider的{​​{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:camerap_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

使QML可用
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();
    }
}