Added the option to execute the decoding to an other thread. Not sure if it will give any benefit. It will be investigated.

This commit is contained in:
favoritas37 2013-07-30 20:59:51 +03:00
parent 3ae1130138
commit 4eb0ea479c
7 changed files with 241 additions and 60 deletions

View File

@ -12,6 +12,8 @@ Rectangle {
border.width: 1
radius: 5
property int decoderHint;
Text{
id: label
color: "white"
@ -35,4 +37,6 @@ Rectangle {
PropertyChanges {target: rect; color:"darkgray"}
}
]
onIsPressedChanged: parent.updateDecoderHints(decoderHint)
}

View File

@ -14,6 +14,7 @@ Rectangle {
anchors.top: parent.top
height: parent.height-200
DropArea{
anchors.fill: parent
onFileDroped: decoder.decodeImageFromFile(url)
@ -81,10 +82,13 @@ Rectangle {
anchors.bottom: label.top
Flow{
id: flow
anchors.fill: parent
spacing: 10
anchors.margins: 5
property int hintSum: 0
move: Transition {
NumberAnimation {
properties: "x,y"
@ -92,24 +96,30 @@ Rectangle {
}
}
ToggleButton{ text: "Aztec" }
ToggleButton{ text: "Codabar" }
ToggleButton{ text: "Code_39" }
ToggleButton{ text: "Code_93" }
ToggleButton{ text: "Code_128" }
ToggleButton{ text: "Data Matrix" }
ToggleButton{ text: "EAN_8" }
ToggleButton{ text: "EAN_13" }
ToggleButton{ text: "ITF" }
ToggleButton{ text: "Maxicode" }
ToggleButton{ text: "PDF_417" }
ToggleButton{ text: "Qr Code" }
ToggleButton{ text: "RSS 14" }
ToggleButton{ text: "RSS expanded" }
ToggleButton{ text: "UPC A" }
ToggleButton{ text: "UPC E" }
ToggleButton{ text: "UPC EAN extension" }
ToggleButton{ text: "Aztec"; decoderHint: QZXing.DecoderFormat_Aztec}
ToggleButton{ text: "Codabar"; decoderHint: QZXing.DecoderFormat_CODABAR }
ToggleButton{ text: "Code_39"; decoderHint: QZXing.DecoderFormat_CODE_39 }
ToggleButton{ text: "Code_93"; decoderHint: QZXing.DecoderFormat_CODE_93 }
ToggleButton{ text: "Code_128"; decoderHint: QZXing.DecoderFormat_CODE_128 }
ToggleButton{ text: "Data Matrix"; decoderHint: QZXing.DecoderFormat_DATA_MATRIX }
ToggleButton{ text: "EAN_8"; decoderHint: QZXing.DecoderFormat_EAN_8 }
ToggleButton{ text: "EAN_13"; decoderHint: QZXing.DecoderFormat_EAN_13 }
ToggleButton{ text: "ITF"; decoderHint: QZXing.DecoderFormat_ITF }
ToggleButton{ text: "Maxicode"; decoderHint: QZXing.DecoderFormat_MAXICODE }
ToggleButton{ text: "PDF_417"; decoderHint: QZXing.DecoderFormat_PDF_417 }
ToggleButton{ text: "Qr Code"; decoderHint: QZXing.DecoderFormat_QR_CODE }
ToggleButton{ text: "RSS 14"; decoderHint: QZXing.DecoderFormat_RSS_14 }
ToggleButton{ text: "RSS expanded"; decoderHint: QZXing.DecoderFormat_RSS_EXPANDED }
ToggleButton{ text: "UPC A"; decoderHint: QZXing.DecoderFormat_UPC_A }
ToggleButton{ text: "UPC E"; decoderHint: QZXing.DecoderFormat_UPC_E }
ToggleButton{ text: "UPC EAN extension"; decoderHint: QZXing.DecoderFormat_UPC_EAN_EXTENSION }
function updateDecoderHints(hint)
{
//XOR operator to toggle the specific decoder
hintSum = hintSum ^ hint;
decoder.enabledDecoders = hintSum
}
}
}
@ -132,7 +142,7 @@ Rectangle {
QZXing{
id: decoder
enabledDecoders: QZXing.DecoderFormat_QR_CODE
//enabledDecoders: QZXing.DecoderFormat_QR_CODE
onTagFound: {
log.add("Tag found: " +tag+ ", milliseconds: " + processingTime)

View File

@ -116,6 +116,19 @@ public slots:
*/
void setDecoder(const uint& hint);
/**
* If set to true, the decoding takes place in a different thread.
* Note that if threading is used, the decodeImage function returns
* an empty string. To acquire the data the user needs to connect to the signal
* tagFound.
*
* This option was created for convinience in case the decoding functions are used
* at a low-power device with big images.
*
* (PS. not sure if it gives any advantage, it will be investigated further in the future)
*/
void setIsThreaded(bool enabledThreads);
signals:
void decodingStarted();
void decodingFinished(bool succeeded);

View File

@ -123,7 +123,8 @@ HEADERS += $$PWD/QZXing_global.h \
$$PWD/zxing/bigint/BigIntegerUtils.hh \
$$PWD/zxing/bigint/BigIntegerLibrary.hh \
$$PWD/zxing/bigint/BigIntegerAlgorithms.hh \
$$PWD/zxing/bigint/BigInteger.hh
$$PWD/zxing/bigint/BigInteger.hh \
qzxing/qzxingworker_p.h
SOURCES += $$PWD/CameraImageWrapper.cpp \
$$PWD/qzxing.cpp \
@ -227,7 +228,8 @@ SOURCES += $$PWD/CameraImageWrapper.cpp \
$$PWD/zxing/bigint/BigUnsigned.cc \
$$PWD/zxing/bigint/BigIntegerUtils.cc \
$$PWD/zxing/bigint/BigIntegerAlgorithms.cc \
$$PWD/zxing/bigint/BigInteger.cc
$$PWD/zxing/bigint/BigInteger.cc \
qzxing/qzxingworker_p.cpp
symbian {
TARGET.UID3 = 0xE618743C

View File

@ -9,6 +9,9 @@
#include "imagehandler.h"
#include <QTime>
#include "qzxingworker_p.h"
#include <QThread>
using namespace zxing;
QZXing::QZXing(QObject *parent) : QObject(parent)
@ -95,53 +98,85 @@ void QZXing::setDecoder(const uint &hint)
emit enabledFormatsChanged();
}
void QZXing::setIsThreaded(bool enabledThreads)
{
isThreaded = enabledThreads;
}
QString QZXing::decodeImage(QImage image, int maxWidth, int maxHeight, bool smoothTransformation)
{
QTime t;
t.start();
Ref<Result> res;
emit decodingStarted();
isThreaded = true;
if(image.isNull())
if(isThreaded)
{
emit decodingFinished(false);
processingTime = -1;
QThread *thread = new QThread;
QZXingWorker_p* worker = new QZXingWorker_p();
connect(worker, SIGNAL(decodingFinished(bool)), this, SIGNAL(decodingFinished(bool)));
connect(worker, SIGNAL(decodingStarted()), this, SIGNAL(decodingStarted()));
connect(worker, SIGNAL(tagFound(QString)), this, SIGNAL(tagFound(QString)));
worker->setData(&processingTime, image, maxWidth, maxHeight, smoothTransformation, decoder, enabledDecoders);
worker->moveToThread(thread);
thread->start();
QMetaObject::invokeMethod(worker, "decode", Qt::QueuedConnection);
return "";
}
try{
CameraImageWrapper* ciw;
if(maxWidth > 0 || maxHeight > 0)
{
ciw = new CameraImageWrapper();
ciw->setSmoothTransformation(smoothTransformation);
ciw->setImage(image, maxWidth, maxHeight);
}
else
ciw = new CameraImageWrapper(image);
Ref<LuminanceSource> imageRef(ciw);
GlobalHistogramBinarizer* binz = new GlobalHistogramBinarizer(imageRef);
Ref<Binarizer> bz (binz);
BinaryBitmap* bb = new BinaryBitmap(bz);
Ref<BinaryBitmap> ref(bb);
res = ((MultiFormatReader*)decoder)->decode(ref, DecodeHints((int)enabledDecoders));
QString string = QString(res->getText()->getText().c_str());
processingTime = t.elapsed();
emit tagFound(string);
emit decodingFinished(true);
return string;
}
catch(zxing::Exception& e)
else
{
emit decodingFinished(false);
processingTime = -1;
return "";
QTime t;
t.start();
Ref<Result> res;
emit decodingStarted();
if(image.isNull())
{
emit decodingFinished(false);
processingTime = -1;
return "";
}
try{
CameraImageWrapper* ciw;
if(maxWidth > 0 || maxHeight > 0)
{
ciw = new CameraImageWrapper();
ciw->setSmoothTransformation(smoothTransformation);
ciw->setImage(image, maxWidth, maxHeight);
}
else
ciw = new CameraImageWrapper(image);
Ref<LuminanceSource> imageRef(ciw);
GlobalHistogramBinarizer* binz = new GlobalHistogramBinarizer(imageRef);
Ref<Binarizer> bz (binz);
BinaryBitmap* bb = new BinaryBitmap(bz);
Ref<BinaryBitmap> ref(bb);
res = ((MultiFormatReader*)decoder)->decode(ref, DecodeHints((int)enabledDecoders));
QString string = QString(res->getText()->getText().c_str());
processingTime = t.elapsed();
emit tagFound(string);
emit decodingFinished(true);
delete ciw;
delete binz;
delete bb;
return string;
}
catch(zxing::Exception& e)
{
emit decodingFinished(false);
processingTime = -1;
return "";
}
}
}

84
source/qzxingworker_p.cpp Normal file
View File

@ -0,0 +1,84 @@
#include "qzxingworker_p.h"
#include <zxing/common/GlobalHistogramBinarizer.h>
#include <zxing/Binarizer.h>
#include <zxing/BinaryBitmap.h>
#include <zxing/MultiFormatReader.h>
#include <zxing/DecodeHints.h>
#include "CameraImageWrapper.h"
#include "imagehandler.h"
#include <QTime>
#include <qzxing.h>
using namespace zxing;
QZXingWorker_p::QZXingWorker_p(QObject *parent) :
QObject(parent)
{
}
QString QZXingWorker_p::decode()
{
QTime t;
t.start();
Ref<Result> res;
emit decodingStarted();
if(image.isNull())
{
emit decodingFinished(false);
*processingTime = -1;
return "";
}
try{
CameraImageWrapper* ciw;
if(maxWidth > 0 || maxHeight > 0)
{
ciw = new CameraImageWrapper();
ciw->setSmoothTransformation(smoothTransformation);
ciw->setImage(image, maxWidth, maxHeight);
}
else
ciw = new CameraImageWrapper(image);
Ref<LuminanceSource> imageRef(ciw);
GlobalHistogramBinarizer* binz = new GlobalHistogramBinarizer(imageRef);
Ref<Binarizer> bz (binz);
BinaryBitmap* bb = new BinaryBitmap(bz);
Ref<BinaryBitmap> ref(bb);
res = ((MultiFormatReader*)decoder)->decode(ref, DecodeHints((int)enabledDecoders));
QString string = QString(res->getText()->getText().c_str());
*processingTime = t.elapsed();
emit tagFound(string);
emit decodingFinished(true);
delete ciw;
delete binz;
delete bb;
return string;
}
catch(zxing::Exception& e)
{
emit decodingFinished(false);
*processingTime = -1;
return "";
}
}
void QZXingWorker_p::setData(int *processingTime, QImage image, int maxWidth, int maxHeight, bool smoothTransformation, void *decoder, uint enabledDecoders)
{
this->processingTime = processingTime;
this->image = image;
this->maxWidth = maxWidth;
this->maxHeight = maxHeight;
this->smoothTransformation = smoothTransformation;
this->decoder = decoder;
this->enabledDecoders = enabledDecoders;
}

33
source/qzxingworker_p.h Normal file
View File

@ -0,0 +1,33 @@
#ifndef QZXINGWORKER_P_H
#define QZXINGWORKER_P_H
#include <QObject>
#include <QImage>
class QZXingWorker_p : public QObject
{
Q_OBJECT
public:
explicit QZXingWorker_p(QObject *parent = 0);
signals:
void decodingStarted();
void decodingFinished(bool succeeded);
void tagFound(QString tag);
public slots:
void setData(int* processingTime, QImage image, int maxWidth, int maxHeight, bool smoothTransformation,
void* decoder, uint enabledDecoders);
QString decode();
private:
int* processingTime;
QImage image;
int maxWidth;
int maxHeight;
bool smoothTransformation;
void* decoder;
uint enabledDecoders;
};
#endif // QZXINGWORKER_P_H