summaryrefslogtreecommitdiffstats
path: root/src/multimedia/camera/qimagecapture.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/multimedia/camera/qimagecapture.cpp')
-rw-r--r--src/multimedia/camera/qimagecapture.cpp555
1 files changed, 555 insertions, 0 deletions
diff --git a/src/multimedia/camera/qimagecapture.cpp b/src/multimedia/camera/qimagecapture.cpp
new file mode 100644
index 000000000..7b1a34920
--- /dev/null
+++ b/src/multimedia/camera/qimagecapture.cpp
@@ -0,0 +1,555 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part 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 <qimagecapture.h>
+#include <private/qplatformimagecapture_p.h>
+#include <qmediametadata.h>
+#include <private/qplatformmediacapture_p.h>
+#include <private/qplatformmediaintegration_p.h>
+#include <private/qplatformmediaformatinfo_p.h>
+#include <qmediacapturesession.h>
+
+#include "private/qobject_p.h"
+#include <qcamera.h>
+#include <private/qplatformcamera_p.h>
+#include <QtCore/qdebug.h>
+#include <QtCore/qurl.h>
+#include <QtCore/qstringlist.h>
+#include <QtCore/qmetaobject.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QImageCapture
+ \inmodule QtMultimedia
+ \ingroup multimedia
+ \ingroup multimedia_camera
+
+
+ \brief The QImageCapture class is used for the recording of media content.
+
+ The QImageCapture class is a high level images recording class.
+ It's not intended to be used alone but for accessing the media
+ recording functions of other media objects, like QCamera.
+
+ \snippet multimedia-snippets/camera.cpp Camera
+
+ \snippet multimedia-snippets/camera.cpp Camera keys
+
+ \sa QCamera
+*/
+
+class QImageCapturePrivate
+{
+ Q_DECLARE_PUBLIC(QImageCapture)
+public:
+ QCamera *camera = nullptr;
+
+ QMediaCaptureSession *captureSession = nullptr;
+ QPlatformImageCapture *control = nullptr;
+
+ QImageCapture::Error error = QImageCapture::NoError;
+ QString errorString;
+ QMediaMetaData metaData;
+
+ void _q_error(int id, int error, const QString &errorString);
+
+ void unsetError() { error = QImageCapture::NoError; errorString.clear(); }
+
+ QImageCapture *q_ptr;
+};
+
+void QImageCapturePrivate::_q_error(int id, int error, const QString &errorString)
+{
+ Q_Q(QImageCapture);
+
+ this->error = QImageCapture::Error(error);
+ this->errorString = errorString;
+
+ emit q->errorChanged();
+ emit q->errorOccurred(id, this->error, errorString);
+}
+
+/*!
+ Constructs a image capture object that can capture individual still images produced by a camera.
+
+ Connect both an image capture object and a QCamera to a capture session to capture images.
+*/
+
+QImageCapture::QImageCapture(QObject *parent)
+ : QObject(parent), d_ptr(new QImageCapturePrivate)
+{
+ Q_D(QImageCapture);
+ d->q_ptr = this;
+ d->control = QPlatformMediaIntegration::instance()->createImageCapture(this);
+}
+
+void QImageCapture::setCaptureSession(QMediaCaptureSession *session)
+{
+ Q_D(QImageCapture);
+ d->captureSession = session;
+
+ QPlatformMediaCaptureSession *platformSession = session ? session->platformSession() : nullptr;
+
+ if (platformSession && d->control) {
+ platformSession->setImageCapture(d->control);
+ } else {
+ return;
+ }
+
+ connect(d->control, SIGNAL(imageExposed(int)),
+ this, SIGNAL(imageExposed(int)));
+ connect(d->control, SIGNAL(imageCaptured(int,QImage)),
+ this, SIGNAL(imageCaptured(int,QImage)));
+ connect(d->control, SIGNAL(imageMetadataAvailable(int,const QMediaMetaData&)),
+ this, SIGNAL(imageMetadataAvailable(int,const QMediaMetaData&)));
+ connect(d->control, SIGNAL(imageAvailable(int,QVideoFrame)),
+ this, SIGNAL(imageAvailable(int,QVideoFrame)));
+ connect(d->control, SIGNAL(imageSaved(int,QString)),
+ this, SIGNAL(imageSaved(int,QString)));
+ connect(d->control, SIGNAL(readyForCaptureChanged(bool)),
+ this, SIGNAL(readyForCaptureChanged(bool)));
+ connect(d->control, SIGNAL(error(int,int,QString)),
+ this, SLOT(_q_error(int,int,QString)));
+}
+
+/*!
+ Destroys images capture object.
+*/
+
+QImageCapture::~QImageCapture()
+{
+ if (d_ptr->captureSession) {
+ d_ptr->captureSession->platformSession()->setImageCapture(nullptr);
+ d_ptr->captureSession->setImageCapture(nullptr);
+ }
+ delete d_ptr;
+}
+
+/*!
+ Returns true if the images capture service ready to use.
+*/
+bool QImageCapture::isAvailable() const
+{
+ return d_func()->control != nullptr && d_func()->captureSession->camera();
+}
+
+/*!
+ Returns the capture session this camera is connected to, or
+ a nullptr if the camera is not connected to a capture session.
+
+ Use QMediaCaptureSession::setImageCapture() to connect the image capture to
+ a session.
+*/
+QMediaCaptureSession *QImageCapture::captureSession() const
+{
+ return d_ptr->captureSession;
+}
+
+/*!
+ Returns the current error state.
+
+ \sa errorString()
+*/
+
+QImageCapture::Error QImageCapture::error() const
+{
+ return d_func()->error;
+}
+
+/*!
+ Returns a string describing the current error state.
+
+ \sa error()
+*/
+
+QString QImageCapture::errorString() const
+{
+ return d_func()->errorString;
+}
+
+/*!
+ Returns the meta data that will get embedded into the image. A couple of additional fields
+ such as a time stamp or location might get added by the camera backend.
+*/
+QMediaMetaData QImageCapture::metaData() const
+{
+ Q_D(const QImageCapture);
+ return d->metaData;
+}
+
+/*!
+ Defines a set of meta data that will get embedded into the captured image.
+*/
+void QImageCapture::setMetaData(const QMediaMetaData &metaData)
+{
+ Q_D(QImageCapture);
+ d->metaData = metaData;
+ d->control->setMetaData(d->metaData);
+ emit metaDataChanged();
+}
+
+/*!
+ Adds additional meta data to be embedded into the captured image.
+*/
+void QImageCapture::addMetaData(const QMediaMetaData &metaData)
+{
+ Q_D(QImageCapture);
+ auto data = d->metaData;
+ for (auto k : metaData.keys())
+ data.insert(k, metaData.value(k));
+ setMetaData(data);
+}
+
+/*!
+ \property QImageCapture::readyForCapture
+ \brief whether the service is ready to capture a an image immediately.
+
+ Calling capture() while \e readyForCapture is \c false is not permitted and
+ results in an error.
+*/
+
+bool QImageCapture::isReadyForCapture() const
+{
+ Q_D(const QImageCapture);
+ if (!d->control || !d->captureSession || !d->control->isReadyForCapture())
+ return false;
+ auto *camera = d->captureSession->camera();
+ if (!camera || !camera->isActive())
+ return false;
+ return true;
+}
+
+/*!
+ \fn QImageCapture::readyForCaptureChanged(bool ready)
+
+ Signals that a camera's \a ready for capture state has changed.
+*/
+
+
+/*!
+ Capture the image and save it to \a file.
+ This operation is asynchronous in majority of cases,
+ followed by signals QImageCapture::imageExposed(),
+ QImageCapture::imageCaptured(), QImageCapture::imageSaved()
+ or QImageCapture::error().
+
+ If an empty \a file is passed, the camera backend choses
+ the default location and naming scheme for photos on the system,
+ if only file name without full path is specified, the image will be saved to
+ the default directory, with a full path reported with imageCaptured() and imageSaved() signals.
+
+ QCamera 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.
+
+ QImageCapture::capture returns the capture Id parameter, used with
+ imageExposed(), imageCaptured() and imageSaved() signals.
+
+ \sa isReadyForCapture()
+*/
+int QImageCapture::captureToFile(const QString &file)
+{
+ Q_D(QImageCapture);
+
+ d->unsetError();
+
+ if (!d->control) {
+ d->_q_error(-1, NotSupportedFeatureError, tr("Camera is not ready."));
+ return -1;
+ }
+
+ if (!isReadyForCapture()) {
+ d->_q_error(-1, NotReadyError, tr("Could not capture in stopped state"));
+ return -1;
+ }
+
+ return d->control->capture(file);
+}
+
+/*!
+ Capture the image and make it available as a QImage.
+ This operation is asynchronous in majority of cases,
+ followed by signals QImageCapture::imageExposed(),
+ QImageCapture::imageCaptured()
+ or QImageCapture::error().
+
+ QImageCapture::capture returns the capture Id parameter, used with
+ imageExposed(), imageCaptured() and imageSaved() signals.
+
+ \sa isReadyForCapture()
+*/
+int QImageCapture::capture()
+{
+ Q_D(QImageCapture);
+
+ d->unsetError();
+
+ if (d->control)
+ return d->control->captureToBuffer();
+
+ d->error = NotSupportedFeatureError;
+ d->errorString = tr("Device does not support images capture.");
+
+ d->_q_error(-1, d->error, d->errorString);
+
+ return -1;
+}
+
+/*!
+ \enum QImageCapture::Error
+
+ \value NoError No Errors.
+ \value NotReadyError The service is not ready for capture yet.
+ \value ResourceError Device is not ready or not available.
+ \value OutOfSpaceError No space left on device.
+ \value NotSupportedFeatureError Device does not support stillimages capture.
+ \value FormatError Current format is not supported.
+*/
+
+/*!
+ \fn QImageCapture::error(int id, QImageCapture::Error error, const QString &errorString)
+
+ Signals that the capture request \a id has failed with an \a error
+ and \a errorString description.
+*/
+
+/*!
+ \fn QImageCapture::bufferFormatChanged(QVideoFrameFormat::PixelFormat format)
+
+ Signal emitted when the buffer \a format for the buffer image capture has changed.
+*/
+
+/*!
+ \fn QImageCapture::imageExposed(int id)
+
+ Signal emitted when the frame with request \a id was exposed.
+*/
+
+/*!
+ \fn QImageCapture::imageCaptured(int id, const QImage &preview);
+
+ Signal emitted when the frame with request \a id was captured, but not
+ processed and saved yet. Frame \a preview can be displayed to user.
+*/
+
+/*!
+ \fn QImageCapture::imageMetadataAvailable(int id, const QString &key, const QVariant &value)
+
+ Signals that a metadata for an image with request \a id is available. Also
+ includes the \a key and \a value of the metadata.
+
+ This signal is emitted between imageExposed and imageSaved signals.
+*/
+
+/*!
+ \fn QImageCapture::imageAvailable(int id, const QVideoFrame &frame)
+
+ Signal emitted when QImageCapture::CaptureToBuffer is set and
+ the \a frame with request \a id is available.
+*/
+
+/*!
+ \fn QImageCapture::imageSaved(int id, const QString &fileName)
+
+ Signal emitted when QImageCapture::CaptureToFile is set and
+ the frame with request \a id was saved to \a fileName.
+*/
+
+/*!
+ Returns the image format.
+*/
+
+QImageCapture::FileFormat QImageCapture::fileFormat() const
+{
+ Q_D(const QImageCapture);
+ if (!d->control)
+ return UnspecifiedFormat;
+ return d->control->imageSettings().format();
+}
+
+/*!
+ Sets the image \a format.
+*/
+void QImageCapture::setFileFormat(QImageCapture::FileFormat format)
+{
+ Q_D(QImageCapture);
+ if (!d->control)
+ return;
+ auto fmt = d->control->imageSettings();
+ if (fmt.format() == format)
+ return;
+ fmt.setFormat(format);
+ d->control->setImageSettings(fmt);
+ emit fileFormatChanged();
+}
+
+QList<QImageCapture::FileFormat> QImageCapture::supportedFormats()
+{
+ return QPlatformMediaIntegration::instance()->formatInfo()->imageFormats;
+}
+
+QString QImageCapture::fileFormatName(QImageCapture::FileFormat f)
+{
+ const char *name = nullptr;
+ switch (f) {
+ case UnspecifiedFormat:
+ name = "Unspecified image format";
+ break;
+ case JPEG:
+ name = "JPEG";
+ break;
+ case PNG:
+ name = "PNG";
+ break;
+ case WebP:
+ name = "WebP";
+ break;
+ case Tiff:
+ name = "Tiff";
+ break;
+ }
+ return QString::fromUtf8(name);
+}
+
+QString QImageCapture::fileFormatDescription(QImageCapture::FileFormat f)
+{
+ const char *name = nullptr;
+ switch (f) {
+ case UnspecifiedFormat:
+ name = "Unspecified image format";
+ break;
+ case JPEG:
+ name = "JPEG";
+ break;
+ case PNG:
+ name = "PNG";
+ break;
+ case WebP:
+ name = "WebP";
+ break;
+ case Tiff:
+ name = "Tiff";
+ break;
+ }
+ return QString::fromUtf8(name);
+}
+
+/*!
+ Returns the resolution of the encoded image.
+*/
+
+QSize QImageCapture::resolution() const
+{
+ Q_D(const QImageCapture);
+ if (!d->control)
+ return QSize();
+ return d->control->imageSettings().resolution();
+}
+
+/*!
+ Sets the \a resolution of the encoded image.
+
+ An empty QSize indicates the encoder should make an optimal choice based on
+ what is available from the image source and the limitations of the codec.
+*/
+void QImageCapture::setResolution(const QSize &resolution)
+{
+ Q_D(QImageCapture);
+ if (!d->control)
+ return;
+ auto fmt = d->control->imageSettings();
+ if (fmt.resolution() == resolution)
+ return;
+ fmt.setResolution(resolution);
+ d->control->setImageSettings(fmt);
+ emit resolutionChanged();
+}
+
+/*!
+ Sets the \a width and \a height of the resolution of the encoded image.
+
+ \overload
+*/
+void QImageCapture::setResolution(int width, int height)
+{
+ setResolution(QSize(width, height));
+}
+
+/*!
+ \enum QImageCapture::EncodingQuality
+
+ Enumerates quality encoding levels.
+
+ \value VeryLowQuality
+ \value LowQuality
+ \value NormalQuality
+ \value HighQuality
+ \value VeryHighQuality
+*/
+
+/*!
+ Returns the image encoding quality.
+*/
+QImageCapture::Quality QImageCapture::quality() const
+{
+ Q_D(const QImageCapture);
+ if (!d->control)
+ return NormalQuality;
+ return d->control->imageSettings().quality();
+}
+
+/*!
+ Sets the image encoding \a quality.
+*/
+void QImageCapture::setQuality(Quality quality)
+{
+ Q_D(QImageCapture);
+ if (!d->control)
+ return;
+ auto fmt = d->control->imageSettings();
+ if (fmt.quality() == quality)
+ return;
+ fmt.setQuality(quality);
+ d->control->setImageSettings(fmt);
+ emit resolutionChanged();
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qimagecapture.cpp"