Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qimagecapture.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3#include <qimagecapture.h>
4#include <private/qplatformimagecapture_p.h>
5#include <qmediametadata.h>
6#include <private/qplatformmediacapture_p.h>
7#include <private/qplatformmediaintegration_p.h>
8#include <private/qplatformmediaformatinfo_p.h>
9#include <qmediacapturesession.h>
10
11#include "private/qobject_p.h"
12#include <qcamera.h>
13#include <private/qplatformcamera_p.h>
14#include <QtCore/qdebug.h>
15#include <QtCore/qurl.h>
16#include <QtCore/qstringlist.h>
17#include <QtCore/qmetaobject.h>
18
19QT_BEGIN_NAMESPACE
20
21/*!
22 \class QImageCapture
23 \inmodule QtMultimedia
24 \ingroup multimedia
25 \ingroup multimedia_camera
26
27
28 \brief The QImageCapture class is used for the recording of media content.
29
30 The QImageCapture class is a high level images recording class.
31 It's not intended to be used alone but for accessing the media
32 recording functions of other media objects, like QCamera.
33
34 \snippet multimedia-snippets/camera.cpp Camera
35
36 \snippet multimedia-snippets/camera.cpp Camera keys
37
38 \sa QCamera
39*/
40
41class QImageCapturePrivate
42{
43 Q_DECLARE_PUBLIC(QImageCapture)
44public:
45 QCamera *camera = nullptr;
46
47 QMediaCaptureSession *captureSession = nullptr;
48 QPlatformImageCapture *control = nullptr;
49
50 QImageCapture::Error error = QImageCapture::NoError;
51 QString errorString;
52 QMediaMetaData metaData;
53
54 void _q_error(int id, int error, const QString &errorString);
55
56 void unsetError() { error = QImageCapture::NoError; errorString.clear(); }
57
58 QImageCapture *q_ptr;
59};
60
61void QImageCapturePrivate::_q_error(int id, int error, const QString &errorString)
62{
63 Q_Q(QImageCapture);
64
65 this->error = QImageCapture::Error(error);
66 this->errorString = errorString;
67
68 emit q->errorChanged();
69 emit q->errorOccurred(id, this->error, errorString);
70}
71
72/*!
73 Constructs a image capture object, from a \a parent, that can capture
74 individual still images produced by a camera.
75
76 You must connect both an image capture object and a QCamera to a capture
77 session to capture images.
78*/
79
80QImageCapture::QImageCapture(QObject *parent)
81 : QObject(parent), d_ptr(new QImageCapturePrivate)
82{
83 Q_D(QImageCapture);
84 d->q_ptr = this;
85
86 auto maybeControl = QPlatformMediaIntegration::instance()->createImageCapture(this);
87 if (!maybeControl) {
88 qWarning() << "Failed to initialize QImageCapture" << maybeControl.error();
89 d->errorString = maybeControl.error();
90 d->error = NotReadyError;
91 return;
92 }
93
94 d->control = maybeControl.value();
95 connect(d->control, &QPlatformImageCapture::imageExposed, this, &QImageCapture::imageExposed);
96 connect(d->control, &QPlatformImageCapture::imageCaptured, this, &QImageCapture::imageCaptured);
97 connect(d->control, &QPlatformImageCapture::imageMetadataAvailable, this,
98 &QImageCapture::imageMetadataAvailable);
99 connect(d->control, &QPlatformImageCapture::imageAvailable, this,
100 &QImageCapture::imageAvailable);
101 connect(d->control, &QPlatformImageCapture::imageSaved, this, &QImageCapture::imageSaved);
102 connect(d->control, &QPlatformImageCapture::readyForCaptureChanged, this,
103 &QImageCapture::readyForCaptureChanged);
104 connect(d->control, SIGNAL(error(int,int,QString)),
105 this, SLOT(_q_error(int,int,QString)));
106}
107
108/*!
109 \fn void QImageCapture::imageMetadataAvailable(int id, const QMediaMetaData &metaData)
110
111 Signals that an image identified by \a id has \a metaData.
112*/
113
114/*!
115 \internal
116*/
117void QImageCapture::setCaptureSession(QMediaCaptureSession *session)
118{
119 Q_D(QImageCapture);
120 d->captureSession = session;
121}
122
123/*!
124 Destroys images capture object.
125*/
126
127QImageCapture::~QImageCapture()
128{
129 if (d_ptr->captureSession)
130 d_ptr->captureSession->setImageCapture(nullptr);
131 delete d_ptr;
132}
133
134/*!
135 Returns true if the images capture service ready to use.
136*/
137bool QImageCapture::isAvailable() const
138{
139 return d_func()->control && d_func()->captureSession && d_func()->captureSession->camera();
140}
141
142/*!
143 Returns the capture session this camera is connected to, or
144 a nullptr if the camera is not connected to a capture session.
145
146 Use QMediaCaptureSession::setImageCapture() to connect the image capture to
147 a session.
148*/
149QMediaCaptureSession *QImageCapture::captureSession() const
150{
151 return d_ptr->captureSession;
152}
153
154/*!
155 \qmlproperty enumeration QtMultimedia::ImageCapture::error
156
157 This property holds the last error type that occurred. It can be one of the following.
158
159 \value ImageCapture.NoError No esrrors.
160 \value ImageCapture.NotReadyError The service is not ready for capture yet.
161 \value ImageCapture.ResourceError Device is not ready or not available.
162 \value ImageCapture.OutOfSpaceError No space left on device.
163 \value ImageCapture.NotSupportedFeatureError Device does not support stillimages capture.
164 \value ImageCapture.FormatError Current format is not supported.
165
166 \sa errorString
167*/
168
169/*!
170 \property QImageCapture::error
171
172 Returns the current error state.
173
174 \sa errorString()
175*/
176
177QImageCapture::Error QImageCapture::error() const
178{
179 return d_func()->error;
180}
181
182/*!
183 \qmlproperty string QtMultimedia::ImageCapture::errorString
184
185 This property holds the last error message that occurred.
186
187 \sa error
188*/
189
190/*!
191 \property QImageCapture::errorString
192
193 Returns a string describing the current error state.
194
195 \sa error()
196*/
197
198QString QImageCapture::errorString() const
199{
200 return d_func()->errorString;
201}
202
203/*!
204 \qmlproperty mediaMetaData QtMultimedia::ImageCapture::metaData
205
206 This property holds the metadata that wil be embedded into the image.
207*/
208
209/*!
210 \property QImageCapture::metaData
211 \brief The meta data that will get embedded into the image.
212
213 \note Additional fields such as a time stamp or location may get added by
214 the camera back end.
215*/
216QMediaMetaData QImageCapture::metaData() const
217{
218 Q_D(const QImageCapture);
219 return d->metaData;
220}
221
222/*!
223 Replaces any existing meta data, to be embedded into the captured image,
224 with a set of \a metaData.
225*/
226void QImageCapture::setMetaData(const QMediaMetaData &metaData)
227{
228 Q_D(QImageCapture);
229 d->metaData = metaData;
230 if (d->control)
231 d->control->setMetaData(d->metaData);
232 emit metaDataChanged();
233}
234
235/*!
236 Adds additional \a metaData to any existing meta data, that is embedded
237 into the captured image.
238*/
239void QImageCapture::addMetaData(const QMediaMetaData &metaData)
240{
241 Q_D(QImageCapture);
242 auto data = d->metaData;
243 for (auto &&[key, value] : metaData.asKeyValueRange())
244 data.insert(key, value);
245 setMetaData(data);
246}
247
248/*!
249 \property QImageCapture::readyForCapture
250
251 Holds \c true if the camera is ready to capture an image immediately.
252 Calling capture() while \c readyForCapture is \c false is not
253 permitted and results in an error.
254*/
255bool QImageCapture::isReadyForCapture() const
256{
257 Q_D(const QImageCapture);
258 if (!d->control || !d->captureSession || !d->control->isReadyForCapture())
259 return false;
260 auto *camera = d->captureSession->camera();
261 if (!camera || !camera->isActive())
262 return false;
263 return true;
264}
265
266/*!
267 \fn QImageCapture::readyForCaptureChanged(bool ready)
268
269 Signals that a camera's \a ready for capture state has changed.
270*/
271
272
273/*!
274 Capture the image and save it to \a file.
275 This operation is asynchronous in majority of cases,
276 followed by signals QImageCapture::imageExposed(),
277 QImageCapture::imageCaptured(), QImageCapture::imageSaved()
278 or QImageCapture::error().
279
280 If an empty \a file is passed, the camera back end chooses
281 the default location and naming scheme for photos on the system,
282 if only file name without full path is specified, the image will be saved to
283 the default directory, with a full path reported with imageCaptured() and imageSaved() signals.
284
285 QCamera saves all the capture parameters like exposure settings or
286 image processing parameters, so changes to camera parameters after
287 capture() is called do not affect previous capture requests.
288
289 QImageCapture::capture returns the capture Id parameter, used with
290 imageExposed(), imageCaptured() and imageSaved() signals.
291
292 \sa isReadyForCapture()
293*/
294int QImageCapture::captureToFile(const QString &file)
295{
296 Q_D(QImageCapture);
297 if (!d->control) {
298 d->_q_error(-1, d->error, d->errorString);
299 return -1;
300 }
301
302 d->unsetError();
303
304 if (!isReadyForCapture()) {
305 d->_q_error(-1, NotReadyError, tr("Could not capture in stopped state"));
306 return -1;
307 }
308
309 return d->control->capture(file);
310}
311
312/*!
313 Capture the image and make it available as a QImage.
314 This operation is asynchronous in majority of cases,
315 followed by signals QImageCapture::imageExposed(),
316 QImageCapture::imageCaptured()
317 or QImageCapture::error().
318
319 QImageCapture::capture returns the capture Id parameter, used with
320 imageExposed(), imageCaptured() and imageSaved() signals.
321
322 \sa isReadyForCapture()
323*/
324int QImageCapture::capture()
325{
326 Q_D(QImageCapture);
327 if (!d->control) {
328 d->_q_error(-1, d->error, d->errorString);
329 return -1;
330 } else {
331 d->unsetError();
332 return d->control->captureToBuffer();
333 }
334}
335
336/*!
337 \enum QImageCapture::Error
338
339 \value NoError No Errors.
340 \value NotReadyError The service is not ready for capture yet.
341 \value ResourceError Device is not ready or not available.
342 \value OutOfSpaceError No space left on device.
343 \value NotSupportedFeatureError Device does not support stillimages capture.
344 \value FormatError Current format is not supported.
345*/
346
347/*!
348 \fn QImageCapture::errorOccurred(int id, QImageCapture::Error error, const QString &errorString);
349
350 Signals that the capture request \a id has failed with an \a error
351 and \a errorString description.
352*/
353
354/*!
355 \fn QImageCapture::imageExposed(int id)
356
357 Signal emitted when the frame with request \a id was exposed.
358*/
359
360/*!
361 \fn QImageCapture::imageCaptured(int id, const QImage &preview);
362
363 Signal emitted when the frame with request \a id was captured, but not
364 processed and saved yet. Frame \a preview can be displayed to user.
365*/
366
367/*!
368 \fn QImageCapture::imageAvailable(int id, const QVideoFrame &frame)
369
370 Signal emitted when the \a frame with request \a id is available.
371*/
372
373/*!
374 \fn QImageCapture::imageSaved(int id, const QString &fileName)
375
376 Signal emitted when QImageCapture::CaptureToFile is set and
377 the frame with request \a id was saved to \a fileName.
378*/
379
380/*!
381 \enum QImageCapture::FileFormat
382
383 Choose one of the following image formats:
384
385 \value UnspecifiedFormat No format specified
386 \value JPEG \c .jpg or \c .jpeg format
387 \value PNG \c .png format
388 \value WebP \c .webp format
389 \value Tiff \c .tiff format
390 \omitvalue LastFileFormat
391*/
392
393/*!
394 \qmlproperty enumeration QtMultimedia::ImageCapture::fileFormat
395
396 This property holds the file format for which the image will be
397 written. It can be one of the following.
398
399 \value UnspecifiedFormat No format specified
400 \value JPEG \c .jpg or \c .jpeg format
401 \value PNG \c .png format
402 \value WebP \c .webp format
403 \value Tiff \c .tiff format
404*/
405
406/*!
407 \property QImageCapture::fileFormat
408 \brief The image format.
409*/
410
411QImageCapture::FileFormat QImageCapture::fileFormat() const
412{
413 Q_D(const QImageCapture);
414 return d->control ? d->control->imageSettings().format() : UnspecifiedFormat;
415}
416
417/*!
418 Sets the image \a format.
419
420 Assigning an unsupported \l FileFormat has no effect.
421
422 \sa supportedFormats
423*/
424void QImageCapture::setFileFormat(QImageCapture::FileFormat format)
425{
426 Q_D(QImageCapture);
427 if (!d->control)
428 return;
429 auto fmt = d->control->imageSettings();
430 const FileFormat oldFormat = fmt.format();
431 if (oldFormat == format)
432 return;
433 fmt.setFormat(format);
434 d->control->setImageSettings(fmt);
435 // Only fire the signal if the format was applied.
436 if (oldFormat != fileFormat())
437 emit fileFormatChanged();
438}
439
440/*!
441 \qmlproperty list<FileFormat> QtMultimedia::ImageCapture::supportedFormats
442 \since 6.10
443
444 Contains a list of supported file formats.
445
446 \sa fileFormat
447*/
448
449/*!
450 \property QImageCapture::supportedFormats
451 \brief a list of supported file formats.
452*/
453
454/*!
455 Returns a list of supported file formats.
456
457 \sa {QImageCapture::}{FileFormat}
458*/
459QList<QImageCapture::FileFormat> QImageCapture::supportedFormats()
460{
461 return QPlatformMediaIntegration::instance()->formatInfo()->imageFormats;
462}
463
464/*!
465 Returns the name of the given format, \a f.
466*/
467QString QImageCapture::fileFormatName(QImageCapture::FileFormat f)
468{
469 const char *name = nullptr;
470 switch (f) {
471 case UnspecifiedFormat:
472 name = "Unspecified image format";
473 break;
474 case JPEG:
475 name = "JPEG";
476 break;
477 case PNG:
478 name = "PNG";
479 break;
480 case WebP:
481 name = "WebP";
482 break;
483 case Tiff:
484 name = "Tiff";
485 break;
486 }
487 return QString::fromUtf8(name);
488}
489
490/*!
491 Returns the description of the given file format, \a f.
492*/
493QString QImageCapture::fileFormatDescription(QImageCapture::FileFormat f)
494{
495 const char *name = nullptr;
496 switch (f) {
497 case UnspecifiedFormat:
498 name = "Unspecified image format";
499 break;
500 case JPEG:
501 name = "JPEG";
502 break;
503 case PNG:
504 name = "PNG";
505 break;
506 case WebP:
507 name = "WebP";
508 break;
509 case Tiff:
510 name = "Tiff";
511 break;
512 }
513 return QString::fromUtf8(name);
514}
515
516/*!
517 Returns the resolution of the encoded image.
518*/
519
520QSize QImageCapture::resolution() const
521{
522 Q_D(const QImageCapture);
523 return d->control ? d->control->imageSettings().resolution() : QSize{};
524}
525
526/*!
527 \fn void QImageCapture::resolutionChanged()
528
529 Signals when the image resolution changes.
530*/
531
532/*!
533 Sets the \a resolution of the encoded image.
534
535 An empty QSize indicates the encoder should make an optimal choice based on
536 what is available from the image source and the limitations of the codec.
537*/
538void QImageCapture::setResolution(const QSize &resolution)
539{
540 Q_D(QImageCapture);
541 if (!d->control)
542 return;
543 auto fmt = d->control->imageSettings();
544 if (fmt.resolution() == resolution)
545 return;
546 fmt.setResolution(resolution);
547 d->control->setImageSettings(fmt);
548 emit resolutionChanged();
549}
550
551/*!
552 Sets the \a width and \a height of the resolution of the encoded image.
553
554 \overload
555*/
556void QImageCapture::setResolution(int width, int height)
557{
558 setResolution(QSize(width, height));
559}
560
561/*!
562 \enum QImageCapture::Quality
563
564 Enumerates quality encoding levels.
565
566 \value VeryLowQuality
567 \value LowQuality
568 \value NormalQuality
569 \value HighQuality
570 \value VeryHighQuality
571*/
572
573/*!
574 \qmlproperty enumeration QtMultimedia::ImageCapture::quality
575
576 This property holds the quality hint when storing the captured
577 image. It can be one of the following values.
578
579 \value VeryLowQuality Very low
580 \value LowQuality Low
581 \value NormalQuality Normal
582 \value HighQuality High
583 \value VeryHighQuality Very high
584*/
585
586/*!
587 \property QImageCapture::quality
588 \brief The image encoding quality.
589*/
590QImageCapture::Quality QImageCapture::quality() const
591{
592 Q_D(const QImageCapture);
593 return d->control ? d->control->imageSettings().quality() : NormalQuality;
594}
595
596/*!
597 Sets the image encoding \a quality.
598*/
599void QImageCapture::setQuality(Quality quality)
600{
601 Q_D(QImageCapture);
602 if (!d->control)
603 return;
604 auto fmt = d->control->imageSettings();
605 if (fmt.quality() == quality)
606 return;
607 fmt.setQuality(quality);
608 d->control->setImageSettings(fmt);
609 emit qualityChanged();
610}
611
612/*!
613 \internal
614*/
615QPlatformImageCapture *QImageCapture::platformImageCapture()
616{
617 Q_D(QImageCapture);
618 return d->control;
619}
620
621QT_END_NAMESPACE
622
623#include "moc_qimagecapture.cpp"