QML Camera running in Android dies
Unsolved
QML and Qt Quick
-
I am developing an app that uses a QML
Camera
element. The problem is that after taking some photos the camera dies and does not work anymore until I reopen the app. Could anyone help me?I tried to use
camera.cameraState = Camera.LoadedState
before thecamera.start()
andcamera.cameraState = Camera.UnloadedState
after thecamera.stop()
, but it killed my entire app, not just the camera.Ps: I have tested it just in Android until now. I am going to see if it happens in iOS too.
Here is the entire code:
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; }