Camera Example▲
Sélectionnez
/**
**************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** 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.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
***************************************************************************
*/
#include
"camera.h"
#include
"ui_camera.h"
#include
"videosettings.h"
#include
"imagesettings.h"
#include <QMediaService>
#include <QMediaRecorder>
#include <QCameraViewfinder>
#include <QCameraInfo>
#include <QMediaMetaData>
#include <QMessageBox>
#include <QPalette>
#include <QtWidgets>
Q_DECLARE_METATYPE(QCameraInfo)
Camera::
Camera() : ui(new
Ui::
Camera)
{
ui-&
gt;setupUi(this
);
//Camera devices:
QActionGroup *
videoDevicesGroup =
new
QActionGroup(this
);
videoDevicesGroup-&
gt;setExclusive(true
);
const
QList&
lt;QCameraInfo&
gt; availableCameras =
QCameraInfo::
availableCameras();
for
(const
QCameraInfo &
amp;cameraInfo : availableCameras) {
QAction *
videoDeviceAction =
new
QAction(cameraInfo.description(), videoDevicesGroup);
videoDeviceAction-&
gt;setCheckable(true
);
videoDeviceAction-&
gt;setData(QVariant::
fromValue(cameraInfo));
if
(cameraInfo ==
QCameraInfo::
defaultCamera())
videoDeviceAction-&
gt;setChecked(true
);
ui-&
gt;menuDevices-&
gt;addAction(videoDeviceAction);
}
connect(videoDevicesGroup, &
amp;QActionGroup::
triggered, this
, &
amp;Camera::
updateCameraDevice);
connect(ui-&
gt;captureWidget, &
amp;QTabWidget::
currentChanged, this
, &
amp;Camera::
updateCaptureMode);
setCamera(QCameraInfo::
defaultCamera());
}
void
Camera::
setCamera(const
QCameraInfo &
amp;cameraInfo)
{
m_camera.reset(new
QCamera(cameraInfo));
connect(m_camera.data(), &
amp;QCamera::
stateChanged, this
, &
amp;Camera::
updateCameraState);
connect(m_camera.data(), QOverload&
lt;QCamera::
Error&
gt;::
of(&
amp;QCamera::
error), this
, &
amp;Camera::
displayCameraError);
m_mediaRecorder.reset(new
QMediaRecorder(m_camera.data()));
connect(m_mediaRecorder.data(), &
amp;QMediaRecorder::
stateChanged, this
, &
amp;Camera::
updateRecorderState);
m_imageCapture.reset(new
QCameraImageCapture(m_camera.data()));
connect(m_mediaRecorder.data(), &
amp;QMediaRecorder::
durationChanged, this
, &
amp;Camera::
updateRecordTime);
connect(m_mediaRecorder.data(), QOverload&
lt;QMediaRecorder::
Error&
gt;::
of(&
amp;QMediaRecorder::
error),
this
, &
amp;Camera::
displayRecorderError);
m_mediaRecorder-&
gt;setMetaData(QMediaMetaData::
Title, QVariant(QLatin1String("Test Title"
)));
connect(ui-&
gt;exposureCompensation, &
amp;QAbstractSlider::
valueChanged, this
, &
amp;Camera::
setExposureCompensation);
m_camera-&
gt;setViewfinder(ui-&
gt;viewfinder);
updateCameraState(m_camera-&
gt;state());
updateLockStatus(m_camera-&
gt;lockStatus(), QCamera::
UserRequest);
updateRecorderState(m_mediaRecorder-&
gt;state());
connect(m_imageCapture.data(), &
amp;QCameraImageCapture::
readyForCaptureChanged, this
, &
amp;Camera::
readyForCapture);
connect(m_imageCapture.data(), &
amp;QCameraImageCapture::
imageCaptured, this
, &
amp;Camera::
processCapturedImage);
connect(m_imageCapture.data(), &
amp;QCameraImageCapture::
imageSaved, this
, &
amp;Camera::
imageSaved);
connect(m_imageCapture.data(), QOverload&
lt;int
, QCameraImageCapture::
Error, const
QString &
amp;&
gt;::
of(&
amp;QCameraImageCapture::
error),
this
, &
amp;Camera::
displayCaptureError);
connect(m_camera.data(), QOverload&
lt;QCamera::
LockStatus, QCamera::
LockChangeReason&
gt;::
of(&
amp;QCamera::
lockStatusChanged),
this
, &
amp;Camera::
updateLockStatus);
ui-&
gt;captureWidget-&
gt;setTabEnabled(0
, (m_camera-&
gt;isCaptureModeSupported(QCamera::
CaptureStillImage)));
ui-&
gt;captureWidget-&
gt;setTabEnabled(1
, (m_camera-&
gt;isCaptureModeSupported(QCamera::
CaptureVideo)));
updateCaptureMode();
m_camera-&
gt;start();
}
void
Camera::
keyPressEvent(QKeyEvent *
event)
{
if
(event-&
gt;isAutoRepeat())
return
;
switch
(event-&
gt;key()) {
case
Qt::
Key_CameraFocus:
displayViewfinder();
m_camera-&
gt;searchAndLock();
event-&
gt;accept();
break
;
case
Qt::
Key_Camera:
if
(m_camera-&
gt;captureMode() ==
QCamera::
CaptureStillImage) {
takeImage();
}
else
{
if
(m_mediaRecorder-&
gt;state() ==
QMediaRecorder::
RecordingState)
stop();
else
record();
}
event-&
gt;accept();
break
;
default
:
QMainWindow::
keyPressEvent(event);
}
}
void
Camera::
keyReleaseEvent(QKeyEvent *
event)
{
if
(event-&
gt;isAutoRepeat())
return
;
switch
(event-&
gt;key()) {
case
Qt::
Key_CameraFocus:
m_camera-&
gt;unlock();
break
;
default
:
QMainWindow::
keyReleaseEvent(event);
}
}
void
Camera::
updateRecordTime()
{
QString str =
QString("Recorded %1 sec"
).arg(m_mediaRecorder-&
gt;duration()/
1000
);
ui-&
gt;statusbar-&
gt;showMessage(str);
}
void
Camera::
processCapturedImage(int
requestId, const
QImage&
amp; img)
{
Q_UNUSED(requestId);
QImage scaledImage =
img.scaled(ui-&
gt;viewfinder-&
gt;size(),
Qt::
KeepAspectRatio,
Qt::
SmoothTransformation);
ui-&
gt;lastImagePreviewLabel-&
gt;setPixmap(QPixmap::
fromImage(scaledImage));
// Display captured image for 4 seconds.
displayCapturedImage();
QTimer::
singleShot(4000
, this
, &
amp;Camera::
displayViewfinder);
}
void
Camera::
configureCaptureSettings()
{
switch
(m_camera-&
gt;captureMode()) {
case
QCamera::
CaptureStillImage:
configureImageSettings();
break
;
case
QCamera::
CaptureVideo:
configureVideoSettings();
break
;
default
:
break
;
}
}
void
Camera::
configureVideoSettings()
{
VideoSettings settingsDialog(m_mediaRecorder.data());
settingsDialog.setWindowFlags(settingsDialog.windowFlags() &
amp; ~
Qt::
WindowContextHelpButtonHint);
settingsDialog.setAudioSettings(m_audioSettings);
settingsDialog.setVideoSettings(m_videoSettings);
settingsDialog.setFormat(m_videoContainerFormat);
if
(settingsDialog.exec()) {
m_audioSettings =
settingsDialog.audioSettings();
m_videoSettings =
settingsDialog.videoSettings();
m_videoContainerFormat =
settingsDialog.format();
m_mediaRecorder-&
gt;setEncodingSettings(
m_audioSettings,
m_videoSettings,
m_videoContainerFormat);
m_camera-&
gt;unload();
m_camera-&
gt;start();
}
}
void
Camera::
configureImageSettings()
{
ImageSettings settingsDialog(m_imageCapture.data());
settingsDialog.setWindowFlags(settingsDialog.windowFlags() &
amp; ~
Qt::
WindowContextHelpButtonHint);
settingsDialog.setImageSettings(m_imageSettings);
if
(settingsDialog.exec()) {
m_imageSettings =
settingsDialog.imageSettings();
m_imageCapture-&
gt;setEncodingSettings(m_imageSettings);
}
}
void
Camera::
record()
{
m_mediaRecorder-&
gt;record();
updateRecordTime();
}
void
Camera::
pause()
{
m_mediaRecorder-&
gt;pause();
}
void
Camera::
stop()
{
m_mediaRecorder-&
gt;stop();
}
void
Camera::
setMuted(bool
muted)
{
m_mediaRecorder-&
gt;setMuted(muted);
}
void
Camera::
toggleLock()
{
switch
(m_camera-&
gt;lockStatus()) {
case
QCamera::
Searching:
case
QCamera::
Locked:
m_camera-&
gt;unlock();
break
;
case
QCamera::
Unlocked:
m_camera-&
gt;searchAndLock();
}
}
void
Camera::
updateLockStatus(QCamera::
LockStatus status, QCamera::
LockChangeReason reason)
{
QColor indicationColor =
Qt::
black;
switch
(status) {
case
QCamera::
Searching:
indicationColor =
Qt::
yellow;
ui-&
gt;statusbar-&
gt;showMessage(tr("Focusing..."
));
ui-&
gt;lockButton-&
gt;setText(tr("Focusing..."
));
break
;
case
QCamera::
Locked:
indicationColor =
Qt::
darkGreen;
ui-&
gt;lockButton-&
gt;setText(tr("Unlock"
));
ui-&
gt;statusbar-&
gt;showMessage(tr("Focused"
), 2000
);
break
;
case
QCamera::
Unlocked:
indicationColor =
reason ==
QCamera::
LockFailed ? Qt::
red : Qt::
black;
ui-&
gt;lockButton-&
gt;setText(tr("Focus"
));
if
(reason ==
QCamera::
LockFailed)
ui-&
gt;statusbar-&
gt;showMessage(tr("Focus Failed"
), 2000
);
}
QPalette palette =
ui-&
gt;lockButton-&
gt;palette();
palette.setColor(QPalette::
ButtonText, indicationColor);
ui-&
gt;lockButton-&
gt;setPalette(palette);
}
void
Camera::
takeImage()
{
m_isCapturingImage =
true
;
m_imageCapture-&
gt;capture();
}
void
Camera::
displayCaptureError(int
id, const
QCameraImageCapture::
Error error, const
QString &
amp;errorString)
{
Q_UNUSED(id);
Q_UNUSED(error);
QMessageBox::
warning(this
, tr("Image Capture Error"
), errorString);
m_isCapturingImage =
false
;
}
void
Camera::
startCamera()
{
m_camera-&
gt;start();
}
void
Camera::
stopCamera()
{
m_camera-&
gt;stop();
}
void
Camera::
updateCaptureMode()
{
int
tabIndex =
ui-&
gt;captureWidget-&
gt;currentIndex();
QCamera::
CaptureModes captureMode =
tabIndex ==
0
? QCamera::
CaptureStillImage : QCamera::
CaptureVideo;
if
(m_camera-&
gt;isCaptureModeSupported(captureMode))
m_camera-&
gt;setCaptureMode(captureMode);
}
void
Camera::
updateCameraState(QCamera::
State state)
{
switch
(state) {
case
QCamera::
ActiveState:
ui-&
gt;actionStartCamera-&
gt;setEnabled(false
);
ui-&
gt;actionStopCamera-&
gt;setEnabled(true
);
ui-&
gt;captureWidget-&
gt;setEnabled(true
);
ui-&
gt;actionSettings-&
gt;setEnabled(true
);
break
;
case
QCamera::
UnloadedState:
case
QCamera::
LoadedState:
ui-&
gt;actionStartCamera-&
gt;setEnabled(true
);
ui-&
gt;actionStopCamera-&
gt;setEnabled(false
);
ui-&
gt;captureWidget-&
gt;setEnabled(false
);
ui-&
gt;actionSettings-&
gt;setEnabled(false
);
}
}
void
Camera::
updateRecorderState(QMediaRecorder::
State state)
{
switch
(state) {
case
QMediaRecorder::
StoppedState:
ui-&
gt;recordButton-&
gt;setEnabled(true
);
ui-&
gt;pauseButton-&
gt;setEnabled(true
);
ui-&
gt;stopButton-&
gt;setEnabled(false
);
break
;
case
QMediaRecorder::
PausedState:
ui-&
gt;recordButton-&
gt;setEnabled(true
);
ui-&
gt;pauseButton-&
gt;setEnabled(false
);
ui-&
gt;stopButton-&
gt;setEnabled(true
);
break
;
case
QMediaRecorder::
RecordingState:
ui-&
gt;recordButton-&
gt;setEnabled(false
);
ui-&
gt;pauseButton-&
gt;setEnabled(true
);
ui-&
gt;stopButton-&
gt;setEnabled(true
);
break
;
}
}
void
Camera::
setExposureCompensation(int
index)
{
m_camera-&
gt;exposure()-&
gt;setExposureCompensation(index*
0.5
);
}
void
Camera::
displayRecorderError()
{
QMessageBox::
warning(this
, tr("Capture Error"
), m_mediaRecorder-&
gt;errorString());
}
void
Camera::
displayCameraError()
{
QMessageBox::
warning(this
, tr("Camera Error"
), m_camera-&
gt;errorString());
}
void
Camera::
updateCameraDevice(QAction *
action)
{
setCamera(qvariant_cast&
lt;QCameraInfo&
gt;(action-&
gt;data()));
}
void
Camera::
displayViewfinder()
{
ui-&
gt;stackedWidget-&
gt;setCurrentIndex(0
);
}
void
Camera::
displayCapturedImage()
{
ui-&
gt;stackedWidget-&
gt;setCurrentIndex(1
);
}
void
Camera::
readyForCapture(bool
ready)
{
ui-&
gt;takeImageButton-&
gt;setEnabled(ready);
}
void
Camera::
imageSaved(int
id, const
QString &
amp;fileName)
{
Q_UNUSED(id);
ui-&
gt;statusbar-&
gt;showMessage(tr("Captured
\"
%1
\"
"
).arg(QDir::
toNativeSeparators(fileName)));
m_isCapturingImage =
false
;
if
(m_applicationExiting)
close();
}
void
Camera::
closeEvent(QCloseEvent *
event)
{
if
(m_isCapturingImage) {
setEnabled(false
);
m_applicationExiting =
true
;
event-&
gt;ignore();
}
else
{
event-&
gt;accept();
}
}