forked from feather/feather
Compare commits
13 Commits
8b9e68e2ad
...
5ea7959ab2
Author | SHA1 | Date |
---|---|---|
mrdeveloper | 5ea7959ab2 | 4 years ago |
tobtoht | 48fa938dba | 4 years ago |
tobtoht | b7ddeb5b81 | 4 years ago |
mrdeveloper | 3cb5c2b692 | 4 years ago |
mrdeveloper | 43ae5de534 | 4 years ago |
mrdeveloper | cd1e93784a | 4 years ago |
mrdeveloper | 442aced06f | 4 years ago |
dsc | 485fb89941 | 4 years ago |
dsc | df280cdd91 | 4 years ago |
dsc | 9b96ece2f9 | 4 years ago |
dsc | a44087b750 | 4 years ago |
dsc | 70cbf59ce8 | 4 years ago |
dsc | 4aeaf2660f | 4 years ago |
@ -0,0 +1,4 @@
|
|||||||
|
file(GLOB_RECURSE SRC_SOURCES *.cpp)
|
||||||
|
file(GLOB_RECURSE SRC_HEADERS *.h)
|
||||||
|
|
||||||
|
|
@ -0,0 +1,69 @@
|
|||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
// Copyright (c) 2014-2020, The Monero Project.
|
||||||
|
|
||||||
|
#include "QrCodeScanner.h"
|
||||||
|
#include <WalletManager.h>
|
||||||
|
#include <QVideoProbe>
|
||||||
|
#include <QCamera>
|
||||||
|
|
||||||
|
QrCodeScanner::QrCodeScanner(QObject *parent)
|
||||||
|
: QObject(parent)
|
||||||
|
, m_processTimerId(-1)
|
||||||
|
, m_processInterval(750)
|
||||||
|
, m_enabled(true)
|
||||||
|
{
|
||||||
|
m_probe = new QVideoProbe(this);
|
||||||
|
m_thread = new QrScanThread(this);
|
||||||
|
m_thread->start();
|
||||||
|
QObject::connect(m_thread, SIGNAL(decoded(int, QString)), this, SIGNAL(decoded(int, QString)));
|
||||||
|
QObject::connect(m_thread, SIGNAL(notifyError(const QString &, bool)), this, SIGNAL(notifyError(const QString &, bool)));
|
||||||
|
connect(m_probe, SIGNAL(videoFrameProbed(const QVideoFrame &)),
|
||||||
|
this, SLOT(processFrame(const QVideoFrame &)));
|
||||||
|
}
|
||||||
|
void QrCodeScanner::setSource(QCamera *camera)
|
||||||
|
{
|
||||||
|
m_probe->setSource((QMediaObject *)camera);
|
||||||
|
}
|
||||||
|
void QrCodeScanner::processFrame(const QVideoFrame &frame)
|
||||||
|
{
|
||||||
|
if(frame.isValid()){
|
||||||
|
m_curFrame = frame;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool QrCodeScanner::enabled() const
|
||||||
|
{
|
||||||
|
return m_enabled;
|
||||||
|
}
|
||||||
|
void QrCodeScanner::setEnabled(bool enabled)
|
||||||
|
{
|
||||||
|
m_enabled = enabled;
|
||||||
|
if(!enabled && (m_processTimerId != -1) )
|
||||||
|
{
|
||||||
|
this->killTimer(m_processTimerId);
|
||||||
|
m_processTimerId = -1;
|
||||||
|
}
|
||||||
|
else if (enabled && (m_processTimerId == -1) )
|
||||||
|
{
|
||||||
|
m_processTimerId = this->startTimer(m_processInterval);
|
||||||
|
}
|
||||||
|
emit enabledChanged();
|
||||||
|
}
|
||||||
|
void QrCodeScanner::timerEvent(QTimerEvent *event)
|
||||||
|
{
|
||||||
|
if( (event->timerId() == m_processTimerId) ){
|
||||||
|
m_thread->addFrame(m_curFrame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QrCodeScanner::~QrCodeScanner()
|
||||||
|
{
|
||||||
|
m_thread->stop();
|
||||||
|
m_thread->quit();
|
||||||
|
if(!m_thread->wait(5000))
|
||||||
|
{
|
||||||
|
m_thread->terminate();
|
||||||
|
m_thread->wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,50 @@
|
|||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
// Copyright (c) 2014-2020, The Monero Project.
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef QRCODESCANNER_H_
|
||||||
|
#define QRCODESCANNER_H_
|
||||||
|
|
||||||
|
#include <QImage>
|
||||||
|
#include <QVideoFrame>
|
||||||
|
#include "QrScanThread.h"
|
||||||
|
|
||||||
|
class QVideoProbe;
|
||||||
|
class QCamera;
|
||||||
|
|
||||||
|
class QrCodeScanner : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
|
||||||
|
|
||||||
|
public:
|
||||||
|
QrCodeScanner(QObject *parent = Q_NULLPTR);
|
||||||
|
~QrCodeScanner();
|
||||||
|
void setSource(QCamera*);
|
||||||
|
|
||||||
|
bool enabled() const;
|
||||||
|
void setEnabled(bool enabled);
|
||||||
|
|
||||||
|
public Q_SLOTS:
|
||||||
|
void processFrame(const QVideoFrame &frame);
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
void enabledChanged();
|
||||||
|
|
||||||
|
void decoded(int type, const QString &data);
|
||||||
|
void decode(int type, const QString &data);
|
||||||
|
void notifyError(const QString &error, bool warning = false);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void timerEvent(QTimerEvent *);
|
||||||
|
QrScanThread *m_thread;
|
||||||
|
int m_processTimerId;
|
||||||
|
int m_processInterval;
|
||||||
|
int m_enabled;
|
||||||
|
QVideoFrame m_curFrame;
|
||||||
|
QVideoProbe *m_probe;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,100 @@
|
|||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
// Copyright (c) 2014-2020, The Monero Project.
|
||||||
|
|
||||||
|
#include "QrScanThread.h"
|
||||||
|
#include <QtGlobal>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
QrScanThread::QrScanThread(QObject *parent)
|
||||||
|
: QThread(parent)
|
||||||
|
,m_running(true)
|
||||||
|
{
|
||||||
|
m_scanner.set_handler(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QrScanThread::image_callback(zbar::Image &image)
|
||||||
|
{
|
||||||
|
qDebug() << "image_callback : Found Code ! " ;
|
||||||
|
for(zbar::Image::SymbolIterator sym = image.symbol_begin();
|
||||||
|
sym != image.symbol_end();
|
||||||
|
++sym)
|
||||||
|
if(!sym->get_count()) {
|
||||||
|
QString data = QString::fromStdString(sym->get_data());
|
||||||
|
emit decoded(sym->get_type(), data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QrScanThread::processZImage(zbar::Image &image)
|
||||||
|
{
|
||||||
|
m_scanner.recycle_image(image);
|
||||||
|
zbar::Image tmp = image.convert(*(long*)"Y800");
|
||||||
|
m_scanner.scan(tmp);
|
||||||
|
image.set_symbols(tmp.get_symbols());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QrScanThread::zimageFromQImage(const QImage &qimg, zbar::Image &dst)
|
||||||
|
{
|
||||||
|
switch( qimg.format() ){
|
||||||
|
case QImage::Format_RGB32 :
|
||||||
|
case QImage::Format_ARGB32 :
|
||||||
|
case QImage::Format_ARGB32_Premultiplied :
|
||||||
|
break;
|
||||||
|
default :
|
||||||
|
emit notifyError(QString("Invalid QImage Format !"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
unsigned int bpl( qimg.bytesPerLine() ), width( bpl / 4), height( qimg.height());
|
||||||
|
dst.set_size(width, height);
|
||||||
|
dst.set_format("BGR4");
|
||||||
|
unsigned long datalen = qimg.sizeInBytes();
|
||||||
|
dst.set_data(qimg.bits(), datalen);
|
||||||
|
if((width * 4 != bpl) || (width * height * 4 > datalen)){
|
||||||
|
emit notifyError(QString("QImage to Zbar::Image failed !"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
void QrScanThread::processQImage(const QImage &qimg)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
m_image = QSharedPointer<zbar::Image>(new zbar::Image());
|
||||||
|
if( ! zimageFromQImage(qimg, *m_image) )
|
||||||
|
return;
|
||||||
|
processZImage(*m_image);
|
||||||
|
}
|
||||||
|
catch(std::exception &e) {
|
||||||
|
qDebug() << "ERROR: " << e.what();
|
||||||
|
emit notifyError(e.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QrScanThread::processVideoFrame(const QVideoFrame &frame)
|
||||||
|
{
|
||||||
|
processQImage(frame.image());
|
||||||
|
}
|
||||||
|
|
||||||
|
void QrScanThread::stop()
|
||||||
|
{
|
||||||
|
m_running = false;
|
||||||
|
m_waitCondition.wakeOne();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QrScanThread::addFrame(const QVideoFrame &frame)
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&m_mutex);
|
||||||
|
m_queue.append(frame);
|
||||||
|
m_waitCondition.wakeOne();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QrScanThread::run()
|
||||||
|
{
|
||||||
|
QVideoFrame frame;
|
||||||
|
while(m_running) {
|
||||||
|
QMutexLocker locker(&m_mutex);
|
||||||
|
while(m_queue.isEmpty() && m_running)
|
||||||
|
m_waitCondition.wait(&m_mutex);
|
||||||
|
if(!m_queue.isEmpty())
|
||||||
|
processVideoFrame(m_queue.takeFirst());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,44 @@
|
|||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
// Copyright (c) 2020, The Monero Project.
|
||||||
|
|
||||||
|
#ifndef _QRSCANTHREAD_H_
|
||||||
|
#define _QRSCANTHREAD_H_
|
||||||
|
|
||||||
|
#include <QThread>
|
||||||
|
#include <QMutex>
|
||||||
|
#include <QWaitCondition>
|
||||||
|
#include <QEvent>
|
||||||
|
#include <QVideoFrame>
|
||||||
|
#include <QCamera>
|
||||||
|
#include <zbar.h>
|
||||||
|
|
||||||
|
class QrScanThread : public QThread, public zbar::Image::Handler
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
QrScanThread(QObject *parent = Q_NULLPTR);
|
||||||
|
void addFrame(const QVideoFrame &frame);
|
||||||
|
virtual void stop();
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
void decoded(int type, const QString &data);
|
||||||
|
void notifyError(const QString &error, bool warning = false);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void run();
|
||||||
|
void processVideoFrame(const QVideoFrame &);
|
||||||
|
void processQImage(const QImage &);
|
||||||
|
void processZImage(zbar::Image &image);
|
||||||
|
virtual void image_callback(zbar::Image &image);
|
||||||
|
bool zimageFromQImage(const QImage&, zbar::Image &);
|
||||||
|
|
||||||
|
private:
|
||||||
|
zbar::ImageScanner m_scanner;
|
||||||
|
QSharedPointer<zbar::Image> m_image;
|
||||||
|
bool m_running;
|
||||||
|
QMutex m_mutex;
|
||||||
|
QWaitCondition m_waitCondition;
|
||||||
|
QList<QVideoFrame> m_queue;
|
||||||
|
};
|
||||||
|
#endif
|
Loading…
Reference in new issue