I found that if QR-Code was generated with non standard charSet (and the message language is not English) than decoded QString contains wrong characters. So we must use QTextCodec to make it readable.

Now tagFound signal emits decoded string. If you want to know  what code was detected and what charSet is used, use tagFoundAdvanced(QString tag, QString format, QString charSet) signal or functions foundedFormat() and charSet().
This commit is contained in:
Alexxey593 2015-06-11 10:36:08 +03:00
parent 13720010fc
commit 4df9512790
11 changed files with 446 additions and 346 deletions

View File

@ -114,7 +114,7 @@ ArrayRef<char> CameraImageWrapper::getMatrix() const
ArrayRef<char> tmpRow; ArrayRef<char> tmpRow;
tmpRow = getRow(y, ArrayRef<char>(width)); tmpRow = getRow(y, ArrayRef<char>(width));
#if __cplusplus > 199711L #if __cplusplus > 199711L
memcpy(m, tmpRow->values()..data(), width); memcpy(m, tmpRow->values().data(), width);
#else #else
memcpy(m, &tmpRow->values()[0], width); memcpy(m, &tmpRow->values()[0], width);
#endif #endif

View File

@ -75,6 +75,10 @@ public:
} }
#endif #endif
QString decoderFormatToString(int fmt);
QString foundedFormat() const;
QString charSet() const;
public slots: public slots:
/** /**
* The decoding function. Will try to decode the given image based on the enabled decoders. * The decoding function. Will try to decode the given image based on the enabled decoders.
@ -123,6 +127,7 @@ public slots:
QString decodeSubImageQML(const QUrl &imageUrl, QString decodeSubImageQML(const QUrl &imageUrl,
const double offsetX = 0, const double offsetY = 0, const double offsetX = 0, const double offsetY = 0,
const double width = 0, const double height = 0); const double width = 0, const double height = 0);
/** /**
* Get the prossecing time in millisecond of the last decode operation. * Get the prossecing time in millisecond of the last decode operation.
* Added mainly as a statistic measure. * Added mainly as a statistic measure.
@ -153,6 +158,8 @@ private:
DecoderFormatType enabledDecoders; DecoderFormatType enabledDecoders;
ImageHandler *imageHandler; ImageHandler *imageHandler;
int processingTime; int processingTime;
QString foundedFmt;
QString charSet_;
/** /**
* If true, the decoding operation will take place at a different thread. * If true, the decoding operation will take place at a different thread.

View File

@ -44,6 +44,73 @@ QZXing::QZXing(QZXing::DecoderFormat decodeHints, QObject *parent) : QObject(par
setDecoder(decodeHints); setDecoder(decodeHints);
} }
QString QZXing::decoderFormatToString(int fmt)
{
switch (fmt) {
case 1:
return "AZTEC";
case 2:
return "CODABAR";
case 3:
return "CODE_39";
case 4:
return "CODE_93";
case 5:
return "CODE_128";
case 6:
return "DATA_MATRIX";
case 7:
return "EAN_8";
case 8:
return "EAN_13";
case 9:
return "ITF";
case 10:
return "MAXICODE";
case 11:
return "PDF_417";
case 12:
return "QR_CODE";
case 13:
return "RSS_14";
case 14:
return "RSS_EXPANDED";
case 15:
return "UPC_A";
case 16:
return "UPC_E";
case 17:
return "UPC_EAN_EXTENSION";
} // switch
return QString();
}
QString QZXing::foundedFormat() const
{
return foundedFmt;
}
QString QZXing::charSet() const
{
return charSet_;
}
void QZXing::setDecoder(const uint &hint) void QZXing::setDecoder(const uint &hint)
{ {
unsigned int newHints = 0; unsigned int newHints = 0;
@ -113,16 +180,15 @@ QString QZXing::decodeImage(QImage &image, int maxWidth, int maxHeight, bool smo
if(image.isNull()) if(image.isNull())
{ {
qDebug() << "Image Null"; qDebug() << "Image is Null";
emit decodingFinished(false); emit decodingFinished(false);
processingTime = -1; processingTime = t.elapsed();
return ""; return "";
} }
CameraImageWrapper* ciw; CameraImageWrapper *ciw = NULL;
try { try {
if(maxWidth > 0 || maxHeight > 0) if ((maxWidth > 0) || (maxHeight > 0))
ciw = CameraImageWrapper::Factory(image, maxWidth, maxHeight, smoothTransformation); ciw = CameraImageWrapper::Factory(image, maxWidth, maxHeight, smoothTransformation);
else else
ciw = new CameraImageWrapper(image); ciw = new CameraImageWrapper(image);
@ -138,17 +204,27 @@ QString QZXing::decodeImage(QImage &image, int maxWidth, int maxHeight, bool smo
res = decoder->decode(ref, DecodeHints((int)enabledDecoders)); res = decoder->decode(ref, DecodeHints((int)enabledDecoders));
QString string = QString(res->getText()->getText().c_str()); QString string = QString(res->getText()->getText().c_str());
processingTime = t.elapsed(); if (!string.isEmpty() && (string.length() > 0)) {
qDebug() << "Deconding succeeded: " << string; int fmt = res->getBarcodeFormat().value;
foundedFmt = decoderFormatToString(fmt);
charSet_ = QString::fromStdString(res->getCharSet());
if (!charSet_.isEmpty()) {
QTextCodec *codec = QTextCodec::codecForName(res->getCharSet().c_str());
if (codec)
string = codec->toUnicode(res->getText()->getText().c_str());
}
emit tagFound(string); emit tagFound(string);
emit tagFoundAdvanced(string, foundedFmt, charSet_);
}
processingTime = t.elapsed();
emit decodingFinished(true); emit decodingFinished(true);
return string; return string;
} }
catch(zxing::Exception& /*e*/) catch(zxing::Exception &e)
{ {
qDebug() << "Deconding failed"; emit error(QString(e.what()));
emit decodingFinished(false); emit decodingFinished(false);
processingTime = -1; processingTime = t.elapsed();
return ""; return "";
} }
} }
@ -173,6 +249,7 @@ QString QZXing::decodeSubImageQML(QObject* item,
{ {
if(item == NULL) if(item == NULL)
{ {
processingTime = 0;
emit decodingFinished(false); emit decodingFinished(false);
return ""; return "";
} }
@ -186,6 +263,7 @@ QString QZXing::decodeImageQML(const QUrl &imageUrl)
{ {
return decodeSubImageQML(imageUrl); return decodeSubImageQML(imageUrl);
} }
QString QZXing::decodeSubImageQML(const QUrl &imageUrl, QString QZXing::decodeSubImageQML(const QUrl &imageUrl,
const double offsetX, const double offsetY, const double offsetX, const double offsetY,
const double width, const double height) const double width, const double height)
@ -214,7 +292,3 @@ uint QZXing::getEnabledFormats() const
{ {
return enabledDecoders; return enabledDecoders;
} }

View File

@ -33,8 +33,8 @@ using zxing::BarcodeFormat;
Result::Result(Ref<String> text, Result::Result(Ref<String> text,
ArrayRef<char> rawBytes, ArrayRef<char> rawBytes,
ArrayRef< Ref<ResultPoint> > resultPoints, ArrayRef< Ref<ResultPoint> > resultPoints,
BarcodeFormat format) : BarcodeFormat format, std::string charSet) :
text_(text), rawBytes_(rawBytes), resultPoints_(resultPoints), format_(format) { text_(text), rawBytes_(rawBytes), resultPoints_(resultPoints), format_(format), charSet_(charSet) {
} }
Result::~Result() { Result::~Result() {
@ -59,3 +59,8 @@ ArrayRef< Ref<ResultPoint> >& Result::getResultPoints() {
zxing::BarcodeFormat Result::getBarcodeFormat() const { zxing::BarcodeFormat Result::getBarcodeFormat() const {
return format_; return format_;
} }
std::string Result::getCharSet() const
{
return charSet_;
}

View File

@ -35,18 +35,21 @@ private:
ArrayRef<char> rawBytes_; ArrayRef<char> rawBytes_;
ArrayRef< Ref<ResultPoint> > resultPoints_; ArrayRef< Ref<ResultPoint> > resultPoints_;
BarcodeFormat format_; BarcodeFormat format_;
//NOTE: My
std::string charSet_;
public: public:
Result(Ref<String> text, Result(Ref<String> text,
ArrayRef<char> rawBytes, ArrayRef<char> rawBytes,
ArrayRef< Ref<ResultPoint> > resultPoints, ArrayRef< Ref<ResultPoint> > resultPoints,
BarcodeFormat format); BarcodeFormat format, std::string charSet = "");
~Result(); ~Result();
Ref<String> getText(); Ref<String> getText();
ArrayRef<char> getRawBytes(); ArrayRef<char> getRawBytes();
ArrayRef< Ref<ResultPoint> > const& getResultPoints() const; ArrayRef< Ref<ResultPoint> > const& getResultPoints() const;
ArrayRef< Ref<ResultPoint> >& getResultPoints(); ArrayRef< Ref<ResultPoint> >& getResultPoints();
BarcodeFormat getBarcodeFormat() const; BarcodeFormat getBarcodeFormat() const;
std::string getCharSet() const;
friend std::ostream& operator<<(std::ostream &out, Result& result); friend std::ostream& operator<<(std::ostream &out, Result& result);
}; };

View File

@ -27,15 +27,15 @@ using namespace zxing;
DecoderResult::DecoderResult(ArrayRef<char> rawBytes, DecoderResult::DecoderResult(ArrayRef<char> rawBytes,
Ref<String> text, Ref<String> text,
ArrayRef< ArrayRef<char> >& byteSegments, ArrayRef< ArrayRef<char> >& byteSegments,
string const& ecLevel) : string const& ecLevel, string charSet) :
rawBytes_(rawBytes), rawBytes_(rawBytes),
text_(text), text_(text),
byteSegments_(byteSegments), byteSegments_(byteSegments),
ecLevel_(ecLevel) {} ecLevel_(ecLevel), charSet_(charSet) {}
DecoderResult::DecoderResult(ArrayRef<char> rawBytes, DecoderResult::DecoderResult(ArrayRef<char> rawBytes,
Ref<String> text) Ref<String> text)
: rawBytes_(rawBytes), text_(text) {} : rawBytes_(rawBytes), text_(text),charSet_("") {}
ArrayRef<char> DecoderResult::getRawBytes() { ArrayRef<char> DecoderResult::getRawBytes() {
return rawBytes_; return rawBytes_;
@ -44,3 +44,8 @@ ArrayRef<char> DecoderResult::getRawBytes() {
Ref<String> DecoderResult::getText() { Ref<String> DecoderResult::getText() {
return text_; return text_;
} }
string DecoderResult::charSet()
{
return charSet_;
}

View File

@ -33,17 +33,21 @@ private:
Ref<String> text_; Ref<String> text_;
ArrayRef< ArrayRef<char> > byteSegments_; ArrayRef< ArrayRef<char> > byteSegments_;
std::string ecLevel_; std::string ecLevel_;
std::string charSet_;
public: public:
DecoderResult(ArrayRef<char> rawBytes, DecoderResult(ArrayRef<char> rawBytes,
Ref<String> text, Ref<String> text,
ArrayRef< ArrayRef<char> >& byteSegments, ArrayRef< ArrayRef<char> >& byteSegments,
std::string const& ecLevel); std::string const& ecLevel,
std::string charSet = "");
DecoderResult(ArrayRef<char> rawBytes, Ref<String> text); DecoderResult(ArrayRef<char> rawBytes, Ref<String> text);
ArrayRef<char> getRawBytes(); ArrayRef<char> getRawBytes();
Ref<String> getText(); Ref<String> getText();
// NOTE: my
std::string charSet();
}; };
} }

View File

@ -38,7 +38,7 @@ namespace zxing {
ArrayRef< Ref<ResultPoint> > points (detectorResult->getPoints()); ArrayRef< Ref<ResultPoint> > points (detectorResult->getPoints());
Ref<DecoderResult> decoderResult(decoder_.decode(detectorResult->getBits())); Ref<DecoderResult> decoderResult(decoder_.decode(detectorResult->getBits()));
Ref<Result> result( Ref<Result> result(
new Result(decoderResult->getText(), decoderResult->getRawBytes(), points, BarcodeFormat::QR_CODE)); new Result(decoderResult->getText(), decoderResult->getRawBytes(), points, BarcodeFormat::QR_CODE, decoderResult->charSet()));
return result; return result;
} }

View File

@ -47,7 +47,7 @@ private:
static void decodeHanziSegment(Ref<BitSource> bits, std::string &result, int count); static void decodeHanziSegment(Ref<BitSource> bits, std::string &result, int count);
static void decodeKanjiSegment(Ref<BitSource> bits, std::string &result, int count); static void decodeKanjiSegment(Ref<BitSource> bits, std::string &result, int count);
static void decodeByteSegment(Ref<BitSource> bits, std::string &result, int count); static void decodeByteSegment(Ref<BitSource> bits, std::string &result, int count);
static void decodeByteSegment(Ref<BitSource> bits_, static std::string decodeByteSegment(Ref<BitSource> bits_,
std::string& result, std::string& result,
int count, int count,
zxing::common::CharacterSetECI* currentCharacterSetECI, zxing::common::CharacterSetECI* currentCharacterSetECI,

View File

@ -102,6 +102,7 @@ void DecodedBitStreamParser::append(std::string &result,
result.append((const char *)bufOut); result.append((const char *)bufOut);
delete[] bufOut; delete[] bufOut;
#else #else
Q_UNUSED(src);
result.append((const char *)bufIn, nIn); result.append((const char *)bufIn, nIn);
#endif #endif
} }
@ -181,7 +182,7 @@ void DecodedBitStreamParser::decodeKanjiSegment(Ref<BitSource> bits, std::string
delete[] buffer; delete[] buffer;
} }
void DecodedBitStreamParser::decodeByteSegment(Ref<BitSource> bits_, std::string DecodedBitStreamParser::decodeByteSegment(Ref<BitSource> bits_,
string& result, string& result,
int count, int count,
CharacterSetECI* currentCharacterSetECI, CharacterSetECI* currentCharacterSetECI,
@ -217,6 +218,7 @@ void DecodedBitStreamParser::decodeByteSegment(Ref<BitSource> bits_,
throw FormatException(); throw FormatException();
} }
byteSegments->values().push_back(bytes_); byteSegments->values().push_back(bytes_);
return encoding;
} }
void DecodedBitStreamParser::decodeNumericSegment(Ref<BitSource> bits, std::string &result, int count) { void DecodedBitStreamParser::decodeNumericSegment(Ref<BitSource> bits, std::string &result, int count) {
@ -357,8 +359,9 @@ DecodedBitStreamParser::decode(ArrayRef<char> bytes,
string result; string result;
result.reserve(50); result.reserve(50);
ArrayRef< ArrayRef<char> > byteSegments (0); ArrayRef< ArrayRef<char> > byteSegments (0);
try {
CharacterSetECI* currentCharacterSetECI = 0; CharacterSetECI* currentCharacterSetECI = 0;
string charSet = "";
try {
bool fc1InEffect = false; bool fc1InEffect = false;
Mode* mode = 0; Mode* mode = 0;
do { do {
@ -410,7 +413,7 @@ DecodedBitStreamParser::decode(ArrayRef<char> bytes,
} else if (mode == &Mode::ALPHANUMERIC) { } else if (mode == &Mode::ALPHANUMERIC) {
decodeAlphanumericSegment(bits_, result, count, fc1InEffect); decodeAlphanumericSegment(bits_, result, count, fc1InEffect);
} else if (mode == &Mode::BYTE) { } else if (mode == &Mode::BYTE) {
decodeByteSegment(bits_, result, count, currentCharacterSetECI, byteSegments, hints); charSet = decodeByteSegment(bits_, result, count, currentCharacterSetECI, byteSegments, hints);
} else if (mode == &Mode::KANJI) { } else if (mode == &Mode::KANJI) {
decodeKanjiSegment(bits_, result, count); decodeKanjiSegment(bits_, result, count);
} else { } else {
@ -425,7 +428,6 @@ DecodedBitStreamParser::decode(ArrayRef<char> bytes,
// from readBits() calls // from readBits() calls
throw FormatException(); throw FormatException();
} }
return Ref<DecoderResult>(new DecoderResult(bytes, Ref<String>(new String(result)), byteSegments, (string)ecLevel, charSet));
return Ref<DecoderResult>(new DecoderResult(bytes, Ref<String>(new String(result)), byteSegments, (string)ecLevel));
} }