mirror of
https://github.com/status-im/qzxing.git
synced 2025-02-04 15:14:33 +00:00
saving merge
This commit is contained in:
commit
e70dd5e1a2
@ -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);
|
||||
|
@ -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
|
||||
|
@ -31,7 +31,7 @@
|
||||
#ifndef QQRDECODER_H
|
||||
#define QQRDECODER_H
|
||||
|
||||
#include <QtGui/QMainWindow>
|
||||
#include <QMainWindow>
|
||||
#include <QPixmap>
|
||||
#include "ui_QQrDecoder.h"
|
||||
#include <qzxing.h>
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -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_;
|
||||
}
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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_;
|
||||
}
|
||||
|
@ -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();
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user