1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qcameraexposure.h"
41#include "qmediaobject_p.h"
42
43#include <qcamera.h>
44#include <qcameraexposurecontrol.h>
45#include <qcameraflashcontrol.h>
46
47#include <QtCore/QMetaObject>
48#include <QtCore/QDebug>
49
50QT_BEGIN_NAMESPACE
51
52/*!
53 \class QCameraExposure
54
55
56 \brief The QCameraExposure class provides interface for exposure related camera settings.
57
58 \inmodule QtMultimedia
59 \ingroup multimedia
60 \ingroup multimedia_camera
61
62*/
63
64//#define DEBUG_EXPOSURE_CHANGES 1
65
66static void qRegisterCameraExposureMetaTypes()
67{
68 qRegisterMetaType<QCameraExposure::ExposureMode>(typeName: "QCameraExposure::ExposureMode");
69 qRegisterMetaType<QCameraExposure::FlashModes>(typeName: "QCameraExposure::FlashModes");
70 qRegisterMetaType<QCameraExposure::MeteringMode>(typeName: "QCameraExposure::MeteringMode");
71}
72
73Q_CONSTRUCTOR_FUNCTION(qRegisterCameraExposureMetaTypes)
74
75
76class QCameraExposurePrivate
77{
78 Q_DECLARE_NON_CONST_PUBLIC(QCameraExposure)
79public:
80 void initControls();
81 QCameraExposure *q_ptr;
82
83 template<typename T> T actualExposureParameter(QCameraExposureControl::ExposureParameter parameter, const T &defaultValue) const;
84 template<typename T> T requestedExposureParameter(QCameraExposureControl::ExposureParameter parameter, const T &defaultValue) const;
85 template<typename T> void setExposureParameter(QCameraExposureControl::ExposureParameter parameter, const T &value);
86 void resetExposureParameter(QCameraExposureControl::ExposureParameter parameter);
87
88 QCamera *camera;
89 QCameraExposureControl *exposureControl;
90 QCameraFlashControl *flashControl;
91
92 void _q_exposureParameterChanged(int parameter);
93 void _q_exposureParameterRangeChanged(int parameter);
94};
95
96void QCameraExposurePrivate::initControls()
97{
98 Q_Q(QCameraExposure);
99
100 QMediaService *service = camera->service();
101 exposureControl = nullptr;
102 flashControl = nullptr;
103 if (service) {
104 exposureControl = qobject_cast<QCameraExposureControl *>(object: service->requestControl(QCameraExposureControl_iid));
105 flashControl = qobject_cast<QCameraFlashControl *>(object: service->requestControl(QCameraFlashControl_iid));
106 }
107 if (exposureControl) {
108 q->connect(sender: exposureControl, SIGNAL(actualValueChanged(int)),
109 receiver: q, SLOT(_q_exposureParameterChanged(int)));
110 q->connect(sender: exposureControl, SIGNAL(parameterRangeChanged(int)),
111 receiver: q, SLOT(_q_exposureParameterRangeChanged(int)));
112 }
113
114 if (flashControl)
115 q->connect(sender: flashControl, SIGNAL(flashReady(bool)), receiver: q, SIGNAL(flashReady(bool)));
116}
117
118template<typename T>
119T QCameraExposurePrivate::actualExposureParameter(QCameraExposureControl::ExposureParameter parameter, const T &defaultValue) const
120{
121 QVariant value = exposureControl ? exposureControl->actualValue(parameter) : QVariant();
122
123 return value.isValid() ? value.value<T>() : defaultValue;
124}
125
126template<typename T>
127T QCameraExposurePrivate::requestedExposureParameter(QCameraExposureControl::ExposureParameter parameter, const T &defaultValue) const
128{
129 QVariant value = exposureControl ? exposureControl->requestedValue(parameter) : QVariant();
130
131 return value.isValid() ? value.value<T>() : defaultValue;
132}
133
134template<typename T>
135void QCameraExposurePrivate::setExposureParameter(QCameraExposureControl::ExposureParameter parameter, const T &value)
136{
137 if (exposureControl)
138 exposureControl->setValue(parameter, value: QVariant::fromValue<T>(value));
139}
140
141void QCameraExposurePrivate::resetExposureParameter(QCameraExposureControl::ExposureParameter parameter)
142{
143 if (exposureControl)
144 exposureControl->setValue(parameter, value: QVariant());
145}
146
147
148void QCameraExposurePrivate::_q_exposureParameterChanged(int parameter)
149{
150 Q_Q(QCameraExposure);
151
152#if DEBUG_EXPOSURE_CHANGES
153 qDebug() << "Exposure parameter changed:"
154 << QCameraExposureControl::ExposureParameter(parameter)
155 << exposureControl->actualValue(QCameraExposureControl::ExposureParameter(parameter));
156#endif
157
158 switch (parameter) {
159 case QCameraExposureControl::ISO:
160 emit q->isoSensitivityChanged(q->isoSensitivity());
161 break;
162 case QCameraExposureControl::Aperture:
163 emit q->apertureChanged(q->aperture());
164 break;
165 case QCameraExposureControl::ShutterSpeed:
166 emit q->shutterSpeedChanged(speed: q->shutterSpeed());
167 break;
168 case QCameraExposureControl::ExposureCompensation:
169 emit q->exposureCompensationChanged(q->exposureCompensation());
170 break;
171 }
172}
173
174void QCameraExposurePrivate::_q_exposureParameterRangeChanged(int parameter)
175{
176 Q_Q(QCameraExposure);
177
178 switch (parameter) {
179 case QCameraExposureControl::Aperture:
180 emit q->apertureRangeChanged();
181 break;
182 case QCameraExposureControl::ShutterSpeed:
183 emit q->shutterSpeedRangeChanged();
184 break;
185 }
186}
187
188/*!
189 Construct a QCameraExposure from service \a provider and \a parent.
190*/
191
192QCameraExposure::QCameraExposure(QCamera *parent):
193 QObject(parent), d_ptr(new QCameraExposurePrivate)
194{
195 Q_D(QCameraExposure);
196 d->camera = parent;
197 d->q_ptr = this;
198 d->initControls();
199}
200
201
202/*!
203 Destroys the camera exposure object.
204*/
205
206QCameraExposure::~QCameraExposure()
207{
208 Q_D(QCameraExposure);
209 if (d->exposureControl)
210 d->camera->service()->releaseControl(control: d->exposureControl);
211
212 delete d;
213}
214
215/*!
216 Returns true if exposure settings are supported by this camera.
217*/
218bool QCameraExposure::isAvailable() const
219{
220 return d_func()->exposureControl != nullptr;
221}
222
223
224/*!
225 \property QCameraExposure::flashMode
226 \brief The flash mode being used.
227
228 Usually the single QCameraExposure::FlashMode flag is used,
229 but some non conflicting flags combination are also allowed,
230 like QCameraExposure::FlashManual | QCameraExposure::FlashSlowSyncRearCurtain.
231
232 \sa QCameraExposure::isFlashModeSupported(), QCameraExposure::isFlashReady()
233*/
234
235QCameraExposure::FlashModes QCameraExposure::flashMode() const
236{
237 return d_func()->flashControl ? d_func()->flashControl->flashMode() : QCameraExposure::FlashOff;
238}
239
240void QCameraExposure::setFlashMode(QCameraExposure::FlashModes mode)
241{
242 if (d_func()->flashControl)
243 d_func()->flashControl->setFlashMode(mode);
244}
245
246/*!
247 Returns true if the flash \a mode is supported.
248*/
249
250bool QCameraExposure::isFlashModeSupported(QCameraExposure::FlashModes mode) const
251{
252 return d_func()->flashControl ? d_func()->flashControl->isFlashModeSupported(mode) : false;
253}
254
255/*!
256 Returns true if flash is charged.
257*/
258
259bool QCameraExposure::isFlashReady() const
260{
261 return d_func()->flashControl ? d_func()->flashControl->isFlashReady() : false;
262}
263
264/*!
265 \property QCameraExposure::exposureMode
266 \brief The exposure mode being used.
267
268 \sa QCameraExposure::isExposureModeSupported()
269*/
270
271QCameraExposure::ExposureMode QCameraExposure::exposureMode() const
272{
273 return d_func()->actualExposureParameter<QCameraExposure::ExposureMode>(parameter: QCameraExposureControl::ExposureMode, defaultValue: QCameraExposure::ExposureAuto);
274}
275
276void QCameraExposure::setExposureMode(QCameraExposure::ExposureMode mode)
277{
278 d_func()->setExposureParameter<QCameraExposure::ExposureMode>(parameter: QCameraExposureControl::ExposureMode, value: mode);
279}
280
281/*!
282 Returns true if the exposure \a mode is supported.
283*/
284
285bool QCameraExposure::isExposureModeSupported(QCameraExposure::ExposureMode mode) const
286{
287 if (!d_func()->exposureControl)
288 return false;
289
290 bool continuous = false;
291 return d_func()->exposureControl->supportedParameterRange(parameter: QCameraExposureControl::ExposureMode, continuous: &continuous)
292 .contains(t: QVariant::fromValue<QCameraExposure::ExposureMode>(value: mode));
293}
294
295/*!
296 \property QCameraExposure::exposureCompensation
297 \brief Exposure compensation in EV units.
298
299 Exposure compensation property allows to adjust the automatically calculated exposure.
300*/
301
302qreal QCameraExposure::exposureCompensation() const
303{
304 return d_func()->actualExposureParameter<qreal>(parameter: QCameraExposureControl::ExposureCompensation, defaultValue: 0.0);
305}
306
307void QCameraExposure::setExposureCompensation(qreal ev)
308{
309 d_func()->setExposureParameter<qreal>(parameter: QCameraExposureControl::ExposureCompensation, value: ev);
310}
311
312/*!
313 \property QCameraExposure::meteringMode
314 \brief The metering mode being used.
315
316 \sa QCameraExposure::isMeteringModeSupported()
317*/
318
319QCameraExposure::MeteringMode QCameraExposure::meteringMode() const
320{
321 return d_func()->actualExposureParameter<QCameraExposure::MeteringMode>(parameter: QCameraExposureControl::MeteringMode, defaultValue: QCameraExposure::MeteringMatrix);
322}
323
324void QCameraExposure::setMeteringMode(QCameraExposure::MeteringMode mode)
325{
326 d_func()->setExposureParameter<QCameraExposure::MeteringMode>(parameter: QCameraExposureControl::MeteringMode, value: mode);
327}
328
329/*!
330 \fn QCameraExposure::spotMeteringPoint() const
331
332 When supported, the spot metering point is the (normalized) position of the point of the image
333 where exposure metering will be performed. This is typically used to indicate an
334 "interesting" area of the image that should be exposed properly.
335
336 The coordinates are relative frame coordinates:
337 QPointF(0,0) points to the left top frame point, QPointF(0.5,0.5) points to the frame center,
338 which is typically the default spot metering point.
339
340 The spot metering point is only used with spot metering mode.
341
342 \sa setSpotMeteringPoint()
343*/
344
345QPointF QCameraExposure::spotMeteringPoint() const
346{
347 return d_func()->exposureControl ? d_func()->exposureControl->actualValue(parameter: QCameraExposureControl::SpotMeteringPoint).toPointF() : QPointF();
348}
349
350/*!
351 \fn QCameraExposure::setSpotMeteringPoint(const QPointF &point)
352
353 Allows setting the spot metering point to \a point.
354
355 \sa spotMeteringPoint()
356*/
357
358void QCameraExposure::setSpotMeteringPoint(const QPointF &point)
359{
360 if (d_func()->exposureControl)
361 d_func()->exposureControl->setValue(parameter: QCameraExposureControl::SpotMeteringPoint, value: point);
362}
363
364
365/*!
366 Returns true if the metering \a mode is supported.
367*/
368bool QCameraExposure::isMeteringModeSupported(QCameraExposure::MeteringMode mode) const
369{
370 if (!d_func()->exposureControl)
371 return false;
372
373 bool continuous = false;
374 return d_func()->exposureControl->supportedParameterRange(parameter: QCameraExposureControl::MeteringMode, continuous: &continuous)
375 .contains(t: QVariant::fromValue<QCameraExposure::MeteringMode>(value: mode));
376}
377
378int QCameraExposure::isoSensitivity() const
379{
380 return d_func()->actualExposureParameter<int>(parameter: QCameraExposureControl::ISO, defaultValue: -1);
381}
382
383/*!
384 Returns the requested ISO sensitivity
385 or -1 if automatic ISO is turned on.
386*/
387int QCameraExposure::requestedIsoSensitivity() const
388{
389 return d_func()->requestedExposureParameter<int>(parameter: QCameraExposureControl::ISO, defaultValue: -1);
390}
391
392/*!
393 Returns the list of ISO senitivities camera supports.
394
395 If the camera supports arbitrary ISO sensitivities within the supported range,
396 *\a continuous is set to true, otherwise *\a continuous is set to false.
397*/
398QList<int> QCameraExposure::supportedIsoSensitivities(bool *continuous) const
399{
400 QList<int> res;
401 QCameraExposureControl *control = d_func()->exposureControl;
402
403 bool tmp = false;
404 if (!continuous)
405 continuous = &tmp;
406
407 if (!control)
408 return res;
409
410 const auto range = control->supportedParameterRange(parameter: QCameraExposureControl::ISO, continuous);
411 for (const QVariant &value : range) {
412 bool ok = false;
413 int intValue = value.toInt(ok: &ok);
414 if (ok)
415 res.append(t: intValue);
416 else
417 qWarning() << "Incompatible ISO value type, int is expected";
418 }
419
420 return res;
421}
422
423/*!
424 \fn QCameraExposure::setManualIsoSensitivity(int iso)
425 Sets the manual sensitivity to \a iso
426*/
427
428void QCameraExposure::setManualIsoSensitivity(int iso)
429{
430 d_func()->setExposureParameter<int>(parameter: QCameraExposureControl::ISO, value: iso);
431}
432
433/*!
434 \fn QCameraExposure::setAutoIsoSensitivity()
435 Turn on auto sensitivity
436*/
437
438void QCameraExposure::setAutoIsoSensitivity()
439{
440 d_func()->resetExposureParameter(parameter: QCameraExposureControl::ISO);
441}
442
443/*!
444 \property QCameraExposure::shutterSpeed
445 \brief Camera's shutter speed in seconds.
446
447 \sa supportedShutterSpeeds(), setAutoShutterSpeed(), setManualShutterSpeed()
448*/
449
450/*!
451 \fn QCameraExposure::shutterSpeedChanged(qreal speed)
452
453 Signals that a camera's shutter \a speed has changed.
454*/
455
456/*!
457 \property QCameraExposure::isoSensitivity
458 \brief The sensor ISO sensitivity.
459
460 \sa supportedIsoSensitivities(), setAutoIsoSensitivity(), setManualIsoSensitivity()
461*/
462
463/*!
464 \property QCameraExposure::aperture
465 \brief Lens aperture is specified as an F number, the ratio of the focal length to effective aperture diameter.
466
467 \sa supportedApertures(), setAutoAperture(), setManualAperture(), requestedAperture()
468*/
469
470
471qreal QCameraExposure::aperture() const
472{
473 return d_func()->actualExposureParameter<qreal>(parameter: QCameraExposureControl::Aperture, defaultValue: -1.0);
474}
475
476/*!
477 Returns the requested manual aperture
478 or -1.0 if automatic aperture is turned on.
479*/
480qreal QCameraExposure::requestedAperture() const
481{
482 return d_func()->requestedExposureParameter<qreal>(parameter: QCameraExposureControl::Aperture, defaultValue: -1.0);
483}
484
485
486/*!
487 Returns the list of aperture values camera supports.
488 The apertures list can change depending on the focal length,
489 in such a case the apertureRangeChanged() signal is emitted.
490
491 If the camera supports arbitrary aperture values within the supported range,
492 *\a continuous is set to true, otherwise *\a continuous is set to false.
493*/
494QList<qreal> QCameraExposure::supportedApertures(bool * continuous) const
495{
496 QList<qreal> res;
497 QCameraExposureControl *control = d_func()->exposureControl;
498
499 bool tmp = false;
500 if (!continuous)
501 continuous = &tmp;
502
503 if (!control)
504 return res;
505
506 const auto range = control->supportedParameterRange(parameter: QCameraExposureControl::Aperture, continuous);
507 for (const QVariant &value : range) {
508 bool ok = false;
509 qreal realValue = value.toReal(ok: &ok);
510 if (ok)
511 res.append(t: realValue);
512 else
513 qWarning() << "Incompatible aperture value type, qreal is expected";
514 }
515
516 return res;
517}
518
519/*!
520 \fn QCameraExposure::setManualAperture(qreal aperture)
521 Sets the manual camera \a aperture value.
522*/
523
524void QCameraExposure::setManualAperture(qreal aperture)
525{
526 d_func()->setExposureParameter<qreal>(parameter: QCameraExposureControl::Aperture, value: aperture);
527}
528
529/*!
530 \fn QCameraExposure::setAutoAperture()
531 Turn on auto aperture
532*/
533
534void QCameraExposure::setAutoAperture()
535{
536 d_func()->resetExposureParameter(parameter: QCameraExposureControl::Aperture);
537}
538
539/*!
540 Returns the current shutter speed in seconds.
541*/
542
543qreal QCameraExposure::shutterSpeed() const
544{
545 return d_func()->actualExposureParameter<qreal>(parameter: QCameraExposureControl::ShutterSpeed, defaultValue: -1.0);
546}
547
548/*!
549 Returns the requested manual shutter speed in seconds
550 or -1.0 if automatic shutter speed is turned on.
551*/
552qreal QCameraExposure::requestedShutterSpeed() const
553{
554 return d_func()->requestedExposureParameter<qreal>(parameter: QCameraExposureControl::ShutterSpeed, defaultValue: -1.0);
555}
556
557/*!
558 Returns the list of shutter speed values in seconds camera supports.
559
560 If the camera supports arbitrary shutter speed values within the supported range,
561 *\a continuous is set to true, otherwise *\a continuous is set to false.
562*/
563QList<qreal> QCameraExposure::supportedShutterSpeeds(bool *continuous) const
564{
565 QList<qreal> res;
566 QCameraExposureControl *control = d_func()->exposureControl;
567
568 bool tmp = false;
569 if (!continuous)
570 continuous = &tmp;
571
572 if (!control)
573 return res;
574
575 const auto range = control->supportedParameterRange(parameter: QCameraExposureControl::ShutterSpeed, continuous);
576 for (const QVariant &value : range) {
577 bool ok = false;
578 qreal realValue = value.toReal(ok: &ok);
579 if (ok)
580 res.append(t: realValue);
581 else
582 qWarning() << "Incompatible shutter speed value type, qreal is expected";
583 }
584
585 return res;
586}
587
588/*!
589 Set the manual shutter speed to \a seconds
590*/
591
592void QCameraExposure::setManualShutterSpeed(qreal seconds)
593{
594 d_func()->setExposureParameter<qreal>(parameter: QCameraExposureControl::ShutterSpeed, value: seconds);
595}
596
597/*!
598 Turn on auto shutter speed
599*/
600
601void QCameraExposure::setAutoShutterSpeed()
602{
603 d_func()->resetExposureParameter(parameter: QCameraExposureControl::ShutterSpeed);
604}
605
606
607/*!
608 \enum QCameraExposure::FlashMode
609
610 \value FlashAuto Automatic flash.
611 \value FlashOff Flash is Off.
612 \value FlashOn Flash is On.
613 \value FlashRedEyeReduction Red eye reduction flash.
614 \value FlashFill Use flash to fillin shadows.
615 \value FlashTorch Constant light source. If supported,
616 torch can be enabled without loading the camera.
617 \value FlashVideoLight Constant light source, useful for video capture.
618 The light is turned on only while camera is active.
619 \value FlashSlowSyncFrontCurtain
620 Use the flash in conjunction with a slow shutter speed.
621 This mode allows better exposure of distant objects and/or motion blur effect.
622 \value FlashSlowSyncRearCurtain
623 The similar mode to FlashSlowSyncFrontCurtain but flash is fired at the end of exposure.
624 \value FlashManual Flash power is manualy set.
625*/
626
627/*!
628 \enum QCameraExposure::ExposureMode
629
630 \value ExposureAuto Automatic mode.
631 \value ExposureManual Manual mode.
632 \value ExposurePortrait Portrait exposure mode.
633 \value ExposureNight Night mode.
634 \value ExposureBacklight Backlight exposure mode.
635 \value ExposureSpotlight Spotlight exposure mode.
636 \value ExposureSports Spots exposure mode.
637 \value ExposureSnow Snow exposure mode.
638 \value ExposureBeach Beach exposure mode.
639 \value ExposureLargeAperture Use larger aperture with small depth of field.
640 \value ExposureSmallAperture Use smaller aperture.
641 \value ExposureAction Action mode. Since 5.5
642 \value ExposureLandscape Landscape mode. Since 5.5
643 \value ExposureNightPortrait Night portrait mode. Since 5.5
644 \value ExposureTheatre Theatre mode. Since 5.5
645 \value ExposureSunset Sunset mode. Since 5.5
646 \value ExposureSteadyPhoto Steady photo mode. Since 5.5
647 \value ExposureFireworks Fireworks mode. Since 5.5
648 \value ExposureParty Party mode. Since 5.5
649 \value ExposureCandlelight Candlelight mode. Since 5.5
650 \value ExposureBarcode Barcode mode. Since 5.5
651 \value ExposureModeVendor The base value for device specific exposure modes.
652*/
653
654/*!
655 \enum QCameraExposure::MeteringMode
656
657 \value MeteringMatrix Matrix metering mode.
658 \value MeteringAverage Center weighted average metering mode.
659 \value MeteringSpot Spot metering mode.
660*/
661
662/*!
663 \property QCameraExposure::flashReady
664 \brief Indicates if the flash is charged and ready to use.
665*/
666
667/*!
668 \fn void QCameraExposure::flashReady(bool ready)
669
670 Signal the flash \a ready status has changed.
671*/
672
673/*!
674 \fn void QCameraExposure::apertureChanged(qreal value)
675
676 Signal emitted when aperature changes to \a value.
677*/
678
679/*!
680 \fn void QCameraExposure::apertureRangeChanged()
681
682 Signal emitted when aperature range has changed.
683*/
684
685
686/*!
687 \fn void QCameraExposure::shutterSpeedRangeChanged()
688
689 Signal emitted when the shutter speed range has changed.
690*/
691
692
693/*!
694 \fn void QCameraExposure::isoSensitivityChanged(int value)
695
696 Signal emitted when sensitivity changes to \a value.
697*/
698
699/*!
700 \fn void QCameraExposure::exposureCompensationChanged(qreal value)
701
702 Signal emitted when the exposure compensation changes to \a value.
703*/
704
705QT_END_NAMESPACE
706
707#include "moc_qcameraexposure.cpp"
708

source code of qtmultimedia/src/multimedia/camera/qcameraexposure.cpp