在 Android 中运行的 QML 相机死了
Posted
技术标签:
【中文标题】在 Android 中运行的 QML 相机死了【英文标题】:QML Camera running in Android dies 【发布时间】:2015-11-13 14:22:30 【问题描述】:我正在开发一个使用 QML Camera
元素的应用程序。问题是,在拍摄了一些照片后,相机会死机并且在我重新打开应用程序之前不再工作。谁能帮帮我?
我尝试在camera.start()
之前使用camera.cameraState = Camera.LoadedState
,在camera.stop()
之后使用camera.cameraState = Camera.UnloadedState
,但它杀死了我的整个应用程序,而不仅仅是相机。
Ps:到目前为止,我只是在 android 中测试过它。我将看看它是否也发生在 ios 中。
这是完整的代码:
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;
【问题讨论】:
【参考方案1】:你为什么在imageCapture
中使用camera.stop()
。您将 imagemPreviewRectangle.visible
设置为 true
并将 cameraRectangle.visible
设置为 false
。尝试在imageCapture
和novaFotoButton
中注释掉camera.stop()
和camera.start()
并告诉结果。
【讨论】:
我正在使用camera.stop()
在不需要相机时停止使用资源。这是问题的原因吗?
我猜。删除 start () 和 stop() 后它是否工作?
是的,它正在工作。我会多尝试一点来重现错误,我会告诉你结果。
问题又出现了。我认为这可能是我捕捉图片的速度比 QML 清理垃圾的速度要快。我如何在资源非常有限的智能手机中对其进行测试,它正在使用大量内存。会是这样吗?
这可能是计算机上没有发生此类问题的原因。它使用了多少(百分比)?资源有限是什么意思?以上是关于在 Android 中运行的 QML 相机死了的主要内容,如果未能解决你的问题,请参考以下文章