Revision control
++ // Copyright (C) 2022 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
++
++ #include "qwasmimagecapture_p.h"
++
++ #include "qwasmmediacapturesession_p.h"
++ #include "qwasmcamera_p.h"
++ #include "qwasmvideosink_p.h"
++
++ #include <QtGui/qimagewriter.h>
++ #include <QtCore/qdir.h>
++ #include <QtCore/private/qstdweb_p.h>
++
++ #include <emscripten/val.h>
++
++ QT_BEGIN_NAMESPACE
++
++ using namespace Qt::Literals;
++
++ Q_LOGGING_CATEGORY(qWasmImageCapture, "qt.multimedia.wasm.imagecapture")
++ /* TODO
++ signals:
++ imageExposed
++ */
++ QWasmImageCapture::QWasmImageCapture(QImageCapture *parent) : QPlatformImageCapture(parent) { }
++
++ QWasmImageCapture::~QWasmImageCapture() = default;
++
++ int QWasmImageCapture::capture(const QString &fileName)
++ {
++ if (!isReadyForCapture()) {
++ Q_EMIT error(m_lastId, QImageCapture::NotReadyError, msgCameraNotReady());
++ return -1;
++ }
++
++ QString imageFilenName;
++ if (fileName.isEmpty())
++ imageFilenName = QDir::homePath() + u"/image.jpg"_s;
++ else
++ imageFilenName = fileName;
++
++ QImage image = takePicture();
++ if (image.isNull())
++ return -1;
++
++ QImageWriter writer(imageFilenName);
++ // TODO
++ // writer.setQuality(quality);
++ // writer.setFormat("png");
++
++ if (writer.write(image)) {
++ qCDebug(qWasmImageCapture) << Q_FUNC_INFO << "image saved";
++ Q_EMIT imageSaved(m_lastId, fileName);
++ } else {
++ QImageCapture::Error err = (writer.error() == QImageWriter::UnsupportedFormatError)
++ ? QImageCapture::FormatError
++ : QImageCapture::ResourceError;
++
++ Q_EMIT error(m_lastId, err, writer.errorString());
++ }
++
++ return m_lastId;
++ }
++
++ int QWasmImageCapture::captureToBuffer()
++ {
++ if (!isReadyForCapture()) {
++ Q_EMIT error(m_lastId, QImageCapture::NotReadyError, msgCameraNotReady());
++ return -1;
++ }
++
++ QImage image = takePicture();
++ if (image.isNull())
++ return -1;
++
++ Q_EMIT imageCaptured(m_lastId, image);
++ return m_lastId;
++ }
++
++ QImage QWasmImageCapture::takePicture()
++ {
++ m_lastId++;
++
++ // Try the fast path: grab the current frame and convert via RHI.
++ QVideoFrame thisFrame = m_captureSession->videoSink()->videoFrame();
++ QImage image;
++ if (thisFrame.isValid()) {
++ Q_EMIT imageAvailable(m_lastId, thisFrame);
++ image = thisFrame.toImage();
++ }
++
++ if (image.isNull()) {
++ qCDebug(qWasmImageCapture) << Q_FUNC_INFO << "image capture failed";
++ Q_EMIT error(m_lastId, QImageCapture::ResourceError, QStringLiteral("Capture failed"));
++ return QImage();
++ }
++
++ Q_EMIT imageCaptured(m_lastId, image);
++ if (m_settings.resolution().isValid() && m_settings.resolution() != image.size())
++ image = image.scaled(m_settings.resolution());
++
++ return image;
++ }
++
++ bool QWasmImageCapture::isReadyForCapture() const
++ {
++ return m_isReadyForCapture;
++ }
++
++ QImageEncoderSettings QWasmImageCapture::imageSettings() const
++ {
++ return m_settings;
++ }
++
++ void QWasmImageCapture::setImageSettings(const QImageEncoderSettings &settings)
++ {
++ m_settings = settings;
++ }
++
++ void QWasmImageCapture::setReadyForCapture(bool isReady)
++ {
++ if (m_isReadyForCapture != isReady) {
++ m_isReadyForCapture = isReady;
++ Q_EMIT readyForCaptureChanged(m_isReadyForCapture);
++ }
++ }
++
++ void QWasmImageCapture::setCaptureSession(QPlatformMediaCaptureSession *session)
++ {
++ QWasmMediaCaptureSession *captureSession = static_cast<QWasmMediaCaptureSession *>(session);
++ // nullptr clears
++ if (m_captureSession == captureSession)
++ return;
++
++ if (captureSession) {
++ m_lastId = 0;
++ m_captureSession = captureSession;
++ }
++ m_captureSession = captureSession;
++ }
++
++ QT_END_NAMESPACE