From 7d3b430b9ee53343f43181ed82f7198dc1884a42 Mon Sep 17 00:00:00 2001 From: Nikolaos Ftylitakis Date: Tue, 7 Dec 2021 23:34:44 +0200 Subject: [PATCH] Fix unmap in case of early return of frame processing Added support to image rotate based on the orientation of the frame #199 --- src/QZXingFilterVideoSink.cpp | 80 +++++++++++++++++++++++------------ src/QZXingFilterVideoSink.h | 5 +++ 2 files changed, 58 insertions(+), 27 deletions(-) diff --git a/src/QZXingFilterVideoSink.cpp b/src/QZXingFilterVideoSink.cpp index 49f1f6e..1de7aaa 100644 --- a/src/QZXingFilterVideoSink.cpp +++ b/src/QZXingFilterVideoSink.cpp @@ -37,6 +37,21 @@ void QZXingFilter::handleDecodingFinished(bool succeeded) emit isDecodingChanged(); } +void QZXingFilter::setOrientation(int orientation) +{ + if (orientation_ == orientation) { + return; + } + + orientation_ = orientation; + emit orientationChanged(orientation_); +} + +int QZXingFilter::orientation() const +{ + return orientation_; +} + void QZXingFilter::setVideoSink(QObject *videoSink){ m_videoSink = qobject_cast(videoSink); @@ -52,37 +67,48 @@ void QZXingFilter::processFrame(const QVideoFrame &frame) { const QVideoFrame &f = frame; #endif // Q_OS_ANDROID - if(isDecoding() || !processThread.isFinished()) return; + if(!isDecoding() && processThread.isFinished()){ + decoding = true; - decoding = true; + QImage image = f.toImage(); + processThread = QtConcurrent::run([=](){ + if(image.isNull()) + { + qDebug() << "QZXingFilter error: Cant create image file to process."; + decoding = false; + return; + } - QImage image = f.toImage(); + QImage frameToProcess(image); + const QRect& rect = captureRect.toRect(); + + if (captureRect.isValid() && frameToProcess.size() != rect.size()) { + frameToProcess = image.copy(rect); + } + + if (!orientation_) { + decoder.decodeImage(frameToProcess); + } else { + QTransform transformation; + transformation.translate(frameToProcess.rect().center().x(), frameToProcess.rect().center().y()); + transformation.rotate(-orientation_); + + QImage translatedImage = frameToProcess.transformed(transformation); + + decoder.decodeImage(translatedImage); + } + + // static int i=0; + // qDebug() << "image.size()" << frameToProcess.size(); + // qDebug() << "image.format()" << frameToProcess.format(); + // const QString path = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation) + "/qrtest/test_" + QString::number(i++ % 100) + ".png"; + // qDebug() << "saving image" << i << "at:" << path << frameToProcess.save(path); + + decoder.decodeImage(frameToProcess, frameToProcess.width(), frameToProcess.height()); + }); + } #ifdef Q_OS_ANDROID f.unmap(); #endif - - processThread = QtConcurrent::run([=](){ - if(image.isNull()) - { - qDebug() << "QZXingFilter error: Cant create image file to process."; - decoding = false; - return; - } - - QImage frameToProcess(image); - const QRect& rect = captureRect.toRect(); - - if (captureRect.isValid() && frameToProcess.size() != rect.size()) { - frameToProcess = image.copy(rect); - } - -// static int i=0; -// qDebug() << "image.size()" << frameToProcess.size(); -// qDebug() << "image.format()" << frameToProcess.format(); -// const QString path = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation) + "/qrtest/test_" + QString::number(i++ % 100) + ".png"; -// qDebug() << "saving image" << i << "at:" << path << frameToProcess.save(path); - - decoder.decodeImage(frameToProcess, frameToProcess.width(), frameToProcess.height()); - }); } diff --git a/src/QZXingFilterVideoSink.h b/src/QZXingFilterVideoSink.h index 60b921b..76d4d55 100644 --- a/src/QZXingFilterVideoSink.h +++ b/src/QZXingFilterVideoSink.h @@ -32,22 +32,27 @@ class QZXingFilter : public QObject Q_PROPERTY(QZXing* decoder READ getDecoder) Q_PROPERTY(QRectF captureRect MEMBER captureRect NOTIFY captureRectChanged) Q_PROPERTY(QObject* videoSink WRITE setVideoSink) + Q_PROPERTY(int orientation READ orientation WRITE setOrientation NOTIFY orientationChanged) signals: void isDecodingChanged(); void decodingFinished(bool succeeded, int decodeTime); void decodingStarted(); void captureRectChanged(); + void orientationChanged(int orientation); private slots: void handleDecodingStarted(); void handleDecodingFinished(bool succeeded); void processFrame(const QVideoFrame &frame); + void setOrientation(int orientation); + int orientation() const; private: /// Attributes QZXing decoder; bool decoding; QRectF captureRect; + int orientation_; QVideoSink *m_videoSink; QFuture processThread;