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
qwindowsimagecapture.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
5
6#include <mediacapture/qwindowsmediacapture_p.h>
7#include <mediacapture/qwindowsmediadevicesession_p.h>
8
9#include <QtMultimedia/private/qmediastoragelocation_p.h>
10#include <QtGui/qimagewriter.h>
11#include <QtConcurrent/qtconcurrentrun.h>
12
14
15using namespace Qt::StringLiterals;
16
17QWindowsImageCapture::QWindowsImageCapture(QImageCapture *parent)
18 : QPlatformImageCapture(parent)
19{
20}
21
23
25{
26 if (!m_mediaDeviceSession)
27 return false;
28 return !m_capturing && m_mediaDeviceSession->isActive() && !m_mediaDeviceSession->activeCamera().isNull();
29}
30
31int QWindowsImageCapture::capture(const QString &fileName)
32{
33 auto ext = writerFormat(m_settings.format());
34 auto path = QMediaStorageLocation::generateFileName(fileName, QStandardPaths::PicturesLocation, ext);
35 return doCapture(path);
36}
37
39{
40 return doCapture(QString());
41}
42
43int QWindowsImageCapture::doCapture(const QString &fileName)
44{
46 return -1;
47 m_fileName = fileName;
48 m_capturing = true;
49 return m_captureId;
50}
51
53{
54 return m_settings;
55}
56
57void QWindowsImageCapture::setImageSettings(const QImageEncoderSettings &settings)
58{
59 m_settings = settings;
60}
61
62void QWindowsImageCapture::setCaptureSession(QPlatformMediaCaptureSession *session)
63{
64 QWindowsMediaCaptureService *captureService = static_cast<QWindowsMediaCaptureService *>(session);
65 if (m_captureService == captureService)
66 return;
67
68 auto readyForCapture = isReadyForCapture();
69 if (m_mediaDeviceSession)
70 disconnect(m_mediaDeviceSession, nullptr, this, nullptr);
71
72 m_captureService = captureService;
73 if (!m_captureService) {
74 if (readyForCapture)
75 emit readyForCaptureChanged(false);
76 m_mediaDeviceSession = nullptr;
77 return;
78 }
79
80 m_mediaDeviceSession = m_captureService->session();
81 Q_ASSERT(m_mediaDeviceSession);
82
83 if (isReadyForCapture() != readyForCapture)
84 emit readyForCaptureChanged(isReadyForCapture());
85
86 connect(m_mediaDeviceSession, &QWindowsMediaDeviceSession::readyForCaptureChanged,
87 this, &QWindowsImageCapture::readyForCaptureChanged);
88
89 connect(m_mediaDeviceSession, &QWindowsMediaDeviceSession::videoFrameChanged,
90 this, &QWindowsImageCapture::handleVideoFrameChanged);
91}
92
93void QWindowsImageCapture::handleVideoFrameChanged(const QVideoFrame &frame)
94{
95 if (m_capturing) {
96
97 QImage image = frame.toImage();
98
99 QSize size = m_settings.resolution();
100 if (size.isValid() && image.size() != size) {
101 image = image.scaled(size, Qt::KeepAspectRatioByExpanding);
102 if (image.size() != size) {
103 int xoff = (image.size().width() - size.width()) / 2;
104 int yoff = (image.size().height() - size.height()) / 2;
105 image = image.copy(xoff, yoff, size.width(), size.height());
106 }
107 }
108
109 emit imageExposed(m_captureId);
110 emit imageAvailable(m_captureId, frame);
111 emit imageCaptured(m_captureId, image);
112
113 QMediaMetaData metaData = this->metaData();
114 metaData.insert(QMediaMetaData::Date, QDateTime::currentDateTime());
115 metaData.insert(QMediaMetaData::Resolution, size);
116
117 emit imageMetadataAvailable(m_captureId, metaData);
118
119 if (!m_fileName.isEmpty()) {
120
121 (void)QtConcurrent::run(&QWindowsImageCapture::saveImage, this,
122 m_captureId, m_fileName, image, metaData, m_settings);
123 }
124
125 ++m_captureId;
126 m_capturing = false;
127 }
128}
129
130void QWindowsImageCapture::saveImage(int captureId, const QString &fileName,
131 const QImage &image, const QMediaMetaData &metaData,
132 const QImageEncoderSettings &settings)
133{
134 QImageWriter imageWriter;
135 imageWriter.setFileName(fileName);
136
137 QString format = writerFormat(settings.format());
138 imageWriter.setFormat(format.toUtf8());
139
140 int quality = writerQuality(format, settings.quality());
141 if (quality > -1)
142 imageWriter.setQuality(quality);
143
144 for (auto key : metaData.keys())
145 imageWriter.setText(QMediaMetaData::metaDataKeyToString(key),
146 metaData.stringValue(key));
147
148 imageWriter.write(image);
149
150 QMetaObject::invokeMethod(this, [this, captureId, fileName] {
151 emit imageSaved(captureId, fileName);
152 }, Qt::QueuedConnection);
153}
154
155QString QWindowsImageCapture::writerFormat(QImageCapture::FileFormat reqFormat)
156{
157 QString format;
158
159 switch (reqFormat) {
160 case QImageCapture::FileFormat::JPEG:
161 format = u"jpg"_s;
162 break;
163 case QImageCapture::FileFormat::PNG:
164 format = u"png"_s;
165 break;
166 case QImageCapture::FileFormat::WebP:
167 format = u"webp"_s;
168 break;
169 case QImageCapture::FileFormat::Tiff:
170 format = u"tiff"_s;
171 break;
172 default:
173 format = u"jpg"_s;
174 }
175
176 auto supported = QImageWriter::supportedImageFormats();
177 for (const auto &f : supported)
178 if (format.compare(QString::fromUtf8(f), Qt::CaseInsensitive) == 0)
179 return format;
180
181 return u"jpg"_s;
182}
183
184int QWindowsImageCapture::writerQuality(const QString &writerFormat,
185 QImageCapture::Quality quality)
186{
187 if (writerFormat.compare(u"jpg", Qt::CaseInsensitive) == 0 ||
188 writerFormat.compare(u"jpeg", Qt::CaseInsensitive) == 0) {
189
190 switch (quality) {
191 case QImageCapture::Quality::VeryLowQuality:
192 return 10;
193 case QImageCapture::Quality::LowQuality:
194 return 30;
195 case QImageCapture::Quality::NormalQuality:
196 return 75;
197 case QImageCapture::Quality::HighQuality:
198 return 90;
199 case QImageCapture::Quality::VeryHighQuality:
200 return 98;
201 default:
202 return 75;
203 }
204 }
205 return -1;
206}
207
208QT_END_NAMESPACE
209
210#include "moc_qwindowsimagecapture_p.cpp"
int capture(const QString &fileName) override
virtual ~QWindowsImageCapture()
QImageEncoderSettings imageSettings() const override
void setImageSettings(const QImageEncoderSettings &settings) override
void setCaptureSession(QPlatformMediaCaptureSession *session)
bool isReadyForCapture() const override
QWindowsMediaDeviceSession * session() const
Combined button and popup list for selecting options.