saving merge

This commit is contained in:
favoritas37 2015-06-13 20:08:58 +03:00
commit e70dd5e1a2
18 changed files with 472 additions and 364 deletions

View File

@ -41,7 +41,9 @@
#include "QCameraControllerWidget.h"
//#include <QDebug>
#include <QCameraFlashControl>
#include <QHBoxLayout>
#include <QMessageBox>
#include <QStandardPaths>
/*****************************************************************************
* QCameraControllerWidget
@ -125,11 +127,17 @@ QCameraControllerWidget::QCameraControllerWidget(QWidget *parent) :
setLayout(hboxl);
QStringList list = QStandardPaths::standardLocations(QStandardPaths::PicturesLocation);
if(list.isEmpty())
imagePath = qApp->applicationDirPath();
else
imagePath = list.at(0);
fileWatcher = new QFileSystemWatcher();
fileWatcher->addPath(QDesktopServices::storageLocation(QDesktopServices::PicturesLocation));
fileWatcher->addPath(imagePath);
connect(fileWatcher, SIGNAL( directoryChanged (const QString &)), this, SLOT(deleteImage(const QString &)));
imageFolder = QDir(QDesktopServices::storageLocation(QDesktopServices::PicturesLocation));
imageFolder = QDir(imagePath);
QStringList filters;
filters << "camera*";
imageFolder.setNameFilters(filters);
@ -280,6 +288,7 @@ void QCameraControllerWidget::captureImage()
void QCameraControllerWidget::onImageCaptured(int id, const QImage &preview)
{
Q_UNUSED(id);
// m_stillImageCapture->cancelCapture();
// showViewFinder = false;
m_focusing = false;
@ -291,6 +300,7 @@ void QCameraControllerWidget::onImageCaptured(int id, const QImage &preview)
void QCameraControllerWidget::deleteImage(const QString & folderPath)
{
Q_UNUSED(folderPath);
//qdebug() << "Detected change to folder: " << folderPath;
QStringList files = imageFolder.entryList(imageFolder.nameFilters());
@ -300,8 +310,7 @@ void QCameraControllerWidget::deleteImage(const QString & folderPath)
//qdebug() << "Checking file: " << image;
if(image.startsWith("camera"))
{
QString path(QDesktopServices::storageLocation(QDesktopServices::PicturesLocation));
QDir pathDir(path);
QDir pathDir(imagePath);
pathDir.remove(image);
//qdebug() << "file deleted: " << image;
@ -354,6 +363,7 @@ void QCameraControllerWidget::updateVideo()
void QCameraControllerWidget::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
//QMainWindow::paintEvent(event);
QPainter painter(this);

View File

@ -58,7 +58,7 @@
#include "myvideosurface.h"
#include "button.h"
#include <QStackedWidget>
class QCameraControllerWidget: public QWidget, public VideoIF
{
@ -117,6 +117,7 @@ private:
QCameraFocus* cameraFocus;
QFileSystemWatcher* fileWatcher;
QDir imageFolder;
QString imagePath;
};
#endif // QCAMERA_H

View File

@ -31,7 +31,7 @@
#ifndef QQRDECODER_H
#define QQRDECODER_H
#include <QtGui/QMainWindow>
#include <QMainWindow>
#include <QPixmap>
#include "ui_QQrDecoder.h"
#include <qzxing.h>

View File

@ -1,15 +1,9 @@
TEMPLATE = app
TARGET = QQrDecoder
QT += core \
gui \
declarative
QT += core gui multimedia widgets
VERSION = 2.0.0
CONFIG += mobility
MOBILITY = multimedia #\
#systeminfo
RESOURCES += resources.qrc
include(../../source/QZXing.pri)

View File

@ -46,7 +46,6 @@
Button::Button(QWidget *parent, Qt::WindowFlags f) :
QLabel(parent, f)
{
m_downPixmap = 0;
m_disabled = false;
m_toggled = false;
m_toggle_enabled = false;

View File

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

View File

@ -28,9 +28,9 @@ class ImageHandler;
*/
class
#ifndef DISABLE_LIBRARY_FEATURES
QZXINGSHARED_EXPORT
QZXINGSHARED_EXPORT
#endif
QZXing : public QObject{
QZXing : public QObject {
Q_OBJECT
Q_ENUMS(DecoderFormat)
@ -75,6 +75,10 @@ public:
}
#endif
QString decoderFormatToString(int fmt);
QString foundedFormat() const;
QString charSet() const;
public slots:
/**
* The decoding function. Will try to decode the given image based on the enabled decoders.
@ -85,14 +89,13 @@ public slots:
* The smoothTransformation flag determines whether the transformation will be smooth or fast.
* Smooth transformation provides better results but fast transformation is...faster.
*/
QString decodeImage(QImage &image, int maxWidth=-1, int maxHeight=-1, bool smoothTransformation = false);
QString decodeImage(QImage &image, int maxWidth = -1, int maxHeight = -1, bool smoothTransformation = false);
/**
* The decoding function. Will try to decode the given image based on the enabled decoders.
* The input image is read from a local image file.
*/
QString decodeImageFromFile(const QString& imageFilePath, int maxWidth=-1, int maxHeight=-1, bool smoothTransformation = false);
/**
* The decoding function accessible from QML. (Suggested for Qt 4.x)
*/
@ -102,7 +105,7 @@ public slots:
* The decoding function accessible from QML. Able to set the decoding
* of a portion of the image. (Suggested for Qt 4.x)
*/
QString decodeSubImageQML(QObject* item,
QString decodeSubImageQML(QObject *item,
const double offsetX = 0 , const double offsetY = 0,
const double width = 0, const double height = 0);
@ -123,6 +126,7 @@ public slots:
QString decodeSubImageQML(const QUrl &imageUrl,
const double offsetX = 0, const double offsetY = 0,
const double width = 0, const double height = 0);
/**
* Get the prossecing time in millisecond of the last decode operation.
* Added mainly as a statistic measure.
@ -140,19 +144,23 @@ public slots:
* As argument it is possible to pass conjuction of decoders by using logic OR.
* e.x. setDecoder ( DecoderFormat_QR_CODE | DecoderFormat_EAN_13 | DecoderFormat_CODE_39 )
*/
void setDecoder(const uint& hint);
void setDecoder(const uint &hint);
signals:
void decodingStarted();
void decodingFinished(bool succeeded);
void tagFound(QString tag);
void enabledFormatsChanged();
void tagFoundAdvanced(QString tag, QString format, QString charSet);
void error(QString msg);
private:
zxing::MultiFormatReader* decoder;
zxing::MultiFormatReader *decoder;
DecoderFormatType enabledDecoders;
ImageHandler* imageHandler;
ImageHandler *imageHandler;
int processingTime;
QString foundedFmt;
QString charSet_;
/**
* If true, the decoding operation will take place at a different thread.

View File

@ -1,7 +1,7 @@
QT += core gui
greaterThan(QT_VERSION, 4.7): QT += declarative
greaterThan(QT_VERSION, 5.0): QT += quick
greaterThan(QT_VERSION, 4.7): lessThan(QT_VERSION, 5.0): QT += declarative
greaterThan(QT_MAJOR_VERSION, 4): QT += quick
DEFINES += QZXING_LIBRARY \
ZXING_ICONV_CONST \
@ -284,3 +284,7 @@ win32-g++{
SOURCES += $$PWD/zxing/win32/zxing/win_iconv.c
}
!win32{
DEFINES += NO_ICONV
}

View File

@ -16,7 +16,7 @@ QImage ImageHandler::extractQImage(QObject *imageObj,
{
QGraphicsObject *item = qobject_cast<QGraphicsObject*>(imageObj);
if (!item ) {
if (!item) {
qDebug() << "Item is NULL";
return QImage();
}

View File

@ -45,6 +45,73 @@ QZXing::QZXing(QZXing::DecoderFormat decodeHints, QObject *parent) : QObject(par
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)
{
unsigned int newHints = 0;
@ -114,50 +181,58 @@ QString QZXing::decodeImage(QImage &image, int maxWidth, int maxHeight, bool smo
if(image.isNull())
{
qDebug() << "Image Null";
emit decodingFinished(false);
processingTime = -1;
processingTime = t.elapsed();
return "";
}
CameraImageWrapper* ciw;
try{
if(maxWidth > 0 || maxHeight > 0)
CameraImageWrapper *ciw = NULL;
try {
if ((maxWidth > 0) || (maxHeight > 0))
ciw = CameraImageWrapper::Factory(image, maxWidth, maxHeight, smoothTransformation);
else
ciw = new CameraImageWrapper(image);
Ref<LuminanceSource> imageRef(ciw);
GlobalHistogramBinarizer* binz = new GlobalHistogramBinarizer(imageRef);
GlobalHistogramBinarizer *binz = new GlobalHistogramBinarizer(imageRef);
Ref<Binarizer> bz (binz);
BinaryBitmap* bb = new BinaryBitmap(bz);
Ref<Binarizer> bz(binz);
BinaryBitmap *bb = new BinaryBitmap(bz);
Ref<BinaryBitmap> ref(bb);
res = decoder->decode(ref, DecodeHints((int)enabledDecoders));
QString string = QString(res->getText()->getText().c_str());
if (!string.isEmpty() && (string.length() > 0)) {
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 tagFoundAdvanced(string, foundedFmt, charSet_);
}
processingTime = t.elapsed();
qDebug() << "Deconding succeeded: " << string;
emit tagFound(string);
emit decodingFinished(true);
return string;
}
catch(zxing::Exception& /*e*/)
catch(zxing::Exception &e)
{
qDebug() << "Deconding failed";
emit error(QString(e.what()));
emit decodingFinished(false);
processingTime = -1;
processingTime = t.elapsed();
return "";
}
}
QString QZXing::decodeImageFromFile(const QString& imageFilePath, int maxWidth, int maxHeight, bool smoothTransformation)
{
//used to have a check if this image exists
//but was removed because if the image file path doesn't point to a valid image
// used to have a check if this image exists
// but was removed because if the image file path doesn't point to a valid image
// then the QImage::isNull will return true and the decoding will fail eitherway.
QUrl imageUrl(imageFilePath);
QImage tmpImage = QImage(imageUrl.toLocalFile());
@ -169,12 +244,13 @@ QString QZXing::decodeImageQML(QObject *item)
return decodeSubImageQML(item);
}
QString QZXing::decodeSubImageQML(QObject* item,
QString QZXing::decodeSubImageQML(QObject *item,
const double offsetX, const double offsetY,
const double width, const double height)
{
if(item == NULL)
{
processingTime = 0;
emit decodingFinished(false);
return "";
}
@ -188,6 +264,7 @@ QString QZXing::decodeImageQML(const QUrl &imageUrl)
{
return decodeSubImageQML(imageUrl);
}
QString QZXing::decodeSubImageQML(const QUrl &imageUrl,
const double offsetX, const double offsetY,
const double width, const double height)
@ -216,7 +293,3 @@ uint QZXing::getEnabledFormats() const
{
return enabledDecoders;
}

View File

@ -33,8 +33,8 @@ using zxing::BarcodeFormat;
Result::Result(Ref<String> text,
ArrayRef<char> rawBytes,
ArrayRef< Ref<ResultPoint> > resultPoints,
BarcodeFormat format) :
text_(text), rawBytes_(rawBytes), resultPoints_(resultPoints), format_(format) {
BarcodeFormat format, std::string charSet) :
text_(text), rawBytes_(rawBytes), resultPoints_(resultPoints), format_(format), charSet_(charSet) {
}
Result::~Result() {
@ -57,5 +57,10 @@ ArrayRef< Ref<ResultPoint> >& Result::getResultPoints() {
}
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< Ref<ResultPoint> > resultPoints_;
BarcodeFormat format_;
//NOTE: My
std::string charSet_;
public:
Result(Ref<String> text,
ArrayRef<char> rawBytes,
ArrayRef< Ref<ResultPoint> > resultPoints,
BarcodeFormat format);
BarcodeFormat format, std::string charSet = "");
~Result();
Ref<String> getText();
ArrayRef<char> getRawBytes();
ArrayRef< Ref<ResultPoint> > const& getResultPoints() const;
ArrayRef< Ref<ResultPoint> >& getResultPoints();
BarcodeFormat getBarcodeFormat() const;
std::string getCharSet() const;
friend std::ostream& operator<<(std::ostream &out, Result& result);
};

View File

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

View File

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

View File

@ -31,14 +31,14 @@ namespace zxing {
QRCodeReader::QRCodeReader() :decoder_() {
}
//TODO: see if any of the other files in the qrcode tree need tryHarder
//TODO : see if any of the other files in the qrcode tree need tryHarder
Ref<Result> QRCodeReader::decode(Ref<BinaryBitmap> image, DecodeHints hints) {
Detector detector(image->getBlackMatrix());
Ref<DetectorResult> detectorResult(detector.detect(hints));
ArrayRef< Ref<ResultPoint> > points (detectorResult->getPoints());
Ref<DecoderResult> decoderResult(decoder_.decode(detectorResult->getBits()));
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;
}

View File

@ -47,7 +47,7 @@ private:
static void decodeHanziSegment(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_,
static std::string decodeByteSegment(Ref<BitSource> bits_,
std::string& result,
int count,
zxing::common::CharacterSetECI* currentCharacterSetECI,

View File

@ -28,7 +28,7 @@
#include <iconv.h>
#endif
// Required for compatibility. TODO: test on Symbian
// Required for compatibility. TODO : test on Symbian
#ifdef ZXING_ICONV_CONST
#undef ICONV_CONST
#define ICONV_CONST const
@ -46,18 +46,18 @@ using namespace zxing::qrcode;
using namespace zxing::common;
const char DecodedBitStreamParser::ALPHANUMERIC_CHARS[] =
{ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B',
'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
'Y', 'Z', ' ', '$', '%', '*', '+', '-', '.', '/', ':'
};
{ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B',
'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
'Y', 'Z', ' ', '$', '%', '*', '+', '-', '.', '/', ':'
};
namespace {int GB2312_SUBSET = 1;}
void DecodedBitStreamParser::append(std::string &result,
string const& in,
const char *src) {
append(result, (char const*)in.c_str(), in.length(), src);
append(result, (char const*)in.c_str(), in.length(), src);
}
void DecodedBitStreamParser::append(std::string &result,
@ -65,286 +65,288 @@ void DecodedBitStreamParser::append(std::string &result,
size_t nIn,
const char *src) {
#ifndef NO_ICONV
if (nIn == 0) {
return;
}
if (nIn == 0) {
return;
}
iconv_t cd = iconv_open(StringUtils::UTF8, src);
if (cd == (iconv_t)-1) {
result.append((const char *)bufIn, nIn);
return;
}
iconv_t cd = iconv_open(StringUtils::UTF8, src);
if (cd == (iconv_t)-1) {
result.append((const char *)bufIn, nIn);
return;
}
const int maxOut = 4 * nIn + 1;
char* bufOut = new char[maxOut];
const int maxOut = 4 * nIn + 1;
char* bufOut = new char[maxOut];
ICONV_CONST char *fromPtr = (ICONV_CONST char *)bufIn;
size_t nFrom = nIn;
char *toPtr = (char *)bufOut;
size_t nTo = maxOut;
ICONV_CONST char *fromPtr = (ICONV_CONST char *)bufIn;
size_t nFrom = nIn;
char *toPtr = (char *)bufOut;
size_t nTo = maxOut;
while (nFrom > 0) {
while (nFrom > 0) {
#if defined(Q_OS_SYMBIAN)
size_t oneway = iconv(cd,(const char**) &fromPtr, &nFrom, &toPtr, &nTo);
#else
size_t oneway = iconv(cd,(char**) &fromPtr, &nFrom, &toPtr, &nTo);
#endif
if (oneway == (size_t)(-1)) {
iconv_close(cd);
delete[] bufOut;
throw ReaderException("error converting characters");
if (oneway == (size_t)(-1)) {
iconv_close(cd);
delete[] bufOut;
throw ReaderException("error converting characters");
}
}
}
iconv_close(cd);
iconv_close(cd);
int nResult = maxOut - nTo;
bufOut[nResult] = '\0';
result.append((const char *)bufOut);
delete[] bufOut;
int nResult = maxOut - nTo;
bufOut[nResult] = '\0';
result.append((const char *)bufOut);
delete[] bufOut;
#else
result.append((const char *)bufIn, nIn);
Q_UNUSED(src);
result.append((const char *)bufIn, nIn);
#endif
}
void DecodedBitStreamParser::decodeHanziSegment(Ref<BitSource> bits_,
string& result,
int count) {
BitSource& bits (*bits_);
// Don't crash trying to read more bits than we have available.
if (count * 13 > bits.available()) {
throw FormatException();
}
// Each character will require 2 bytes. Read the characters as 2-byte pairs
// and decode as GB2312 afterwards
size_t nBytes = 2 * count;
char* buffer = new char[nBytes];
int offset = 0;
while (count > 0) {
// Each 13 bits encodes a 2-byte character
int twoBytes = bits.readBits(13);
int assembledTwoBytes = ((twoBytes / 0x060) << 8) | (twoBytes % 0x060);
if (assembledTwoBytes < 0x003BF) {
// In the 0xA1A1 to 0xAAFE range
assembledTwoBytes += 0x0A1A1;
} else {
// In the 0xB0A1 to 0xFAFE range
assembledTwoBytes += 0x0A6A1;
BitSource& bits (*bits_);
// Don't crash trying to read more bits than we have available.
if (count * 13 > bits.available()) {
throw FormatException();
}
// Each character will require 2 bytes. Read the characters as 2-byte pairs
// and decode as GB2312 afterwards
size_t nBytes = 2 * count;
char* buffer = new char[nBytes];
int offset = 0;
while (count > 0) {
// Each 13 bits encodes a 2-byte character
int twoBytes = bits.readBits(13);
int assembledTwoBytes = ((twoBytes / 0x060) << 8) | (twoBytes % 0x060);
if (assembledTwoBytes < 0x003BF) {
// In the 0xA1A1 to 0xAAFE range
assembledTwoBytes += 0x0A1A1;
} else {
// In the 0xB0A1 to 0xFAFE range
assembledTwoBytes += 0x0A6A1;
}
buffer[offset] = (char) ((assembledTwoBytes >> 8) & 0xFF);
buffer[offset + 1] = (char) (assembledTwoBytes & 0xFF);
offset += 2;
count--;
}
try {
append(result, buffer, nBytes, StringUtils::GB2312);
} catch (ReaderException const& ignored) {
(void)ignored;
delete [] buffer;
throw FormatException();
}
buffer[offset] = (char) ((assembledTwoBytes >> 8) & 0xFF);
buffer[offset + 1] = (char) (assembledTwoBytes & 0xFF);
offset += 2;
count--;
}
try {
append(result, buffer, nBytes, StringUtils::GB2312);
} catch (ReaderException const& ignored) {
(void)ignored;
delete [] buffer;
throw FormatException();
}
delete [] buffer;
}
void DecodedBitStreamParser::decodeKanjiSegment(Ref<BitSource> bits, std::string &result, int count) {
// Each character will require 2 bytes. Read the characters as 2-byte pairs
// and decode as Shift_JIS afterwards
size_t nBytes = 2 * count;
char* buffer = new char[nBytes];
int offset = 0;
while (count > 0) {
// Each 13 bits encodes a 2-byte character
// Each character will require 2 bytes. Read the characters as 2-byte pairs
// and decode as Shift_JIS afterwards
size_t nBytes = 2 * count;
char* buffer = new char[nBytes];
int offset = 0;
while (count > 0) {
// Each 13 bits encodes a 2-byte character
int twoBytes = bits->readBits(13);
int assembledTwoBytes = ((twoBytes / 0x0C0) << 8) | (twoBytes % 0x0C0);
if (assembledTwoBytes < 0x01F00) {
// In the 0x8140 to 0x9FFC range
assembledTwoBytes += 0x08140;
} else {
// In the 0xE040 to 0xEBBF range
assembledTwoBytes += 0x0C140;
int twoBytes = bits->readBits(13);
int assembledTwoBytes = ((twoBytes / 0x0C0) << 8) | (twoBytes % 0x0C0);
if (assembledTwoBytes < 0x01F00) {
// In the 0x8140 to 0x9FFC range
assembledTwoBytes += 0x08140;
} else {
// In the 0xE040 to 0xEBBF range
assembledTwoBytes += 0x0C140;
}
buffer[offset] = (char)(assembledTwoBytes >> 8);
buffer[offset + 1] = (char)assembledTwoBytes;
offset += 2;
count--;
}
buffer[offset] = (char)(assembledTwoBytes >> 8);
buffer[offset + 1] = (char)assembledTwoBytes;
offset += 2;
count--;
}
try {
append(result, buffer, nBytes, StringUtils::SHIFT_JIS);
} catch (ReaderException const& ignored) {
(void)ignored;
delete [] buffer;
throw FormatException();
}
delete[] buffer;
try {
append(result, buffer, nBytes, StringUtils::SHIFT_JIS);
} catch (ReaderException const& ignored) {
(void)ignored;
delete [] buffer;
throw FormatException();
}
delete[] buffer;
}
void DecodedBitStreamParser::decodeByteSegment(Ref<BitSource> bits_,
string& result,
int count,
CharacterSetECI* currentCharacterSetECI,
ArrayRef< ArrayRef<char> >& byteSegments,
Hashtable const& hints) {
int nBytes = count;
BitSource& bits (*bits_);
// Don't crash trying to read more bits than we have available.
if (count << 3 > bits.available()) {
throw FormatException();
}
std::string DecodedBitStreamParser::decodeByteSegment(Ref<BitSource> bits_,
string& result,
int count,
CharacterSetECI* currentCharacterSetECI,
ArrayRef< ArrayRef<char> >& byteSegments,
Hashtable const& hints) {
int nBytes = count;
BitSource& bits (*bits_);
// Don't crash trying to read more bits than we have available.
if (count << 3 > bits.available()) {
throw FormatException();
}
ArrayRef<char> bytes_ (count);
char* readBytes = &(*bytes_)[0];
for (int i = 0; i < count; i++) {
readBytes[i] = (char) bits.readBits(8);
}
string encoding;
if (currentCharacterSetECI == 0) {
// The spec isn't clear on this mode; see
// section 6.4.5: t does not say which encoding to assuming
// upon decoding. I have seen ISO-8859-1 used as well as
// Shift_JIS -- without anything like an ECI designator to
// give a hint.
encoding = StringUtils::guessEncoding(readBytes, count, hints);
} else {
encoding = currentCharacterSetECI->name();
}
try {
append(result, readBytes, nBytes, encoding.c_str());
} catch (ReaderException const& ignored) {
(void)ignored;
throw FormatException();
}
byteSegments->values().push_back(bytes_);
ArrayRef<char> bytes_ (count);
char* readBytes = &(*bytes_)[0];
for (int i = 0; i < count; i++) {
readBytes[i] = (char) bits.readBits(8);
}
string encoding;
if (currentCharacterSetECI == 0) {
// The spec isn't clear on this mode; see
// section 6.4.5: t does not say which encoding to assuming
// upon decoding. I have seen ISO-8859-1 used as well as
// Shift_JIS -- without anything like an ECI designator to
// give a hint.
encoding = StringUtils::guessEncoding(readBytes, count, hints);
} else {
encoding = currentCharacterSetECI->name();
}
try {
append(result, readBytes, nBytes, encoding.c_str());
} catch (ReaderException const& ignored) {
(void)ignored;
throw FormatException();
}
byteSegments->values().push_back(bytes_);
return encoding;
}
void DecodedBitStreamParser::decodeNumericSegment(Ref<BitSource> bits, std::string &result, int count) {
int nBytes = count;
char* bytes = new char[nBytes];
int i = 0;
// Read three digits at a time
while (count >= 3) {
// Each 10 bits encodes three digits
if (bits->available() < 10) {
throw ReaderException("format exception");
int nBytes = count;
char* bytes = new char[nBytes];
int i = 0;
// Read three digits at a time
while (count >= 3) {
// Each 10 bits encodes three digits
if (bits->available() < 10) {
throw ReaderException("format exception");
}
int threeDigitsBits = bits->readBits(10);
if (threeDigitsBits >= 1000) {
ostringstream s;
s << "Illegal value for 3-digit unit: " << threeDigitsBits;
delete[] bytes;
throw ReaderException(s.str().c_str());
}
bytes[i++] = ALPHANUMERIC_CHARS[threeDigitsBits / 100];
bytes[i++] = ALPHANUMERIC_CHARS[(threeDigitsBits / 10) % 10];
bytes[i++] = ALPHANUMERIC_CHARS[threeDigitsBits % 10];
count -= 3;
}
int threeDigitsBits = bits->readBits(10);
if (threeDigitsBits >= 1000) {
ostringstream s;
s << "Illegal value for 3-digit unit: " << threeDigitsBits;
delete[] bytes;
throw ReaderException(s.str().c_str());
if (count == 2) {
if (bits->available() < 7) {
throw ReaderException("format exception");
}
// Two digits left over to read, encoded in 7 bits
int twoDigitsBits = bits->readBits(7);
if (twoDigitsBits >= 100) {
ostringstream s;
s << "Illegal value for 2-digit unit: " << twoDigitsBits;
delete[] bytes;
throw ReaderException(s.str().c_str());
}
bytes[i++] = ALPHANUMERIC_CHARS[twoDigitsBits / 10];
bytes[i++] = ALPHANUMERIC_CHARS[twoDigitsBits % 10];
} else if (count == 1) {
if (bits->available() < 4) {
throw ReaderException("format exception");
}
// One digit left over to read
int digitBits = bits->readBits(4);
if (digitBits >= 10) {
ostringstream s;
s << "Illegal value for digit unit: " << digitBits;
delete[] bytes;
throw ReaderException(s.str().c_str());
}
bytes[i++] = ALPHANUMERIC_CHARS[digitBits];
}
bytes[i++] = ALPHANUMERIC_CHARS[threeDigitsBits / 100];
bytes[i++] = ALPHANUMERIC_CHARS[(threeDigitsBits / 10) % 10];
bytes[i++] = ALPHANUMERIC_CHARS[threeDigitsBits % 10];
count -= 3;
}
if (count == 2) {
if (bits->available() < 7) {
throw ReaderException("format exception");
}
// Two digits left over to read, encoded in 7 bits
int twoDigitsBits = bits->readBits(7);
if (twoDigitsBits >= 100) {
ostringstream s;
s << "Illegal value for 2-digit unit: " << twoDigitsBits;
delete[] bytes;
throw ReaderException(s.str().c_str());
}
bytes[i++] = ALPHANUMERIC_CHARS[twoDigitsBits / 10];
bytes[i++] = ALPHANUMERIC_CHARS[twoDigitsBits % 10];
} else if (count == 1) {
if (bits->available() < 4) {
throw ReaderException("format exception");
}
// One digit left over to read
int digitBits = bits->readBits(4);
if (digitBits >= 10) {
ostringstream s;
s << "Illegal value for digit unit: " << digitBits;
delete[] bytes;
throw ReaderException(s.str().c_str());
}
bytes[i++] = ALPHANUMERIC_CHARS[digitBits];
}
append(result, bytes, nBytes, StringUtils::ASCII);
delete[] bytes;
append(result, bytes, nBytes, StringUtils::ASCII);
delete[] bytes;
}
char DecodedBitStreamParser::toAlphaNumericChar(size_t value) {
if (value >= sizeof(DecodedBitStreamParser::ALPHANUMERIC_CHARS)) {
throw FormatException();
}
return ALPHANUMERIC_CHARS[value];
if (value >= sizeof(DecodedBitStreamParser::ALPHANUMERIC_CHARS)) {
throw FormatException();
}
return ALPHANUMERIC_CHARS[value];
}
void DecodedBitStreamParser::decodeAlphanumericSegment(Ref<BitSource> bits_,
string& result,
int count,
bool fc1InEffect) {
BitSource& bits (*bits_);
ostringstream bytes;
// Read two characters at a time
while (count > 1) {
if (bits.available() < 11) {
throw FormatException();
}
int nextTwoCharsBits = bits.readBits(11);
bytes << toAlphaNumericChar(nextTwoCharsBits / 45);
bytes << toAlphaNumericChar(nextTwoCharsBits % 45);
count -= 2;
}
if (count == 1) {
// special case: one character left
if (bits.available() < 6) {
throw FormatException();
}
bytes << toAlphaNumericChar(bits.readBits(6));
}
// See section 6.4.8.1, 6.4.8.2
string s = bytes.str();
if (fc1InEffect) {
// We need to massage the result a bit if in an FNC1 mode:
ostringstream r;
for (size_t i = 0; i < s.length(); i++) {
if (s[i] != '%') {
r << s[i];
} else {
if (i < s.length() - 1 && s[i + 1] == '%') {
// %% is rendered as %
r << s[i++];
} else {
// In alpha mode, % should be converted to FNC1 separator 0x1D
r << (char)0x1D;
BitSource& bits (*bits_);
ostringstream bytes;
// Read two characters at a time
while (count > 1) {
if (bits.available() < 11) {
throw FormatException();
}
}
int nextTwoCharsBits = bits.readBits(11);
bytes << toAlphaNumericChar(nextTwoCharsBits / 45);
bytes << toAlphaNumericChar(nextTwoCharsBits % 45);
count -= 2;
}
s = r.str();
}
append(result, s, StringUtils::ASCII);
if (count == 1) {
// special case: one character left
if (bits.available() < 6) {
throw FormatException();
}
bytes << toAlphaNumericChar(bits.readBits(6));
}
// See section 6.4.8.1, 6.4.8.2
string s = bytes.str();
if (fc1InEffect) {
// We need to massage the result a bit if in an FNC1 mode:
ostringstream r;
for (size_t i = 0; i < s.length(); i++) {
if (s[i] != '%') {
r << s[i];
} else {
if (i < s.length() - 1 && s[i + 1] == '%') {
// %% is rendered as %
r << s[i++];
} else {
// In alpha mode, % should be converted to FNC1 separator 0x1D
r << (char)0x1D;
}
}
}
s = r.str();
}
append(result, s, StringUtils::ASCII);
}
namespace {
int parseECIValue(BitSource& bits) {
int parseECIValue(BitSource& bits) {
int firstByte = bits.readBits(8);
if ((firstByte & 0x80) == 0) {
// just one byte
return firstByte & 0x7F;
// just one byte
return firstByte & 0x7F;
}
if ((firstByte & 0xC0) == 0x80) {
// two bytes
int secondByte = bits.readBits(8);
return ((firstByte & 0x3F) << 8) | secondByte;
// two bytes
int secondByte = bits.readBits(8);
return ((firstByte & 0x3F) << 8) | secondByte;
}
if ((firstByte & 0xE0) == 0xC0) {
// three bytes
int secondThirdBytes = bits.readBits(16);
return ((firstByte & 0x1F) << 16) | secondThirdBytes;
// three bytes
int secondThirdBytes = bits.readBits(16);
return ((firstByte & 0x1F) << 16) | secondThirdBytes;
}
throw FormatException();
}
}
}
Ref<DecoderResult>
@ -352,80 +354,80 @@ DecodedBitStreamParser::decode(ArrayRef<char> bytes,
Version* version,
ErrorCorrectionLevel const& ecLevel,
Hashtable const& hints) {
Ref<BitSource> bits_ (new BitSource(bytes));
BitSource& bits (*bits_);
string result;
result.reserve(50);
ArrayRef< ArrayRef<char> > byteSegments (0);
try {
Ref<BitSource> bits_ (new BitSource(bytes));
BitSource& bits (*bits_);
string result;
result.reserve(50);
ArrayRef< ArrayRef<char> > byteSegments (0);
CharacterSetECI* currentCharacterSetECI = 0;
bool fc1InEffect = false;
Mode* mode = 0;
do {
// While still another segment to read...
if (bits.available() < 4) {
// OK, assume we're done. Really, a TERMINATOR mode should have been recorded here
mode = &Mode::TERMINATOR;
} else {
try {
mode = &Mode::forBits(bits.readBits(4)); // mode is encoded by 4 bits
} catch (IllegalArgumentException const& iae) {
throw iae;
// throw FormatException.getFormatInstance();
}
}
if (mode != &Mode::TERMINATOR) {
if ((mode == &Mode::FNC1_FIRST_POSITION) || (mode == &Mode::FNC1_SECOND_POSITION)) {
// We do little with FNC1 except alter the parsed result a bit according to the spec
fc1InEffect = true;
} else if (mode == &Mode::STRUCTURED_APPEND) {
if (bits.available() < 16) {
throw FormatException();
}
// not really supported; all we do is ignore it
// Read next 8 bits (symbol sequence #) and 8 bits (parity data), then continue
bits.readBits(16);
} else if (mode == &Mode::ECI) {
// Count doesn't apply to ECI
int value = parseECIValue(bits);
currentCharacterSetECI = CharacterSetECI::getCharacterSetECIByValue(value);
if (currentCharacterSetECI == 0) {
throw FormatException();
}
} else {
// First handle Hanzi mode which does not start with character count
if (mode == &Mode::HANZI) {
//chinese mode contains a sub set indicator right after mode indicator
int subset = bits.readBits(4);
int countHanzi = bits.readBits(mode->getCharacterCountBits(version));
if (subset == GB2312_SUBSET) {
decodeHanziSegment(bits_, result, countHanzi);
}
} else {
// "Normal" QR code modes:
// How many characters will follow, encoded in this mode?
int count = bits.readBits(mode->getCharacterCountBits(version));
if (mode == &Mode::NUMERIC) {
decodeNumericSegment(bits_, result, count);
} else if (mode == &Mode::ALPHANUMERIC) {
decodeAlphanumericSegment(bits_, result, count, fc1InEffect);
} else if (mode == &Mode::BYTE) {
decodeByteSegment(bits_, result, count, currentCharacterSetECI, byteSegments, hints);
} else if (mode == &Mode::KANJI) {
decodeKanjiSegment(bits_, result, count);
string charSet = "";
try {
bool fc1InEffect = false;
Mode* mode = 0;
do {
// While still another segment to read...
if (bits.available() < 4) {
// OK, assume we're done. Really, a TERMINATOR mode should have been recorded here
mode = &Mode::TERMINATOR;
} else {
throw FormatException();
try {
mode = &Mode::forBits(bits.readBits(4)); // mode is encoded by 4 bits
} catch (IllegalArgumentException const& iae) {
throw iae;
// throw FormatException.getFormatInstance();
}
}
}
}
}
} while (mode != &Mode::TERMINATOR);
} catch (IllegalArgumentException const& iae) {
(void)iae;
// from readBits() calls
throw FormatException();
}
return Ref<DecoderResult>(new DecoderResult(bytes, Ref<String>(new String(result)), byteSegments, (string)ecLevel));
if (mode != &Mode::TERMINATOR) {
if ((mode == &Mode::FNC1_FIRST_POSITION) || (mode == &Mode::FNC1_SECOND_POSITION)) {
// We do little with FNC1 except alter the parsed result a bit according to the spec
fc1InEffect = true;
} else if (mode == &Mode::STRUCTURED_APPEND) {
if (bits.available() < 16) {
throw FormatException();
}
// not really supported; all we do is ignore it
// Read next 8 bits (symbol sequence #) and 8 bits (parity data), then continue
bits.readBits(16);
} else if (mode == &Mode::ECI) {
// Count doesn't apply to ECI
int value = parseECIValue(bits);
currentCharacterSetECI = CharacterSetECI::getCharacterSetECIByValue(value);
if (currentCharacterSetECI == 0) {
throw FormatException();
}
} else {
// First handle Hanzi mode which does not start with character count
if (mode == &Mode::HANZI) {
//chinese mode contains a sub set indicator right after mode indicator
int subset = bits.readBits(4);
int countHanzi = bits.readBits(mode->getCharacterCountBits(version));
if (subset == GB2312_SUBSET) {
decodeHanziSegment(bits_, result, countHanzi);
}
} else {
// "Normal" QR code modes:
// How many characters will follow, encoded in this mode?
int count = bits.readBits(mode->getCharacterCountBits(version));
if (mode == &Mode::NUMERIC) {
decodeNumericSegment(bits_, result, count);
} else if (mode == &Mode::ALPHANUMERIC) {
decodeAlphanumericSegment(bits_, result, count, fc1InEffect);
} else if (mode == &Mode::BYTE) {
charSet = decodeByteSegment(bits_, result, count, currentCharacterSetECI, byteSegments, hints);
} else if (mode == &Mode::KANJI) {
decodeKanjiSegment(bits_, result, count);
} else {
throw FormatException();
}
}
}
}
} while (mode != &Mode::TERMINATOR);
} catch (IllegalArgumentException const& iae) {
(void)iae;
// from readBits() calls
throw FormatException();
}
return Ref<DecoderResult>(new DecoderResult(bytes, Ref<String>(new String(result)), byteSegments, (string)ecLevel, charSet));
}

View File

@ -226,7 +226,7 @@ int MatrixUtil::findMSBSet(int value)
{
int numDigits = 0;
while (value != 0) {
(size_t)value >> 1; // ??value >>>= 1;
value >>= 1;
++numDigits;
}
return numDigits;