diff options
author | Lars Knoll <lars.knoll@qt.io> | 2021-04-15 10:18:43 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2021-04-19 11:06:54 +0000 |
commit | 0ca672235b097937f32d2960e4a8ca3e323074db (patch) | |
tree | c7990c15714e373a8271c6ab168a55207098fcba | |
parent | 8d0cd064a0272b0d7a005738f0a08c5e3b8e7281 (diff) |
New QML API for image capturing
Adjust the QML API for image capturing to fit with the new
handling of capture sessions. Simplify some things and
avoid using a wrapper class to the largest degree by
inheriting from QCameraImageCapture.
Remove the old image capturing code.
Change-Id: Ic99116f5202f2d0438fe0d048be2faa6687f0e4b
Reviewed-by: Doris Verria <doris.verria@qt.io>
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
17 files changed, 309 insertions, 404 deletions
diff --git a/examples/multimediawidgets/camera/camera.cpp b/examples/multimediawidgets/camera/camera.cpp index cf211534e..b7cbd936a 100644 --- a/examples/multimediawidgets/camera/camera.cpp +++ b/examples/multimediawidgets/camera/camera.cpp @@ -131,8 +131,7 @@ void Camera::setCamera(const QCameraInfo &cameraInfo) connect(m_imageCapture, &QCameraImageCapture::readyForCaptureChanged, this, &Camera::readyForCapture); connect(m_imageCapture, &QCameraImageCapture::imageCaptured, this, &Camera::processCapturedImage); connect(m_imageCapture, &QCameraImageCapture::imageSaved, this, &Camera::imageSaved); - connect(m_imageCapture, QOverload<int, QCameraImageCapture::Error, const QString &>::of(&QCameraImageCapture::error), - this, &Camera::displayCaptureError); + connect(m_imageCapture, &QCameraImageCapture::errorOccurred, this, &Camera::displayCaptureError); readyForCapture(m_imageCapture->isReadyForCapture()); QCameraImageProcessing *imageProcessing = m_camera->imageProcessing(); @@ -271,7 +270,7 @@ void Camera::setMuted(bool muted) void Camera::takeImage() { m_isCapturingImage = true; - m_imageCapture->capture(); + m_imageCapture->captureToFile(); } void Camera::displayCaptureError(int id, const QCameraImageCapture::Error error, const QString &errorString) diff --git a/src/imports/multimedia/CMakeLists.txt b/src/imports/multimedia/CMakeLists.txt index 2a09a00cd..9ef27bab8 100644 --- a/src/imports/multimedia/CMakeLists.txt +++ b/src/imports/multimedia/CMakeLists.txt @@ -11,10 +11,8 @@ qt_internal_add_qml_module(declarative_multimedia SOURCES multimedia.cpp qdeclarativecamera.cpp qdeclarativecamera_p.h - qdeclarativecameracapture.cpp qdeclarativecameracapture_p.h qdeclarativecameraexposure.cpp qdeclarativecameraexposure_p.h qdeclarativecameraflash.cpp qdeclarativecameraflash_p.h - qdeclarativecamerapreviewprovider.cpp qdeclarativecamerapreviewprovider_p.h qdeclarativecamerarecorder.cpp qdeclarativecamerarecorder_p.h qdeclarativemultimediaglobal.cpp qdeclarativemultimediaglobal_p.h qdeclarativeplaylist.cpp qdeclarativeplaylist_p.h diff --git a/src/imports/multimedia/multimedia.cpp b/src/imports/multimedia/multimedia.cpp index 0360a859e..a838dcf86 100644 --- a/src/imports/multimedia/multimedia.cpp +++ b/src/imports/multimedia/multimedia.cpp @@ -53,11 +53,12 @@ #include "qdeclarativemultimediaglobal_p.h" #include "qdeclarativeplaylist_p.h" #include "qdeclarativecamera_p.h" -#include "qdeclarativecamerapreviewprovider_p.h" #include "qdeclarativecameraexposure_p.h" #include "qdeclarativecameraflash_p.h" #include "qdeclarativetorch_p.h" +#include "qquickimagepreviewprovider_p.h" + QML_DECLARE_TYPE(QSoundEffect) QT_BEGIN_NAMESPACE @@ -87,8 +88,6 @@ public: // 6.0 types qmlRegisterType<QDeclarativeCamera>(uri, 6, 0, "Camera"); - qmlRegisterUncreatableType<QDeclarativeCameraCapture>(uri, 6, 0, "CameraCapture", - tr("CameraCapture is provided by Camera")); qmlRegisterUncreatableType<QDeclarativeCameraRecorder>(uri, 6, 0, "CameraRecorder", tr("CameraRecorder is provided by Camera")); qmlRegisterUncreatableType<QDeclarativeCameraExposure>(uri, 6, 0, "CameraExposure", @@ -111,7 +110,7 @@ public: void initializeEngine(QQmlEngine *engine, const char *uri) override { Q_UNUSED(uri); - engine->addImageProvider("camera", new QDeclarativeCameraPreviewProvider); + engine->addImageProvider("camera", new QQuickImagePreviewProvider); } }; diff --git a/src/imports/multimedia/qdeclarativecamera.cpp b/src/imports/multimedia/qdeclarativecamera.cpp index 626342cc6..282359efa 100644 --- a/src/imports/multimedia/qdeclarativecamera.cpp +++ b/src/imports/multimedia/qdeclarativecamera.cpp @@ -38,7 +38,6 @@ ****************************************************************************/ #include "qdeclarativecamera_p.h" -#include "qdeclarativecamerapreviewprovider_p.h" #include "qdeclarativecameraexposure_p.h" #include "qdeclarativecameraflash_p.h" @@ -48,6 +47,7 @@ #include <qobject.h> #include <QMediaDeviceManager> #include <QtQml/qqmlinfo.h> +#include <QtQml/qqmlengine.h> #include <QtCore/QTimer> #include <QtGui/qevent.h> @@ -166,7 +166,6 @@ QDeclarativeCamera::QDeclarativeCamera(QObject *parent) : m_currentCameraInfo = QMediaDeviceManager::defaultVideoInput(); m_camera = new QCamera(m_currentCameraInfo); - m_imageCapture = new QDeclarativeCameraCapture(&captureSession); m_videoRecorder = new QDeclarativeCameraRecorder(&captureSession); m_exposure = new QDeclarativeCameraExposure(m_camera); m_flash = new QDeclarativeCameraFlash(m_camera); @@ -181,7 +180,6 @@ QDeclarativeCamera::QDeclarativeCamera(QObject *parent) : QDeclarativeCamera::~QDeclarativeCamera() { // These must be deleted before QCamera - delete m_imageCapture; delete m_videoRecorder; delete m_exposure; delete m_flash; diff --git a/src/imports/multimedia/qdeclarativecamera_p.h b/src/imports/multimedia/qdeclarativecamera_p.h index 5d4f68114..425c60ddf 100644 --- a/src/imports/multimedia/qdeclarativecamera_p.h +++ b/src/imports/multimedia/qdeclarativecamera_p.h @@ -51,13 +51,11 @@ // We mean it. // -#include "qdeclarativecameracapture_p.h" #include "qdeclarativecamerarecorder_p.h" #include <qcamera.h> #include <qcamerainfo.h> #include <qcameraimageprocessing.h> -#include <qcameraimagecapture.h> #include <qmediacapturesession.h> #include <QtCore/qbasictimer.h> @@ -85,7 +83,6 @@ class QDeclarativeCamera : public QObject, public QQmlParserStatus Q_PROPERTY(Error errorCode READ errorCode NOTIFY errorChanged) Q_PROPERTY(QString errorString READ errorString NOTIFY errorChanged) - Q_PROPERTY(QDeclarativeCameraCapture* imageCapture READ imageCapture CONSTANT) Q_PROPERTY(QDeclarativeCameraRecorder* videoRecorder READ videoRecorder CONSTANT) Q_PROPERTY(QDeclarativeCameraExposure* exposure READ exposure CONSTANT) Q_PROPERTY(QDeclarativeCameraFlash* flash READ flash CONSTANT) @@ -171,7 +168,6 @@ public: QDeclarativeCamera(QObject *parent = 0); ~QDeclarativeCamera(); - QDeclarativeCameraCapture *imageCapture() { return m_imageCapture; } QDeclarativeCameraRecorder *videoRecorder() { return m_videoRecorder; } QDeclarativeCameraExposure *exposure() { return m_exposure; } QDeclarativeCameraFlash *flash() { return m_flash; } @@ -232,7 +228,6 @@ private: QCamera *m_camera; QCameraInfo m_currentCameraInfo; - QDeclarativeCameraCapture *m_imageCapture; QDeclarativeCameraRecorder *m_videoRecorder; QDeclarativeCameraExposure *m_exposure; QDeclarativeCameraFlash *m_flash; diff --git a/src/imports/multimedia/qdeclarativecameracapture.cpp b/src/imports/multimedia/qdeclarativecameracapture.cpp deleted file mode 100644 index 26ee1e67c..000000000 --- a/src/imports/multimedia/qdeclarativecameracapture.cpp +++ /dev/null @@ -1,307 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qdeclarativecamera_p.h" -#include "qdeclarativecameracapture_p.h" -#include "qdeclarativecamerapreviewprovider_p.h" - -#include <QtCore/qurl.h> - -QT_BEGIN_NAMESPACE - -/*! - \qmltype CameraCapture - \instantiates QDeclarativeCameraCapture - \brief An interface for capturing camera images. - \ingroup multimedia_qml - \inqmlmodule QtMultimedia - \ingroup camera_qml - - This type allows you to capture still images and be notified when they - are available or saved to disk. You can adjust the resolution of the captured - image and where the saved image should go. - - CameraCapture is a child of a \l Camera (as the \c imageCapture property) - and cannot be created directly. - - \qml - Item { - width: 640 - height: 360 - - Camera { - id: camera - - imageCapture { - onImageCaptured: { - // Show the preview in an Image - photoPreview.source = preview - } - } - } - - VideoOutput { - source: camera - focus : visible // to receive focus and capture key events when visible - anchors.fill: parent - - MouseArea { - anchors.fill: parent; - onClicked: camera.imageCapture.capture(); - } - } - - Image { - id: photoPreview - } - } - \endqml - -*/ - -QDeclarativeCameraCapture::QDeclarativeCameraCapture(QMediaCaptureSession *captureSession) - : QObject(captureSession) -{ - m_capture = new QCameraImageCapture(captureSession); - - connect(m_capture, SIGNAL(readyForCaptureChanged(bool)), this, SIGNAL(readyForCaptureChanged(bool))); - connect(m_capture, SIGNAL(imageExposed(int)), this, SIGNAL(imageExposed(int))); - connect(m_capture, SIGNAL(imageCaptured(int,QImage)), this, SLOT(_q_imageCaptured(int,QImage))); - connect(m_capture, SIGNAL(imageMetadataAvailable(int,const QMediaMetaData&)), this, - SIGNAL(imageMetadataAvailable(int,const QMediaMetaData&))); - connect(m_capture, SIGNAL(imageSaved(int,QString)), this, SLOT(_q_imageSaved(int,QString))); - connect(m_capture, SIGNAL(error(int,QCameraImageCapture::Error,QString)), - this, SLOT(_q_captureFailed(int,QCameraImageCapture::Error,QString))); -} - -QDeclarativeCameraCapture::~QDeclarativeCameraCapture() = default; - -/*! - \property QDeclarativeCameraCapture::ready - - This property holds a bool value indicating whether the camera - is ready to capture photos or not. - - Calling capture() while \e ready is \c false is not permitted and - results in an error. -*/ - -/*! - \qmlproperty bool QtMultimedia::CameraCapture::ready - - This property holds a bool value indicating whether the camera - is ready to capture photos or not. - - Calling capture() while \e ready is \c false is not permitted and - results in an error. -*/ -bool QDeclarativeCameraCapture::isReadyForCapture() const -{ - return m_capture->isReadyForCapture(); -} - -/*! - \qmlmethod QtMultimedia::CameraCapture::capture() - - Start image capture. The \l imageCaptured and \l imageSaved signals will - be emitted when the capture is complete. - - The image will be captured to the default system location, typically - QStandardPaths::writableLocation(QStandardPaths::PicturesLocation) for - still imaged or QStandardPaths::writableLocation(QStandardPaths::MoviesLocation) - for video. - - Camera saves all the capture parameters like exposure settings or - image processing parameters, so changes to camera parameters after - capture() is called do not affect previous capture requests. - - capture() returns the capture requestId parameter, used with - imageExposed(), imageCaptured(), imageMetadataAvailable() and imageSaved() signals. - - \sa ready -*/ -int QDeclarativeCameraCapture::capture() -{ - return m_capture->capture(); -} - -/*! - \qmlmethod QtMultimedia::CameraCapture::captureToLocation(location) - - Start image capture to specified \a location. The \l imageCaptured and \l imageSaved signals will - be emitted when the capture is complete. - - CameraCapture::captureToLocation returns the capture requestId parameter, used with - imageExposed(), imageCaptured(), imageMetadataAvailable() and imageSaved() signals. - - If the application is unable to write to the location specified by \c location - the CameraCapture will emit an error. The most likely reasons for the application - to be unable to write to a location is that the path is wrong and the location does not exists, - or the application does not have write permission for that location. -*/ -int QDeclarativeCameraCapture::captureToLocation(const QString &location) -{ - return m_capture->capture(location); -} - -/*! - \property QDeclarativeCameraCapture::capturedImagePath - - This property holds the location of the last captured image. -*/ -/*! - \qmlproperty string QtMultimedia::CameraCapture::capturedImagePath - - This property holds the location of the last captured image. -*/ -QString QDeclarativeCameraCapture::capturedImagePath() const -{ - return m_capturedImagePath; -} - -void QDeclarativeCameraCapture::_q_imageCaptured(int id, const QImage &preview) -{ - QString previewId = QString("preview_%1").arg(id); - QDeclarativeCameraPreviewProvider::registerPreview(previewId, preview); - - emit imageCaptured(id, QLatin1String("image://camera/")+previewId); -} - -void QDeclarativeCameraCapture::_q_imageSaved(int id, const QString &fileName) -{ - m_capturedImagePath = fileName; - emit imageSaved(id, fileName); -} - -void QDeclarativeCameraCapture::_q_captureFailed(int id, QCameraImageCapture::Error error, const QString &message) -{ - Q_UNUSED(error); - qWarning() << "QCameraImageCapture error:" << message; - emit captureFailed(id, message); -} - -/*! - \property QDeclarativeCameraCapture::resolution - - This property holds the resolution/size of the image to be captured. - If empty, the system chooses the appropriate resolution. -*/ -QCameraImageCapture::Error QDeclarativeCameraCapture::error() const -{ - return m_capture->error(); -} -/*! - \property QDeclarativeCameraCapture::errorString - - This property holds the error message related to the last capture. -*/ - -/*! - \qmlproperty string QtMultimedia::CameraCapture::errorString - - This property holds the error message related to the last capture. -*/ -QString QDeclarativeCameraCapture::errorString() const -{ - return m_capture->errorString(); -} - -/*! - \qmlmethod QtMultimedia::CameraCapture::setMetadata(key, value) - - - Sets a particular metadata \a key to \a value for the subsequent image captures. - - \sa QMediaMetaData -*/ -void QDeclarativeCameraCapture::setMetadata(QMediaMetaData::Key key, const QVariant &value) -{ - QMediaMetaData data; - data.insert(key, value); - m_capture->addMetaData(data); -} - -/*! - \qmlsignal QtMultimedia::CameraCapture::captureFailed(requestId, message) - - This signal is emitted when an error occurs during capture with \a requestId. - A descriptive message is available in \a message. - - The corresponding handler is \c onCaptureFailed. -*/ - -/*! - \qmlsignal QtMultimedia::CameraCapture::imageCaptured(requestId, preview) - - This signal is emitted when an image with \a requestId has been captured - but not yet saved to the filesystem. The \a preview - parameter can be used as the URL supplied to an \l Image. - - The corresponding handler is \c onImageCaptured. - - \sa imageSaved -*/ - -/*! - \qmlsignal QtMultimedia::CameraCapture::imageSaved(requestId, path) - - This signal is emitted after the image with \a requestId has been written to the filesystem. - The \a path is a local file path, not a URL. - - The corresponding handler is \c onImageSaved. - - \sa imageCaptured -*/ - - -/*! - \qmlsignal QtMultimedia::CameraCapture::imageMetadataAvailable(requestId, key, value) - - This signal is emitted when the image with \a requestId has new metadata - available with the key \a key and value \a value. - - The corresponding handler is \c onImageMetadataAvailable. - - \sa imageCaptured -*/ - - -QT_END_NAMESPACE - -#include "moc_qdeclarativecameracapture_p.cpp" diff --git a/src/imports/multimedia/qdeclarativecamerarecorder_p.h b/src/imports/multimedia/qdeclarativecamerarecorder_p.h index 9903c552d..467cc304d 100644 --- a/src/imports/multimedia/qdeclarativecamerarecorder_p.h +++ b/src/imports/multimedia/qdeclarativecamerarecorder_p.h @@ -56,6 +56,8 @@ #include <qmediaencodersettings.h> #include <qmediaformat.h> +#include <QtQml/qqml.h> + QT_BEGIN_NAMESPACE class QDeclarativeCamera; diff --git a/src/multimedia/camera/qcameraimagecapture.cpp b/src/multimedia/camera/qcameraimagecapture.cpp index b20d63a50..b7da53429 100644 --- a/src/multimedia/camera/qcameraimagecapture.cpp +++ b/src/multimedia/camera/qcameraimagecapture.cpp @@ -100,7 +100,8 @@ void QCameraImageCapturePrivate::_q_error(int id, int error, const QString &erro this->error = QCameraImageCapture::Error(error); this->errorString = errorString; - emit q->error(id, this->error, errorString); + emit q->errorChanged(); + emit q->errorOccurred(id, this->error, errorString); } /*! @@ -235,6 +236,7 @@ void QCameraImageCapture::setMetaData(const QMediaMetaData &metaData) Q_D(QCameraImageCapture); d->metaData = metaData; d->control->setMetaData(d->metaData); + emit metaDataChanged(); } void QCameraImageCapture::addMetaData(const QMediaMetaData &metaData) @@ -289,7 +291,7 @@ bool QCameraImageCapture::isReadyForCapture() const \sa isReadyForCapture() */ -int QCameraImageCapture::capture(const QString &file) +int QCameraImageCapture::captureToFile(const QString &file) { Q_D(QCameraImageCapture); @@ -301,12 +303,24 @@ int QCameraImageCapture::capture(const QString &file) d->error = NotSupportedFeatureError; d->errorString = tr("Device does not support images capture."); - emit error(-1, d->error, d->errorString); + d->_q_error(-1, d->error, d->errorString); return -1; } -int QCameraImageCapture::captureToBuffer() +/*! + Capture the image and make it available as a QImage. + This operation is asynchronous in majority of cases, + followed by signals QCameraImageCapture::imageExposed(), + QCameraImageCapture::imageCaptured() + or QCameraImageCapture::error(). + + QCameraImageCapture::capture returns the capture Id parameter, used with + imageExposed(), imageCaptured() and imageSaved() signals. + + \sa isReadyForCapture() +*/ +int QCameraImageCapture::capture() { Q_D(QCameraImageCapture); @@ -318,7 +332,7 @@ int QCameraImageCapture::captureToBuffer() d->error = NotSupportedFeatureError; d->errorString = tr("Device does not support images capture."); - emit error(-1, d->error, d->errorString); + d->_q_error(-1, d->error, d->errorString); return -1; } diff --git a/src/multimedia/camera/qcameraimagecapture.h b/src/multimedia/camera/qcameraimagecapture.h index 20edd9b65..c285e0784 100644 --- a/src/multimedia/camera/qcameraimagecapture.h +++ b/src/multimedia/camera/qcameraimagecapture.h @@ -64,7 +64,9 @@ class Q_MULTIMEDIA_EXPORT QCameraImageCapture : public QObject Q_OBJECT Q_ENUMS(Error) Q_PROPERTY(bool readyForCapture READ isReadyForCapture NOTIFY readyForCaptureChanged) - Q_PROPERTY(QMediaMetaData metaData READ metaData WRITE setMetaData) + Q_PROPERTY(QMediaMetaData metaData READ metaData WRITE setMetaData NOTIFY metaDataChanged) + Q_PROPERTY(Error error READ error NOTIFY errorChanged) + Q_PROPERTY(QString errorString READ errorString NOTIFY errorChanged) public: enum Error { @@ -96,13 +98,15 @@ public: void addMetaData(const QMediaMetaData &metaData); public Q_SLOTS: - int capture(const QString &location = QString()); - int captureToBuffer(); + int captureToFile(const QString &location = QString()); + int capture(); Q_SIGNALS: - void error(int id, QCameraImageCapture::Error error, const QString &errorString); + void errorChanged(); + void errorOccurred(int id, QCameraImageCapture::Error error, const QString &errorString); void readyForCaptureChanged(bool ready); + void metaDataChanged(); void imageExposed(int id); void imageCaptured(int id, const QImage &preview); diff --git a/src/multimediaquick/CMakeLists.txt b/src/multimediaquick/CMakeLists.txt index a3601e106..64c489d36 100644 --- a/src/multimediaquick/CMakeLists.txt +++ b/src/multimediaquick/CMakeLists.txt @@ -10,6 +10,8 @@ qt_add_module(MultimediaQuick SOURCES qdeclarativevideooutput.cpp qdeclarativevideooutput_p.h qdeclarativevideooutput_render.cpp qdeclarativevideooutput_render_p.h + qquickimagecapture.cpp qquickimagecapture_p.h + qquickimagepreviewprovider.cpp qquickimagepreviewprovider_p.h qsgvideonode_p.cpp qsgvideonode_p.h qsgvideotexture.cpp qsgvideotexture_p.h qtmultimediaquickglobal_p.h diff --git a/src/multimediaquick/qquickimagecapture.cpp b/src/multimediaquick/qquickimagecapture.cpp new file mode 100644 index 000000000..27f655c85 --- /dev/null +++ b/src/multimediaquick/qquickimagecapture.cpp @@ -0,0 +1,221 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickimagecapture_p.h" +#include "qquickimagepreviewprovider_p.h" + +#include <QtCore/qurl.h> + +QT_BEGIN_NAMESPACE + +/*! + \qmltype ImageCapture + \instantiates QQuickImageCapture + \brief An interface for capturing camera images. + \ingroup multimedia_qml + \inqmlmodule QtMultimedia + \ingroup camera_qml + + This type allows you to capture still images and be notified when they + are available or saved to disk. + + \qml + Item { + width: 640 + height: 360 + + CaptureSession { + imageCapture : ImageCapture { + id: imageCapture + } + camera: Camera { + id: camera + } + + videoOutput: VideoOutput { + anchors.fill: parent + + MouseArea { + anchors.fill: parent; + onClicked: imageCapture.capture(); + } + } + + Image { + id: photoPreview + src: imageCapture.preview // always shows the last captured image + } + } + \endqml + +*/ + +QQuickImageCapture::QQuickImageCapture(QObject *parent) + : QCameraImageCapture(parent) +{ + connect(this, SIGNAL(imageCaptured(int,QImage)), this, SLOT(_q_imageCaptured(int,QImage))); +} + +QQuickImageCapture::~QQuickImageCapture() = default; + +/*! + \property QQuickImageCapture::ready + + This property holds a bool value indicating whether the camera + is ready to capture photos or not. + + Calling capture() while \e ready is \c false is not permitted and + results in an error. +*/ + +/*! + \qmlproperty bool QtMultimedia::CameraCapture::readyForCapture + + This property holds a bool value indicating whether the camera + is ready to capture photos or not. + + Calling capture() while \e ready is \c false is not permitted and + results in an error. +*/ + +/*! + \qmlmethod QtMultimedia::CameraCapture::capture() + + Start image capture. The \l imageCaptured and \l imageSaved signals will + be emitted when the capture is complete. + + The captured image will be available through the preview property that can be + used as the source for a QML Image item. The saveToFile() method can then be used + save the image. + + Camera saves all the capture parameters like exposure settings or + image processing parameters, so changes to camera parameters after + capture() is called do not affect previous capture requests. + + capture() returns the capture requestId parameter, used with + imageExposed(), imageCaptured(), imageMetadataAvailable() and imageSaved() signals. + + \sa ready +*/ + +/*! + \qmlmethod QtMultimedia::CameraCapture::captureToFile() + + Does the same as capture() but additionally automatically saves the captured image to the specified + \a location. + + \sa capture +*/ + +/*! + \property QQuickImageCapture::capturedImagePath + + This property holds the location of the last captured image. +*/ +/*! + \qmlproperty string QtMultimedia::CameraCapture::capturedImagePath + + This property holds the location of the last captured image. +*/ +QString QQuickImageCapture::preview() const +{ + return m_capturedImagePath; +} + +void QQuickImageCapture::saveToFile(const QUrl &location) const +{ + m_lastImage.save(location.toLocalFile()); +} + +void QQuickImageCapture::_q_imageCaptured(int id, const QImage &preview) +{ + QString previewId = QString::fromLatin1("preview_%1").arg(id); + QQuickImagePreviewProvider::registerPreview(previewId, preview); + m_lastImage = preview; + emit previewChanged(); +} + +/*! + \qmlsignal QtMultimedia::CameraCapture::errorOccurred(requestId, Error, message) + + This signal is emitted when an error occurs during capture with \a requestId. + A descriptive message is available in \a message. + + The corresponding handler is \c onErrorOccurred. +*/ + +/*! + \qmlsignal QtMultimedia::CameraCapture::imageCaptured(requestId, preview) + + This signal is emitted when an image with \a requestId has been captured + but not yet saved to the filesystem. The \a preview + parameter can be used as the URL supplied to an \l Image. + + The corresponding handler is \c onImageCaptured. + + \sa imageSaved +*/ + +/*! + \qmlsignal QtMultimedia::CameraCapture::imageSaved(requestId, path) + + This signal is emitted after the image with \a requestId has been written to the filesystem. + The \a path is a local file path, not a URL. + + The corresponding handler is \c onImageSaved. + + \sa imageCaptured +*/ + + +/*! + \qmlsignal QtMultimedia::CameraCapture::imageMetadataAvailable(requestId, key, value) + + This signal is emitted when the image with \a requestId has new metadata + available with the key \a key and value \a value. + + The corresponding handler is \c onImageMetadataAvailable. + + \sa imageCaptured +*/ + + +QT_END_NAMESPACE + +#include "moc_qquickimagecapture_p.cpp" diff --git a/src/imports/multimedia/qdeclarativecameracapture_p.h b/src/multimediaquick/qquickimagecapture_p.h index 6ef19e941..f47617c87 100644 --- a/src/imports/multimedia/qdeclarativecameracapture_p.h +++ b/src/multimediaquick/qquickimagecapture_p.h @@ -37,8 +37,8 @@ ** ****************************************************************************/ -#ifndef QDECLARATIVECAMERACAPTURE_H -#define QDECLARATIVECAMERACAPTURE_H +#ifndef QQUICKIMAGECAPTURE_H +#define QQUICKIMAGECAPTURE_H // // W A R N I N G @@ -60,55 +60,34 @@ QT_BEGIN_NAMESPACE -class QDeclarativeCamera; +class QUrl; -class QDeclarativeCameraCapture : public QObject +class QQuickImageCapture : public QCameraImageCapture { Q_OBJECT - Q_PROPERTY(bool ready READ isReadyForCapture NOTIFY readyForCaptureChanged) - Q_PROPERTY(QString capturedImagePath READ capturedImagePath NOTIFY imageSaved) - Q_PROPERTY(QString errorString READ errorString NOTIFY captureFailed) + Q_PROPERTY(QString preview READ preview NOTIFY previewChanged) + QML_NAMED_ELEMENT(ImageCapture) public: - ~QDeclarativeCameraCapture(); + QQuickImageCapture(QObject *parent); + ~QQuickImageCapture(); - bool isReadyForCapture() const; - - QString capturedImagePath() const; - QCameraImageCapture::Error error() const; - QString errorString() const; + QString preview() const; public Q_SLOTS: - int capture(); - int captureToLocation(const QString &location); - - void setMetadata(QMediaMetaData::Key key, const QVariant &value); + void saveToFile(const QUrl &location) const; Q_SIGNALS: - void readyForCaptureChanged(bool); - - void imageExposed(int requestId); - void imageCaptured(int requestId, const QString &preview); - void imageMetadataAvailable(int requestId, const QMediaMetaData &); - void imageSaved(int requestId, const QString &path); - void captureFailed(int requestId, const QString &message); + void previewChanged(); -private slots: +private Q_SLOTS: void _q_imageCaptured(int, const QImage&); - void _q_imageSaved(int, const QString&); - void _q_captureFailed(int, QCameraImageCapture::Error, const QString&); private: - friend class QDeclarativeCamera; - QDeclarativeCameraCapture(QMediaCaptureSession *captureSession); - - QCameraImageCapture *m_capture; - QImageEncoderSettings m_imageSettings; + QImage m_lastImage; QString m_capturedImagePath; }; QT_END_NAMESPACE -QML_DECLARE_TYPE(QT_PREPEND_NAMESPACE(QDeclarativeCameraCapture)) - #endif diff --git a/src/imports/multimedia/qdeclarativecamerapreviewprovider.cpp b/src/multimediaquick/qquickimagepreviewprovider.cpp index 0c1566992..2f57f90d1 100644 --- a/src/imports/multimedia/qdeclarativecamerapreviewprovider.cpp +++ b/src/multimediaquick/qquickimagepreviewprovider.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the plugins of the Qt Toolkit. @@ -37,37 +37,37 @@ ** ****************************************************************************/ -#include "qdeclarativecamerapreviewprovider_p.h" +#include "qquickimagepreviewprovider_p.h" #include <QtCore/qmutex.h> #include <QtCore/qdebug.h> QT_BEGIN_NAMESPACE -struct QDeclarativeCameraPreviewProviderPrivate +struct QQuickImagePreviewProviderPrivate { QString id; QImage image; QMutex mutex; }; -Q_GLOBAL_STATIC(QDeclarativeCameraPreviewProviderPrivate, qDeclarativeCameraPreviewProviderPrivate) +Q_GLOBAL_STATIC(QQuickImagePreviewProviderPrivate, priv) -QDeclarativeCameraPreviewProvider::QDeclarativeCameraPreviewProvider() +QQuickImagePreviewProvider::QQuickImagePreviewProvider() : QQuickImageProvider(QQuickImageProvider::Image) { } -QDeclarativeCameraPreviewProvider::~QDeclarativeCameraPreviewProvider() +QQuickImagePreviewProvider::~QQuickImagePreviewProvider() { - QDeclarativeCameraPreviewProviderPrivate *d = qDeclarativeCameraPreviewProviderPrivate(); + QQuickImagePreviewProviderPrivate *d = priv(); QMutexLocker lock(&d->mutex); d->id.clear(); d->image = QImage(); } -QImage QDeclarativeCameraPreviewProvider::requestImage(const QString &id, QSize *size, const QSize& requestedSize) +QImage QQuickImagePreviewProvider::requestImage(const QString &id, QSize *size, const QSize& requestedSize) { - QDeclarativeCameraPreviewProviderPrivate *d = qDeclarativeCameraPreviewProviderPrivate(); + QQuickImagePreviewProviderPrivate *d = priv(); QMutexLocker lock(&d->mutex); if (d->id != id) @@ -83,10 +83,10 @@ QImage QDeclarativeCameraPreviewProvider::requestImage(const QString &id, QSize return res; } -void QDeclarativeCameraPreviewProvider::registerPreview(const QString &id, const QImage &preview) +void QQuickImagePreviewProvider::registerPreview(const QString &id, const QImage &preview) { //only the last preview is kept - QDeclarativeCameraPreviewProviderPrivate *d = qDeclarativeCameraPreviewProviderPrivate(); + QQuickImagePreviewProviderPrivate *d = priv(); QMutexLocker lock(&d->mutex); d->id = id; d->image = preview; diff --git a/src/imports/multimedia/qdeclarativecamerapreviewprovider_p.h b/src/multimediaquick/qquickimagepreviewprovider_p.h index cf5f0644c..a5c8a2e6a 100644 --- a/src/imports/multimedia/qdeclarativecamerapreviewprovider_p.h +++ b/src/multimediaquick/qquickimagepreviewprovider_p.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the plugins of the Qt Toolkit. @@ -37,8 +37,8 @@ ** ****************************************************************************/ -#ifndef QDECLARATIVECAMERAPREVIEWPROVIDER_H -#define QDECLARATIVECAMERAPREVIEWPROVIDER_H +#ifndef QQUICKIMAGEPREVIEWPROVIDER_H +#define QQUICKIMAGEPREVIEWPROVIDER_H // // W A R N I N G @@ -51,15 +51,16 @@ // We mean it. // +#include <qtmultimediaquickglobal_p.h> #include <QtQuick/qquickimageprovider.h> QT_BEGIN_NAMESPACE -class QDeclarativeCameraPreviewProvider : public QQuickImageProvider +class Q_MULTIMEDIAQUICK_EXPORT QQuickImagePreviewProvider : public QQuickImageProvider { public: - QDeclarativeCameraPreviewProvider(); - ~QDeclarativeCameraPreviewProvider(); + QQuickImagePreviewProvider(); + ~QQuickImagePreviewProvider(); QImage requestImage(const QString &id, QSize *size, const QSize& requestedSize) override; static void registerPreview(const QString &id, const QImage &preview); diff --git a/tests/auto/integration/qcamerabackend/tst_qcamerabackend.cpp b/tests/auto/integration/qcamerabackend/tst_qcamerabackend.cpp index 70d893277..275617235 100644 --- a/tests/auto/integration/qcamerabackend/tst_qcamerabackend.cpp +++ b/tests/auto/integration/qcamerabackend/tst_qcamerabackend.cpp @@ -225,7 +225,7 @@ void tst_QCameraBackend::testCameraCapture() QSignalSpy savedSignal(&imageCapture, SIGNAL(imageSaved(int,QString))); QSignalSpy errorSignal(&imageCapture, SIGNAL(error(int,QCameraImageCapture::Error,QString))); - imageCapture.capture(); + imageCapture.captureToFile(); QTRY_COMPARE(errorSignal.size(), 1); QCOMPARE(imageCapture.error(), QCameraImageCapture::NotReadyError); QCOMPARE(capturedSignal.size(), 0); @@ -237,7 +237,7 @@ void tst_QCameraBackend::testCameraCapture() QCOMPARE(camera.status(), QCamera::ActiveStatus); QCOMPARE(errorSignal.size(), 0); - int id = imageCapture.capture(); + int id = imageCapture.captureToFile(); QTRY_VERIFY(!savedSignal.isEmpty()); @@ -280,7 +280,7 @@ void tst_QCameraBackend::testCaptureToBuffer() camera.start(); QTRY_VERIFY(imageCapture.isReadyForCapture()); - int id = imageCapture.captureToBuffer(); + int id = imageCapture.capture(); QTRY_VERIFY(!imageAvailableSignal.isEmpty()); QVERIFY(errorSignal.isEmpty()); @@ -323,7 +323,7 @@ void tst_QCameraBackend::testCameraCaptureMetadata() QTRY_VERIFY(imageCapture.isReadyForCapture()); - int id = imageCapture.capture(QString::fromLatin1("/dev/null")); + int id = imageCapture.captureToFile(QString::fromLatin1("/dev/null")); QTRY_VERIFY(!savedSignal.isEmpty()); QVERIFY(!metadataSignal.isEmpty()); QCOMPARE(metadataSignal.first().first().toInt(), id); diff --git a/tests/auto/unit/multimedia/qcamera/tst_qcamera.cpp b/tests/auto/unit/multimedia/qcamera/tst_qcamera.cpp index 8f2854cd4..abdd7a556 100644 --- a/tests/auto/unit/multimedia/qcamera/tst_qcamera.cpp +++ b/tests/auto/unit/multimedia/qcamera/tst_qcamera.cpp @@ -257,7 +257,7 @@ void tst_QCamera::testSimpleCameraCapture() QVERIFY(imageCapture.errorString().isEmpty()); QSignalSpy errorSignal(&imageCapture, SIGNAL(error(int,QCameraImageCapture::Error,QString))); - imageCapture.capture(QString::fromLatin1("/dev/null")); + imageCapture.captureToFile(QString::fromLatin1("/dev/null")); QCOMPARE(errorSignal.size(), 1); QCOMPARE(imageCapture.error(), QCameraImageCapture::NotSupportedFeatureError); QVERIFY(!imageCapture.errorString().isEmpty()); @@ -276,7 +276,7 @@ void tst_QCamera::testCameraCapture() QSignalSpy capturedSignal(&imageCapture, SIGNAL(imageCaptured(int,QImage))); QSignalSpy errorSignal(&imageCapture, SIGNAL(error(int,QCameraImageCapture::Error,QString))); - imageCapture.capture(QString::fromLatin1("/dev/null")); + imageCapture.captureToFile(QString::fromLatin1("/dev/null")); QCOMPARE(capturedSignal.size(), 0); QCOMPARE(errorSignal.size(), 1); QCOMPARE(imageCapture.error(), QCameraImageCapture::NotReadyError); @@ -287,7 +287,7 @@ void tst_QCamera::testCameraCapture() QVERIFY(imageCapture.isReadyForCapture()); QCOMPARE(errorSignal.size(), 0); - imageCapture.capture(QString::fromLatin1("/dev/null")); + imageCapture.captureToFile(QString::fromLatin1("/dev/null")); QTRY_COMPARE(capturedSignal.size(), 1); QCOMPARE(errorSignal.size(), 0); @@ -306,7 +306,7 @@ void tst_QCamera::testCameraCaptureMetadata() QSignalSpy savedSignal(&imageCapture, SIGNAL(imageSaved(int,QString))); camera.start(); - int id = imageCapture.capture(QString::fromLatin1("/dev/null")); + int id = imageCapture.captureToFile(QString::fromLatin1("/dev/null")); QTRY_COMPARE(savedSignal.size(), 1); diff --git a/tests/auto/unit/multimedia/qcameraimagecapture/tst_qcameraimagecapture.cpp b/tests/auto/unit/multimedia/qcameraimagecapture/tst_qcameraimagecapture.cpp index 8733be409..26e0b2bdd 100644 --- a/tests/auto/unit/multimedia/qcameraimagecapture/tst_qcameraimagecapture.cpp +++ b/tests/auto/unit/multimedia/qcameraimagecapture/tst_qcameraimagecapture.cpp @@ -152,7 +152,7 @@ void tst_QCameraImageCapture::deleteMediaSource() QVERIFY(session.camera() == nullptr); QVERIFY(!capture->isAvailable()); - capture->capture(); + capture->captureToFile(); delete capture; } @@ -168,7 +168,7 @@ void tst_QCameraImageCapture::isReadyForCapture() QVERIFY(imageCapture.isAvailable() == true); QVERIFY(imageCapture.isReadyForCapture() == false); camera.start(); - imageCapture.capture(); + imageCapture.captureToFile(); QTRY_VERIFY(imageCapture.isReadyForCapture()); camera.stop(); } @@ -184,11 +184,11 @@ void tst_QCameraImageCapture::capture() QVERIFY(imageCapture.isAvailable() == true); QVERIFY(imageCapture.isReadyForCapture() == false); - QVERIFY(imageCapture.capture() == -1); + QVERIFY(imageCapture.captureToFile() == -1); camera.start(); QVERIFY(imageCapture.isReadyForCapture() == true); QTest::qWait(300); - QVERIFY(imageCapture.capture() != -1); + QVERIFY(imageCapture.captureToFile() != -1); camera.stop(); } @@ -226,7 +226,7 @@ void tst_QCameraImageCapture::errors() session.setImageCapture(&imageCapture); QVERIFY(imageCapture.isAvailable() == false); - imageCapture.capture(QString::fromLatin1("/dev/null")); + imageCapture.captureToFile(QString::fromLatin1("/dev/null")); QVERIFY(imageCapture.error() == QCameraImageCapture::NotSupportedFeatureError); QVERIFY2(!imageCapture.errorString().isEmpty(), "Device does not support images capture"); } @@ -241,7 +241,7 @@ void tst_QCameraImageCapture::errors() QVERIFY(imageCapture.error() == QCameraImageCapture::NoError); QVERIFY(imageCapture.errorString().isEmpty()); - imageCapture.capture(); + imageCapture.captureToFile(); QVERIFY(imageCapture.error() == QCameraImageCapture::NotReadyError); QVERIFY2(!imageCapture.errorString().isEmpty(), "Could not capture in stopped state"); @@ -258,7 +258,7 @@ void tst_QCameraImageCapture::error() session.setImageCapture(&imageCapture); QSignalSpy spy(&imageCapture, SIGNAL(error(int,QCameraImageCapture::Error,QString))); - imageCapture.capture(); + imageCapture.captureToFile(); QTest::qWait(30); QVERIFY(spy.count() == 1); QVERIFY(qvariant_cast<int>(spy.at(0).at(0)) == -1); @@ -280,7 +280,7 @@ void tst_QCameraImageCapture::imageCaptured() QVERIFY(imageCapture.isAvailable() == true); QVERIFY(imageCapture.isReadyForCapture() == false); camera.start(); - imageCapture.capture(); + imageCapture.captureToFile(); QTRY_VERIFY(imageCapture.isReadyForCapture()); QVERIFY(spy.count() == 1); @@ -304,7 +304,7 @@ void tst_QCameraImageCapture::imageExposed() QVERIFY(imageCapture.isAvailable() == true); QVERIFY(imageCapture.isReadyForCapture() == false); camera.start(); - imageCapture.capture(); + imageCapture.captureToFile(); QTRY_VERIFY(imageCapture.isReadyForCapture()); QVERIFY(spy.count() == 1); @@ -326,7 +326,7 @@ void tst_QCameraImageCapture::imageSaved() QVERIFY(imageCapture.isAvailable() == true); QVERIFY(imageCapture.isReadyForCapture() == false); camera.start(); - imageCapture.capture(QString::fromLatin1("/usr/share")); + imageCapture.captureToFile(QString::fromLatin1("/usr/share")); QTRY_VERIFY(imageCapture.isReadyForCapture()); QVERIFY(spy.count() == 1); @@ -347,13 +347,13 @@ void tst_QCameraImageCapture::readyForCaptureChanged() QSignalSpy spy(&imageCapture, SIGNAL(readyForCaptureChanged(bool))); QVERIFY(imageCapture.isReadyForCapture() == false); - imageCapture.capture(); + imageCapture.captureToFile(); QTest::qWait(100); QVERIFY(spy.count() == 0); QVERIFY2(!imageCapture.errorString().isEmpty(),"Could not capture in stopped state" ); camera.start(); QTest::qWait(100); - imageCapture.capture(); + imageCapture.captureToFile(); QTest::qWait(100); QVERIFY(spy.count() == 2); QVERIFY(spy.at(0).at(0).toBool() == false); |