mirror of
https://github.com/seiichiro0185/sailotp.git
synced 2024-11-21 23:39:41 +00:00
Added a harbour-compatible QR-Code Reader
This commit is contained in:
parent
e5ff3b4a35
commit
d722da8688
266 changed files with 7611 additions and 17998 deletions
|
@ -32,7 +32,8 @@ OTHER_FILES += qml/harbour-sailotp.qml \
|
|||
qml/components/NotifyBanner.qml \
|
||||
qml/pages/ScanOTP.qml \
|
||||
qml/lib/urldecoder.js \
|
||||
qml/pages/QRPage.qml
|
||||
qml/pages/QRPage.qml \
|
||||
rpm/harbour-sailotp.changes
|
||||
|
||||
i18n.files = i18n/*.qm
|
||||
i18n.path = /usr/share/$${TARGET}/i18n
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
import QtQuick 2.0
|
||||
import QtMultimedia 5.0
|
||||
import Sailfish.Silica 1.0
|
||||
import Sailfish.Media 1.0 // Not allowed in harbour, but normal VideoOutput doesn't work yet!
|
||||
import harbour.sailotp.QZXing 2.2
|
||||
import harbour.sailotp.FileIO 1.0
|
||||
import "../lib/urldecoder.js" as URL
|
||||
|
@ -87,8 +86,6 @@ Page {
|
|||
QZXing {
|
||||
id: decoder
|
||||
|
||||
enabledDecoders: QZXing.DecoderFormat_QR_CODE
|
||||
|
||||
onTagFound: {
|
||||
console.log("Barcode data: " + tag)
|
||||
var ret = URL.decode(tag);
|
||||
|
@ -107,7 +104,7 @@ Page {
|
|||
id: fileIO
|
||||
}
|
||||
|
||||
GStreamerVideoOutput {
|
||||
VideoOutput {
|
||||
id: prev
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.top: header.bottom
|
||||
|
|
2
rpm/harbour-sailotp.changes
Normal file
2
rpm/harbour-sailotp.changes
Normal file
|
@ -0,0 +1,2 @@
|
|||
* Tue Jul 01 2014 Stefan Brand <sailfish@seiichiro0185.org> 1.0-1
|
||||
- Added harbour-compatible QR-Reader
|
|
@ -1,6 +1,6 @@
|
|||
Name: harbour-sailotp
|
||||
Summary: SailOTP
|
||||
Version: 0.8
|
||||
Version: 1.0
|
||||
Release: 1
|
||||
Group: Security
|
||||
URL: https://github.com/seiichiro0185/sailotp/
|
||||
|
@ -18,17 +18,14 @@ PkgConfigBR:
|
|||
- Qt5Quick
|
||||
- Qt5Qml
|
||||
- Qt5Core
|
||||
- sailfishapp >= 0.0.10
|
||||
- Qt5Multimedia
|
||||
- sailfishapp >= 1.0.2
|
||||
Requires:
|
||||
- sailfishsilica-qt5 >= 0.10.9
|
||||
Files:
|
||||
- '%{_bindir}'
|
||||
- '%{_datadir}/%{name}/qml'
|
||||
- '%{_datadir}/%{name}/i18n'
|
||||
- '%{_datadir}/applications/%{name}.desktop'
|
||||
- '%{_datadir}/icons/hicolor/86x86/apps/%{name}.png'
|
||||
- /usr/bin
|
||||
- /usr/share/harbour-sailotp
|
||||
- /usr/share/applications
|
||||
- /usr/share/icons/hicolor/86x86/apps
|
||||
- /usr/share/harbour-sailotp/i18n
|
||||
PkgBR: []
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
QT += core declarative
|
||||
QT += core quick
|
||||
|
||||
INCLUDEPATH += $$PWD/src
|
||||
|
||||
|
|
|
@ -1,18 +1,16 @@
|
|||
#include "CameraImageWrapper.h"
|
||||
#include <QColor>
|
||||
#include <QApplication>
|
||||
#include <QDesktopWidget>
|
||||
|
||||
CameraImageWrapper::CameraImageWrapper() : LuminanceSource(0,0), isSmoothTransformationEnabled(false)
|
||||
CameraImageWrapper::CameraImageWrapper() : LuminanceSource(), isSmoothTransformationEnabled(false)
|
||||
{
|
||||
}
|
||||
|
||||
CameraImageWrapper::CameraImageWrapper(QImage& image) : LuminanceSource(image.width(), image.height()) , isSmoothTransformationEnabled(false)
|
||||
CameraImageWrapper::CameraImageWrapper(QImage& image) : LuminanceSource() , isSmoothTransformationEnabled(false)
|
||||
{
|
||||
setImage(image);
|
||||
}
|
||||
|
||||
CameraImageWrapper::CameraImageWrapper(CameraImageWrapper& otherInstance) : LuminanceSource(otherInstance.getWidth(), otherInstance.getHeight()) , isSmoothTransformationEnabled(false)
|
||||
CameraImageWrapper::CameraImageWrapper(CameraImageWrapper& otherInstance) : LuminanceSource() , isSmoothTransformationEnabled(false)
|
||||
{
|
||||
image = otherInstance.getOriginalImage().copy();
|
||||
}
|
||||
|
@ -54,33 +52,30 @@ unsigned char* CameraImageWrapper::copyMatrix() const
|
|||
return newMatrix;
|
||||
}
|
||||
|
||||
bool CameraImageWrapper::setImage(QString fileName, int maxWidth, int maxHeight)
|
||||
bool CameraImageWrapper::setImage(QString fileName)
|
||||
{
|
||||
bool isLoaded = image.load(fileName);
|
||||
|
||||
if(!isLoaded)
|
||||
return false;
|
||||
|
||||
width = image.width();
|
||||
height = image.height();
|
||||
|
||||
scale(maxWidth, maxHeight);
|
||||
// if(image.width() > QApplication::desktop()->width())
|
||||
// image = image.scaled(QApplication::desktop()->width(), image.height(), Qt::IgnoreAspectRatio);
|
||||
|
||||
// if(image.height() > QApplication::desktop()->height())
|
||||
// image = image.scaled(image.width(), QApplication::desktop()->height(), Qt::IgnoreAspectRatio);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CameraImageWrapper::setImage(QImage newImage, int maxWidth, int maxHeight)
|
||||
bool CameraImageWrapper::setImage(QImage newImage)
|
||||
{
|
||||
if(newImage.isNull())
|
||||
return false;
|
||||
|
||||
image = newImage.copy();
|
||||
|
||||
width = image.width();
|
||||
height = image.height();
|
||||
|
||||
scale(maxWidth, maxHeight);
|
||||
|
||||
if(image.width() > 640)
|
||||
image = image.scaled(640, image.height(), Qt::KeepAspectRatio, isSmoothTransformationEnabled ? Qt::SmoothTransformation : Qt::FastTransformation);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -97,6 +92,8 @@ QImage CameraImageWrapper::grayScaleImage(QImage::Format f)
|
|||
}
|
||||
|
||||
return tmp;
|
||||
|
||||
//return image.convertToFormat(f);
|
||||
}
|
||||
|
||||
QImage CameraImageWrapper::getOriginalImage()
|
||||
|
@ -104,12 +101,16 @@ QImage CameraImageWrapper::getOriginalImage()
|
|||
return image;
|
||||
}
|
||||
|
||||
ArrayRef<char> CameraImageWrapper::getRow(int y, ArrayRef<char> row) const
|
||||
|
||||
unsigned char* CameraImageWrapper::getRow(int y, unsigned char* row)
|
||||
{
|
||||
int width = getWidth();
|
||||
|
||||
if (row->size() != width)
|
||||
row.reset(ArrayRef<char>(width));
|
||||
if (row == NULL)
|
||||
{
|
||||
row = new unsigned char[width];
|
||||
pRow = row;
|
||||
}
|
||||
|
||||
for (int x = 0; x < width; x++)
|
||||
row[x] = getPixel(x,y);
|
||||
|
@ -117,48 +118,27 @@ ArrayRef<char> CameraImageWrapper::getRow(int y, ArrayRef<char> row) const
|
|||
return row;
|
||||
}
|
||||
|
||||
ArrayRef<char> CameraImageWrapper::getMatrix() const
|
||||
unsigned char* CameraImageWrapper::getMatrix()
|
||||
{
|
||||
int width = getWidth();
|
||||
int height = getHeight();
|
||||
char* matrix = new char[width*height];
|
||||
char* m = matrix;
|
||||
unsigned char* matrix = new unsigned char[width*height];
|
||||
unsigned char* m = matrix;
|
||||
|
||||
for(int y=0; y<height; y++)
|
||||
{
|
||||
ArrayRef<char> tmpRow;
|
||||
tmpRow = getRow(y, ArrayRef<char>(width));
|
||||
#if __cplusplus > 199711L
|
||||
memcpy(m, tmpRow->values()..data(), width);
|
||||
#else
|
||||
memcpy(m, &tmpRow->values()[0], width);
|
||||
#endif
|
||||
unsigned char* tmpRow;
|
||||
memcpy(m, tmpRow = getRow(y, NULL), width);
|
||||
m += width * sizeof(unsigned char);
|
||||
|
||||
//delete tmpRow;
|
||||
delete tmpRow;
|
||||
}
|
||||
|
||||
//pMatrix = matrix;
|
||||
ArrayRef<char> arr = ArrayRef<char>(matrix, width*height);
|
||||
|
||||
if(matrix)
|
||||
delete matrix;
|
||||
|
||||
|
||||
return arr;
|
||||
pMatrix = matrix;
|
||||
return matrix;
|
||||
}
|
||||
|
||||
void CameraImageWrapper::setSmoothTransformation(bool enable)
|
||||
{
|
||||
isSmoothTransformationEnabled = enable;
|
||||
}
|
||||
|
||||
void CameraImageWrapper::scale(int maxWidth, int maxHeight)
|
||||
{
|
||||
if((maxWidth != 1 || maxHeight != 1) && (image.width() > maxWidth || image.height() > maxHeight))
|
||||
image = image.scaled(
|
||||
maxWidth != -1 ? maxWidth : image.width(),
|
||||
maxHeight != -1 ? maxHeight : image.height(),
|
||||
Qt::KeepAspectRatio,
|
||||
isSmoothTransformationEnabled ? Qt::SmoothTransformation : Qt::FastTransformation);
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include <QImage>
|
||||
#include <QString>
|
||||
#include <zxing/zxing/LuminanceSource.h>
|
||||
#include <zxing/LuminanceSource.h>
|
||||
|
||||
using namespace zxing;
|
||||
|
||||
|
@ -24,25 +24,19 @@ public:
|
|||
/**
|
||||
* Set the source of the image. If it fails, returns false.
|
||||
*/
|
||||
bool setImage(QString fileName, int maxWidth=-1, int maxHeight=-1);
|
||||
bool setImage(QImage newImage, int maxWidth=-1, int maxHeight=-1);
|
||||
bool setImage(QString fileName);
|
||||
bool setImage(QImage newImage);
|
||||
|
||||
QImage grayScaleImage(QImage::Format f);
|
||||
QImage getOriginalImage();
|
||||
|
||||
|
||||
// Callers take ownership of the returned memory and must call delete [] on it themselves.
|
||||
//unsigned char* getRow(int y, unsigned char* row);
|
||||
//unsigned char* getMatrix();
|
||||
|
||||
ArrayRef<char> getRow(int y, ArrayRef<char> row) const;
|
||||
ArrayRef<char> getMatrix() const;
|
||||
unsigned char* getRow(int y, unsigned char* row);
|
||||
unsigned char* getMatrix();
|
||||
|
||||
void setSmoothTransformation(bool enable);
|
||||
|
||||
private:
|
||||
void scale(int maxWidth, int maxHeight);
|
||||
|
||||
private:
|
||||
QImage image;
|
||||
unsigned char* pRow;
|
||||
|
|
|
@ -1,273 +1,191 @@
|
|||
QT += core gui
|
||||
QT += core gui quick
|
||||
|
||||
greaterThan(QT_VERSION, 4.7): QT += declarative
|
||||
|
||||
DEFINES += QZXING_LIBRARY \
|
||||
ZXING_ICONV_CONST \
|
||||
DISABLE_LIBRARY_FEATURES
|
||||
|
||||
INCLUDEPATH += $$PWD \
|
||||
$$PWD/zxing
|
||||
INCLUDEPATH += \
|
||||
$$PWD \
|
||||
$$PWD/zxing
|
||||
|
||||
|
||||
HEADERS += $$PWD/QZXing_global.h \
|
||||
HEADERS += $$PWD/QZXing_global.h \
|
||||
HEADERS += \
|
||||
$$PWD/CameraImageWrapper.h \
|
||||
$$PWD/imagehandler.h \
|
||||
$$PWD/qzxing.h \
|
||||
$$PWD/zxing/zxing/ZXing.h \
|
||||
$$PWD/zxing/zxing/IllegalStateException.h \
|
||||
$$PWD/zxing/zxing/InvertedLuminanceSource.h \
|
||||
$$PWD/zxing/zxing/ChecksumException.h \
|
||||
$$PWD/zxing/zxing/ResultPointCallback.h \
|
||||
$$PWD/zxing/zxing/ResultPoint.h \
|
||||
$$PWD/zxing/zxing/Result.h \
|
||||
$$PWD/zxing/zxing/ReaderException.h \
|
||||
$$PWD/zxing/zxing/Reader.h \
|
||||
$$PWD/zxing/zxing/NotFoundException.h \
|
||||
$$PWD/zxing/zxing/MultiFormatReader.h \
|
||||
$$PWD/zxing/zxing/LuminanceSource.h \
|
||||
$$PWD/zxing/zxing/FormatException.h \
|
||||
$$PWD/zxing/zxing/Exception.h \
|
||||
$$PWD/zxing/zxing/DecodeHints.h \
|
||||
$$PWD/zxing/zxing/BinaryBitmap.h \
|
||||
$$PWD/zxing/zxing/Binarizer.h \
|
||||
$$PWD/zxing/zxing/BarcodeFormat.h \
|
||||
$$PWD/zxing/zxing/aztec/AztecReader.h \
|
||||
$$PWD/zxing/zxing/aztec/AztecDetectorResult.h \
|
||||
$$PWD/zxing/zxing/aztec/decoder/Decoder.h \
|
||||
$$PWD/zxing/zxing/aztec/detector/Detector.h \
|
||||
$$PWD/zxing/zxing/common/StringUtils.h \
|
||||
$$PWD/zxing/zxing/common/Str.h \
|
||||
$$PWD/zxing/zxing/common/Point.h \
|
||||
$$PWD/zxing/zxing/common/PerspectiveTransform.h \
|
||||
$$PWD/zxing/zxing/common/IllegalArgumentException.h \
|
||||
$$PWD/zxing/zxing/common/HybridBinarizer.h \
|
||||
$$PWD/zxing/zxing/common/GridSampler.h \
|
||||
$$PWD/zxing/zxing/common/GreyscaleRotatedLuminanceSource.h \
|
||||
$$PWD/zxing/zxing/common/GreyscaleLuminanceSource.h \
|
||||
$$PWD/zxing/zxing/common/GlobalHistogramBinarizer.h \
|
||||
$$PWD/zxing/zxing/common/DetectorResult.h \
|
||||
$$PWD/zxing/zxing/common/DecoderResult.h \
|
||||
$$PWD/zxing/zxing/common/Counted.h \
|
||||
$$PWD/zxing/zxing/common/CharacterSetECI.h \
|
||||
$$PWD/zxing/zxing/common/BitSource.h \
|
||||
$$PWD/zxing/zxing/common/BitMatrix.h \
|
||||
$$PWD/zxing/zxing/common/BitArray.h \
|
||||
$$PWD/zxing/zxing/common/Array.h \
|
||||
$$PWD/zxing/zxing/common/detector/MathUtils.h \
|
||||
$$PWD/zxing/zxing/common/detector/JavaMath.h \
|
||||
$$PWD/zxing/zxing/common/detector/WhiteRectangleDetector.h \
|
||||
$$PWD/zxing/zxing/common/detector/MonochromeRectangleDetector.h \
|
||||
$$PWD/zxing/zxing/common/reedsolomon/ReedSolomonException.h \
|
||||
$$PWD/zxing/zxing/common/reedsolomon/ReedSolomonDecoder.h \
|
||||
$$PWD/zxing/zxing/common/reedsolomon/GenericGFPoly.h \
|
||||
$$PWD/zxing/zxing/common/reedsolomon/GenericGF.h \
|
||||
$$PWD/zxing/zxing/datamatrix/Version.h \
|
||||
$$PWD/zxing/zxing/datamatrix/DataMatrixReader.h \
|
||||
$$PWD/zxing/zxing/datamatrix/decoder/Decoder.h \
|
||||
$$PWD/zxing/zxing/datamatrix/decoder/DecodedBitStreamParser.h \
|
||||
$$PWD/zxing/zxing/datamatrix/decoder/DataBlock.h \
|
||||
$$PWD/zxing/zxing/datamatrix/decoder/BitMatrixParser.h \
|
||||
$$PWD/zxing/zxing/datamatrix/detector/DetectorException.h \
|
||||
$$PWD/zxing/zxing/datamatrix/detector/Detector.h \
|
||||
$$PWD/zxing/zxing/datamatrix/detector/CornerPoint.h \
|
||||
$$PWD/zxing/zxing/oned/UPCEReader.h \
|
||||
$$PWD/zxing/zxing/oned/UPCEANReader.h \
|
||||
$$PWD/zxing/zxing/oned/UPCAReader.h \
|
||||
$$PWD/zxing/zxing/oned/OneDResultPoint.h \
|
||||
$$PWD/zxing/zxing/oned/OneDReader.h \
|
||||
$$PWD/zxing/zxing/oned/MultiFormatUPCEANReader.h \
|
||||
$$PWD/zxing/zxing/oned/MultiFormatOneDReader.h \
|
||||
$$PWD/zxing/zxing/oned/ITFReader.h \
|
||||
$$PWD/zxing/zxing/oned/EAN13Reader.h \
|
||||
$$PWD/zxing/zxing/oned/EAN8Reader.h \
|
||||
$$PWD/zxing/zxing/oned/Code128Reader.h \
|
||||
$$PWD/zxing/zxing/oned/Code39Reader.h \
|
||||
$$PWD/zxing/zxing/oned/CodaBarReader.h \
|
||||
$$PWD/zxing/zxing/oned/Code93Reader.h \
|
||||
$$PWD/zxing/zxing/qrcode/Version.h \
|
||||
$$PWD/zxing/zxing/qrcode/QRCodeReader.h \
|
||||
$$PWD/zxing/zxing/qrcode/FormatInformation.h \
|
||||
$$PWD/zxing/zxing/qrcode/ErrorCorrectionLevel.h \
|
||||
$$PWD/zxing/zxing/qrcode/decoder/Mode.h \
|
||||
$$PWD/zxing/zxing/qrcode/decoder/Decoder.h \
|
||||
$$PWD/zxing/zxing/qrcode/decoder/DecodedBitStreamParser.h \
|
||||
$$PWD/zxing/zxing/qrcode/decoder/DataMask.h \
|
||||
$$PWD/zxing/zxing/qrcode/decoder/DataBlock.h \
|
||||
$$PWD/zxing/zxing/qrcode/decoder/BitMatrixParser.h \
|
||||
$$PWD/zxing/zxing/qrcode/detector/FinderPatternInfo.h \
|
||||
$$PWD/zxing/zxing/qrcode/detector/FinderPatternFinder.h \
|
||||
$$PWD/zxing/zxing/qrcode/detector/FinderPattern.h \
|
||||
$$PWD/zxing/zxing/qrcode/detector/Detector.h \
|
||||
$$PWD/zxing/zxing/qrcode/detector/AlignmentPatternFinder.h \
|
||||
$$PWD/zxing/zxing/qrcode/detector/AlignmentPattern.h \
|
||||
$$PWD/zxing/zxing/multi/MultipleBarcodeReader.h \
|
||||
$$PWD/zxing/zxing/multi/GenericMultipleBarcodeReader.h \
|
||||
$$PWD/zxing/zxing/multi/ByQuadrantReader.h \
|
||||
$$PWD/zxing/zxing/multi/qrcode/QRCodeMultiReader.h \
|
||||
$$PWD/zxing/zxing/multi/qrcode/detector/MultiFinderPatternFinder.h \
|
||||
$$PWD/zxing/zxing/multi/qrcode/detector/MultiDetector.h \
|
||||
$$PWD/zxing/zxing/pdf417/decoder/ec/ErrorCorrection.h \
|
||||
$$PWD/zxing/zxing/pdf417/decoder/ec/ModulusGF.h \
|
||||
$$PWD/zxing/zxing/pdf417/decoder/ec/ModulusPoly.h \
|
||||
$$PWD/zxing/zxing/pdf417/decoder/BitMatrixParser.h \
|
||||
$$PWD/zxing/zxing/pdf417/decoder/DecodedBitStreamParser.h \
|
||||
$$PWD/zxing/zxing/pdf417/decoder/Decoder.h \
|
||||
$$PWD/zxing/zxing/pdf417/detector/Detector.h \
|
||||
$$PWD/zxing/zxing/pdf417/detector/LinesSampler.h \
|
||||
$$PWD/zxing/zxing/pdf417/PDF417Reader.h \
|
||||
$$PWD/zxing/bigint/NumberlikeArray.hh \
|
||||
$$PWD/zxing/bigint/BigUnsignedInABase.hh \
|
||||
$$PWD/zxing/bigint/BigUnsigned.hh \
|
||||
$$PWD/zxing/bigint/BigIntegerUtils.hh \
|
||||
$$PWD/zxing/bigint/BigIntegerLibrary.hh \
|
||||
$$PWD/zxing/bigint/BigIntegerAlgorithms.hh \
|
||||
$$PWD/zxing/bigint/BigInteger.hh
|
||||
$$PWD/qzxing_global.h \
|
||||
$$PWD/zxing/ResultPointCallback.h \
|
||||
$$PWD/zxing/ResultPoint.h \
|
||||
$$PWD/zxing/Result.h \
|
||||
$$PWD/zxing/ReaderException.h \
|
||||
$$PWD/zxing/Reader.h \
|
||||
$$PWD/zxing/NotFoundException.h \
|
||||
$$PWD/zxing/MultiFormatReader.h \
|
||||
$$PWD/zxing/LuminanceSource.h \
|
||||
$$PWD/zxing/FormatException.h \
|
||||
$$PWD/zxing/Exception.h \
|
||||
$$PWD/zxing/DecodeHints.h \
|
||||
$$PWD/zxing/BinaryBitmap.h \
|
||||
$$PWD/zxing/Binarizer.h \
|
||||
$$PWD/zxing/BarcodeFormat.h \
|
||||
$$PWD/zxing/aztec/AztecReader.h \
|
||||
$$PWD/zxing/aztec/AztecDetectorResult.h \
|
||||
$$PWD/zxing/aztec/decoder/Decoder.h \
|
||||
$$PWD/zxing/aztec/detector/Detector.h \
|
||||
$$PWD/zxing/common/StringUtils.h \
|
||||
$$PWD/zxing/common/Str.h \
|
||||
$$PWD/zxing/common/Point.h \
|
||||
$$PWD/zxing/common/PerspectiveTransform.h \
|
||||
$$PWD/zxing/common/IllegalArgumentException.h \
|
||||
$$PWD/zxing/common/HybridBinarizer.h \
|
||||
$$PWD/zxing/common/GridSampler.h \
|
||||
$$PWD/zxing/common/GreyscaleRotatedLuminanceSource.h \
|
||||
$$PWD/zxing/common/GreyscaleLuminanceSource.h \
|
||||
$$PWD/zxing/common/GlobalHistogramBinarizer.h \
|
||||
$$PWD/zxing/common/EdgeDetector.h \
|
||||
$$PWD/zxing/common/DetectorResult.h \
|
||||
$$PWD/zxing/common/DecoderResult.h \
|
||||
$$PWD/zxing/common/Counted.h \
|
||||
$$PWD/zxing/common/CharacterSetECI.h \
|
||||
$$PWD/zxing/common/BitSource.h \
|
||||
$$PWD/zxing/common/BitMatrix.h \
|
||||
$$PWD/zxing/common/BitArray.h \
|
||||
$$PWD/zxing/common/Array.h \
|
||||
$$PWD/zxing/common/detector/WhiteRectangleDetector.h \
|
||||
$$PWD/zxing/common/detector/MonochromeRectangleDetector.h \
|
||||
$$PWD/zxing/common/reedsolomon/ReedSolomonException.h \
|
||||
$$PWD/zxing/common/reedsolomon/ReedSolomonDecoder.h \
|
||||
$$PWD/zxing/common/reedsolomon/GenericGFPoly.h \
|
||||
$$PWD/zxing/common/reedsolomon/GenericGF.h \
|
||||
$$PWD/zxing/datamatrix/Version.h \
|
||||
$$PWD/zxing/datamatrix/DataMatrixReader.h \
|
||||
$$PWD/zxing/datamatrix/decoder/Decoder.h \
|
||||
$$PWD/zxing/datamatrix/decoder/DecodedBitStreamParser.h \
|
||||
$$PWD/zxing/datamatrix/decoder/DataBlock.h \
|
||||
$$PWD/zxing/datamatrix/decoder/BitMatrixParser.h \
|
||||
$$PWD/zxing/datamatrix/detector/MonochromeRectangleDetector.h \
|
||||
$$PWD/zxing/datamatrix/detector/DetectorException.h \
|
||||
$$PWD/zxing/datamatrix/detector/Detector.h \
|
||||
$$PWD/zxing/datamatrix/detector/CornerPoint.h \
|
||||
$$PWD/zxing/oned/UPCEReader.h \
|
||||
$$PWD/zxing/oned/UPCEANReader.h \
|
||||
$$PWD/zxing/oned/UPCAReader.h \
|
||||
$$PWD/zxing/oned/OneDResultPoint.h \
|
||||
$$PWD/zxing/oned/OneDReader.h \
|
||||
$$PWD/zxing/oned/MultiFormatUPCEANReader.h \
|
||||
$$PWD/zxing/oned/MultiFormatOneDReader.h \
|
||||
$$PWD/zxing/oned/ITFReader.h \
|
||||
$$PWD/zxing/oned/EAN13Reader.h \
|
||||
$$PWD/zxing/oned/EAN8Reader.h \
|
||||
$$PWD/zxing/oned/Code128Reader.h \
|
||||
$$PWD/zxing/oned/Code39Reader.h \
|
||||
$$PWD/zxing/qrcode/Version.h \
|
||||
$$PWD/zxing/qrcode/QRCodeReader.h \
|
||||
$$PWD/zxing/qrcode/FormatInformation.h \
|
||||
$$PWD/zxing/qrcode/ErrorCorrectionLevel.h \
|
||||
$$PWD/zxing/qrcode/decoder/Mode.h \
|
||||
$$PWD/zxing/qrcode/decoder/Decoder.h \
|
||||
$$PWD/zxing/qrcode/decoder/DecodedBitStreamParser.h \
|
||||
$$PWD/zxing/qrcode/decoder/DataMask.h \
|
||||
$$PWD/zxing/qrcode/decoder/DataBlock.h \
|
||||
$$PWD/zxing/qrcode/decoder/BitMatrixParser.h \
|
||||
$$PWD/zxing/qrcode/detector/QREdgeDetector.h \
|
||||
$$PWD/zxing/qrcode/detector/FinderPatternInfo.h \
|
||||
$$PWD/zxing/qrcode/detector/FinderPatternFinder.h \
|
||||
$$PWD/zxing/qrcode/detector/FinderPattern.h \
|
||||
$$PWD/zxing/qrcode/detector/Detector.h \
|
||||
$$PWD/zxing/qrcode/detector/AlignmentPatternFinder.h \
|
||||
$$PWD/zxing/qrcode/detector/AlignmentPattern.h \
|
||||
$$PWD/zxing/multi/MultipleBarcodeReader.h \
|
||||
$$PWD/zxing/multi/GenericMultipleBarcodeReader.h \
|
||||
$$PWD/zxing/multi/ByQuadrantReader.h \
|
||||
$$PWD/zxing/multi/qrcode/QRCodeMultiReader.h \
|
||||
$$PWD/zxing/multi/qrcode/detector/MultiFinderPatternFinder.h \
|
||||
$$PWD/zxing/multi/qrcode/detector/MultiDetector.h
|
||||
|
||||
SOURCES += $$PWD/CameraImageWrapper.cpp \
|
||||
SOURCES += \
|
||||
$$PWD/CameraImageWrapper.cpp \
|
||||
$$PWD/qzxing.cpp \
|
||||
$$PWD/imagehandler.cpp \
|
||||
$$PWD/zxing/zxing/ResultIO.cpp \
|
||||
$$PWD/zxing/zxing/InvertedLuminanceSource.cpp \
|
||||
$$PWD/zxing/zxing/ChecksumException.cpp \
|
||||
$$PWD/zxing/zxing/ResultPointCallback.cpp \
|
||||
$$PWD/zxing/zxing/ResultPoint.cpp \
|
||||
$$PWD/zxing/zxing/Result.cpp \
|
||||
$$PWD/zxing/zxing/Reader.cpp \
|
||||
$$PWD/zxing/zxing/MultiFormatReader.cpp \
|
||||
$$PWD/zxing/zxing/LuminanceSource.cpp \
|
||||
$$PWD/zxing/zxing/FormatException.cpp \
|
||||
$$PWD/zxing/zxing/Exception.cpp \
|
||||
$$PWD/zxing/zxing/DecodeHints.cpp \
|
||||
$$PWD/zxing/zxing/BinaryBitmap.cpp \
|
||||
$$PWD/zxing/zxing/Binarizer.cpp \
|
||||
$$PWD/zxing/zxing/BarcodeFormat.cpp \
|
||||
$$PWD/zxing/zxing/aztec/AztecReader.cpp \
|
||||
$$PWD/zxing/zxing/aztec/AztecDetectorResult.cpp \
|
||||
$$PWD/zxing/zxing/common/StringUtils.cpp \
|
||||
$$PWD/zxing/zxing/common/Str.cpp \
|
||||
$$PWD/zxing/zxing/common/PerspectiveTransform.cpp \
|
||||
$$PWD/zxing/zxing/common/IllegalArgumentException.cpp \
|
||||
$$PWD/zxing/zxing/common/HybridBinarizer.cpp \
|
||||
$$PWD/zxing/zxing/common/GridSampler.cpp \
|
||||
$$PWD/zxing/zxing/common/GreyscaleRotatedLuminanceSource.cpp \
|
||||
$$PWD/zxing/zxing/common/GreyscaleLuminanceSource.cpp \
|
||||
$$PWD/zxing/zxing/common/GlobalHistogramBinarizer.cpp \
|
||||
$$PWD/zxing/zxing/common/DetectorResult.cpp \
|
||||
$$PWD/zxing/zxing/common/DecoderResult.cpp \
|
||||
$$PWD/zxing/zxing/common/CharacterSetECI.cpp \
|
||||
$$PWD/zxing/zxing/common/BitSource.cpp \
|
||||
$$PWD/zxing/zxing/common/BitMatrix.cpp \
|
||||
$$PWD/zxing/zxing/common/BitArray.cpp \
|
||||
$$PWD/zxing/zxing/common/BitArrayIO.cpp \
|
||||
$$PWD/zxing/zxing/common/detector/WhiteRectangleDetector.cpp \
|
||||
$$PWD/zxing/zxing/common/detector/MonochromeRectangleDetector.cpp \
|
||||
$$PWD/zxing/zxing/common/reedsolomon/ReedSolomonException.cpp \
|
||||
$$PWD/zxing/zxing/common/reedsolomon/ReedSolomonDecoder.cpp \
|
||||
$$PWD/zxing/zxing/common/reedsolomon/GenericGFPoly.cpp \
|
||||
$$PWD/zxing/zxing/common/reedsolomon/GenericGF.cpp \
|
||||
$$PWD/zxing/zxing/datamatrix/DataMatrixReader.cpp \
|
||||
$$PWD/zxing/zxing/oned/UPCEReader.cpp \
|
||||
$$PWD/zxing/zxing/oned/UPCEANReader.cpp \
|
||||
$$PWD/zxing/zxing/oned/UPCAReader.cpp \
|
||||
$$PWD/zxing/zxing/oned/OneDResultPoint.cpp \
|
||||
$$PWD/zxing/zxing/oned/OneDReader.cpp \
|
||||
$$PWD/zxing/zxing/oned/MultiFormatUPCEANReader.cpp \
|
||||
$$PWD/zxing/zxing/oned/MultiFormatOneDReader.cpp \
|
||||
$$PWD/zxing/zxing/oned/ITFReader.cpp \
|
||||
$$PWD/zxing/zxing/oned/EAN13Reader.cpp \
|
||||
$$PWD/zxing/zxing/oned/EAN8Reader.cpp \
|
||||
$$PWD/zxing/zxing/oned/Code128Reader.cpp \
|
||||
$$PWD/zxing/zxing/oned/Code39Reader.cpp \
|
||||
$$PWD/zxing/zxing/oned/CodaBarReader.cpp \
|
||||
$$PWD/zxing/zxing/oned/Code93Reader.cpp \
|
||||
$$PWD/zxing/zxing/qrcode/QRCodeReader.cpp \
|
||||
$$PWD/zxing/zxing/multi/MultipleBarcodeReader.cpp \
|
||||
$$PWD/zxing/zxing/multi/GenericMultipleBarcodeReader.cpp \
|
||||
$$PWD/zxing/zxing/multi/ByQuadrantReader.cpp \
|
||||
$$PWD/zxing/zxing/multi/qrcode/QRCodeMultiReader.cpp \
|
||||
$$PWD/zxing/zxing/multi/qrcode/detector/MultiFinderPatternFinder.cpp \
|
||||
$$PWD/zxing/zxing/multi/qrcode/detector/MultiDetector.cpp \
|
||||
$$PWD/zxing/zxing/aztec/decoder/AztecDecoder.cpp \
|
||||
$$PWD/zxing/zxing/aztec/detector/AztecDetector.cpp \
|
||||
$$PWD/zxing/zxing/datamatrix/DataMatrixVersion.cpp \
|
||||
$$PWD/zxing/zxing/datamatrix/decoder/DataMatrixDecoder.cpp \
|
||||
$$PWD/zxing/zxing/datamatrix/decoder/DataMatrixBitMatrixParser.cpp \
|
||||
$$PWD/zxing/zxing/datamatrix/decoder/DataMatrixDataBlock.cpp \
|
||||
$$PWD/zxing/zxing/datamatrix/decoder/DataMatrixDecodedBitStreamParser.cpp \
|
||||
$$PWD/zxing/zxing/datamatrix/detector/DataMatrixCornerPoint.cpp \
|
||||
$$PWD/zxing/zxing/datamatrix/detector/DataMatrixDetector.cpp \
|
||||
$$PWD/zxing/zxing/datamatrix/detector/DataMatrixDetectorException.cpp \
|
||||
$$PWD/zxing/zxing/qrcode/decoder/QRBitMatrixParser.cpp \
|
||||
$$PWD/zxing/zxing/qrcode/decoder/QRDataBlock.cpp \
|
||||
$$PWD/zxing/zxing/qrcode/decoder/QRDataMask.cpp \
|
||||
$$PWD/zxing/zxing/qrcode/decoder/QRDecodedBitStreamParser.cpp \
|
||||
$$PWD/zxing/zxing/qrcode/decoder/QRDecoder.cpp \
|
||||
$$PWD/zxing/zxing/qrcode/decoder/QRMode.cpp \
|
||||
$$PWD/zxing/zxing/qrcode/detector/QRAlignmentPattern.cpp \
|
||||
$$PWD/zxing/zxing/qrcode/detector/QRAlignmentPatternFinder.cpp \
|
||||
$$PWD/zxing/zxing/qrcode/detector/QRDetector.cpp \
|
||||
$$PWD/zxing/zxing/qrcode/detector/QRFinderPattern.cpp \
|
||||
$$PWD/zxing/zxing/qrcode/detector/QRFinderPatternFinder.cpp \
|
||||
$$PWD/zxing/zxing/qrcode/detector/QRFinderPatternInfo.cpp \
|
||||
$$PWD/zxing/zxing/qrcode/QRVersion.cpp \
|
||||
$$PWD/zxing/zxing/qrcode/QRFormatInformation.cpp \
|
||||
$$PWD/zxing/zxing/qrcode/QRErrorCorrectionLevel.cpp \
|
||||
$$PWD/zxing/zxing/pdf417/decoder/ec/ErrorCorrection.cpp \
|
||||
$$PWD/zxing/zxing/pdf417/decoder/ec/ModulusGF.cpp \
|
||||
$$PWD/zxing/zxing/pdf417/decoder/ec/ModulusPoly.cpp \
|
||||
$$PWD/zxing/zxing/pdf417/decoder/PDF417BitMatrixParser.cpp \
|
||||
$$PWD/zxing/zxing/pdf417/decoder/PDF417DecodedBitStreamParser.cpp \
|
||||
$$PWD/zxing/zxing/pdf417/decoder/PDF417Decoder.cpp \
|
||||
$$PWD/zxing/zxing/pdf417/detector/PDF417Detector.cpp \
|
||||
$$PWD/zxing/zxing/pdf417/detector/LinesSampler.cpp \
|
||||
$$PWD/zxing/zxing/pdf417/PDF417Reader.cpp \
|
||||
$$PWD/zxing/bigint/BigUnsignedInABase.cc \
|
||||
$$PWD/zxing/bigint/BigUnsigned.cc \
|
||||
$$PWD/zxing/bigint/BigIntegerUtils.cc \
|
||||
$$PWD/zxing/bigint/BigIntegerAlgorithms.cc \
|
||||
$$PWD/zxing/bigint/BigInteger.cc
|
||||
$$PWD/zxing/ResultPointCallback.cpp \
|
||||
$$PWD/zxing/ResultPoint.cpp \
|
||||
$$PWD/zxing/Result.cpp \
|
||||
$$PWD/zxing/ReaderException.cpp \
|
||||
$$PWD/zxing/Reader.cpp \
|
||||
$$PWD/zxing/NotFoundException.cpp \
|
||||
$$PWD/zxing/MultiFormatReader.cpp \
|
||||
$$PWD/zxing/LuminanceSource.cpp \
|
||||
$$PWD/zxing/FormatException.cpp \
|
||||
$$PWD/zxing/Exception.cpp \
|
||||
$$PWD/zxing/DecodeHints.cpp \
|
||||
$$PWD/zxing/BinaryBitmap.cpp \
|
||||
$$PWD/zxing/Binarizer.cpp \
|
||||
$$PWD/zxing/BarcodeFormat.cpp \
|
||||
$$PWD/zxing/aztec/AztecReader.cpp \
|
||||
$$PWD/zxing/aztec/AztecDetectorResult.cpp \
|
||||
$$PWD/zxing/common/StringUtils.cpp \
|
||||
$$PWD/zxing/common/Str.cpp \
|
||||
$$PWD/zxing/common/PerspectiveTransform.cpp \
|
||||
$$PWD/zxing/common/IllegalArgumentException.cpp \
|
||||
$$PWD/zxing/common/HybridBinarizer.cpp \
|
||||
$$PWD/zxing/common/GridSampler.cpp \
|
||||
$$PWD/zxing/common/GreyscaleRotatedLuminanceSource.cpp \
|
||||
$$PWD/zxing/common/GreyscaleLuminanceSource.cpp \
|
||||
$$PWD/zxing/common/GlobalHistogramBinarizer.cpp \
|
||||
$$PWD/zxing/common/EdgeDetector.cpp \
|
||||
$$PWD/zxing/common/DetectorResult.cpp \
|
||||
$$PWD/zxing/common/DecoderResult.cpp \
|
||||
$$PWD/zxing/common/Counted.cpp \
|
||||
$$PWD/zxing/common/CharacterSetECI.cpp \
|
||||
$$PWD/zxing/common/BitSource.cpp \
|
||||
$$PWD/zxing/common/BitMatrix.cpp \
|
||||
$$PWD/zxing/common/BitArray.cpp \
|
||||
$$PWD/zxing/common/Array.cpp \
|
||||
$$PWD/zxing/common/detector/WhiteRectangleDetector.cpp \
|
||||
$$PWD/zxing/common/detector/MonochromeRectangleDetector.cpp \
|
||||
$$PWD/zxing/common/reedsolomon/ReedSolomonException.cpp \
|
||||
$$PWD/zxing/common/reedsolomon/ReedSolomonDecoder.cpp \
|
||||
$$PWD/zxing/common/reedsolomon/GenericGFPoly.cpp \
|
||||
$$PWD/zxing/common/reedsolomon/GenericGF.cpp \
|
||||
$$PWD/zxing/datamatrix/DataMatrixReader.cpp \
|
||||
$$PWD/zxing/oned/UPCEReader.cpp \
|
||||
$$PWD/zxing/oned/UPCEANReader.cpp \
|
||||
$$PWD/zxing/oned/UPCAReader.cpp \
|
||||
$$PWD/zxing/oned/OneDResultPoint.cpp \
|
||||
$$PWD/zxing/oned/OneDReader.cpp \
|
||||
$$PWD/zxing/oned/MultiFormatUPCEANReader.cpp \
|
||||
$$PWD/zxing/oned/MultiFormatOneDReader.cpp \
|
||||
$$PWD/zxing/oned/ITFReader.cpp \
|
||||
$$PWD/zxing/oned/EAN13Reader.cpp \
|
||||
$$PWD/zxing/oned/EAN8Reader.cpp \
|
||||
$$PWD/zxing/oned/Code128Reader.cpp \
|
||||
$$PWD/zxing/oned/Code39Reader.cpp \
|
||||
$$PWD/zxing/qrcode/QRCodeReader.cpp \
|
||||
$$PWD/zxing/qrcode/detector/QREdgeDetector.cpp \
|
||||
$$PWD/zxing/multi/MultipleBarcodeReader.cpp \
|
||||
$$PWD/zxing/multi/GenericMultipleBarcodeReader.cpp \
|
||||
$$PWD/zxing/multi/ByQuadrantReader.cpp \
|
||||
$$PWD/zxing/multi/qrcode/QRCodeMultiReader.cpp \
|
||||
$$PWD/zxing/multi/qrcode/detector/MultiFinderPatternFinder.cpp \
|
||||
$$PWD/zxing/multi/qrcode/detector/MultiDetector.cpp \
|
||||
$$PWD/zxing/aztec/decoder/AztecDecoder.cpp \
|
||||
$$PWD/zxing/aztec/detector/AztecDetector.cpp \
|
||||
$$PWD/zxing/datamatrix/DataMatrixVersion.cpp \
|
||||
$$PWD/zxing/datamatrix/decoder/DataMatrixDecoder.cpp \
|
||||
$$PWD/zxing/datamatrix/decoder/DataMatrixBitMatrixParser.cpp \
|
||||
$$PWD/zxing/datamatrix/decoder/DataMatrixDataBlock.cpp \
|
||||
$$PWD/zxing/datamatrix/decoder/DataMatrixDecodedBitStreamParser.cpp \
|
||||
$$PWD/zxing/datamatrix/detector/DataMatrixCornerPoint.cpp \
|
||||
$$PWD/zxing/datamatrix/detector/DataMatrixDetector.cpp \
|
||||
$$PWD/zxing/datamatrix/detector/DataMatrixDetectorException.cpp \
|
||||
$$PWD/zxing/datamatrix/detector/DataMatrixMonochromeRectangleDetector.cpp \
|
||||
$$PWD/zxing/qrcode/decoder/QRBitMatrixParser.cpp \
|
||||
$$PWD/zxing/qrcode/decoder/QRDataBlock.cpp \
|
||||
$$PWD/zxing/qrcode/decoder/QRDataMask.cpp \
|
||||
$$PWD/zxing/qrcode/decoder/QRDecodedBitStreamParser.cpp \
|
||||
$$PWD/zxing/qrcode/decoder/QRDecoder.cpp \
|
||||
$$PWD/zxing/qrcode/decoder/QRMode.cpp \
|
||||
$$PWD/zxing/qrcode/detector/QRAlignmentPattern.cpp \
|
||||
$$PWD/zxing/qrcode/detector/QRAlignmentPatternFinder.cpp \
|
||||
$$PWD/zxing/qrcode/detector/QRDetector.cpp \
|
||||
$$PWD/zxing/qrcode/detector/QRFinderPattern.cpp \
|
||||
$$PWD/zxing/qrcode/detector/QRFinderPatternFinder.cpp \
|
||||
$$PWD/zxing/qrcode/detector/QRFinderPatternInfo.cpp \
|
||||
$$PWD/zxing/qrcode/QRVersion.cpp \
|
||||
$$PWD/zxing/qrcode/QRFormatInformation.cpp \
|
||||
$$PWD/zxing/qrcode/QRErrorCorrectionLevel.cpp
|
||||
|
||||
symbian {
|
||||
TARGET.UID3 = 0xE618743C
|
||||
TARGET.EPOCALLOWDLLDATA = 1
|
||||
|
||||
#TARGET.CAPABILITY = All -TCB -AllFiles -DRM
|
||||
TARGET.CAPABILITY += NetworkServices \
|
||||
ReadUserData \
|
||||
WriteUserData \
|
||||
LocalServices \
|
||||
UserEnvironment \
|
||||
Location
|
||||
}
|
||||
|
||||
unix:!symbian {
|
||||
maemo5 {
|
||||
target.path = /opt/usr/lib
|
||||
} else {
|
||||
target.path = /usr/lib
|
||||
}
|
||||
|
||||
DEFINES += NOFMAXL
|
||||
# INSTALLS += target
|
||||
}
|
||||
|
||||
win32-msvc*{
|
||||
|
||||
INCLUDEPATH += $$PWD/zxing/win32/zxing \
|
||||
$$PWD/zxing/win32/zxing/stdint
|
||||
HEADERS += $$PWD/zxing/win32/zxing/stdint/stdint.h \
|
||||
$$PWD/zxing/win32/zxing/iconv.h
|
||||
|
||||
SOURCES += $$PWD/zxing/win32/zxing/win_iconv.c
|
||||
}
|
||||
|
||||
win32-g++{
|
||||
|
||||
INCLUDEPATH += $$PWD/zxing/win32/zxing
|
||||
|
||||
HEADERS += $$PWD/zxing/win32/zxing/iconv.h
|
||||
|
||||
SOURCES += $$PWD/zxing/win32/zxing/win_iconv.c
|
||||
}
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
#include "imagehandler.h"
|
||||
#include <QGraphicsObject>
|
||||
#include <QImage>
|
||||
#include <QPainter>
|
||||
#include <QStyleOptionGraphicsItem>
|
||||
#include <QDebug>
|
||||
|
||||
ImageHandler::ImageHandler(QObject *parent) :
|
||||
QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
QImage ImageHandler::extractQImage(QObject *imageObj,
|
||||
const double offsetX, const double offsetY,
|
||||
const double width, const double height)
|
||||
{
|
||||
QGraphicsObject *item = qobject_cast<QGraphicsObject*>(imageObj);
|
||||
|
||||
if (!item) {
|
||||
qDebug() << "Item is NULL";
|
||||
return QImage();
|
||||
}
|
||||
|
||||
QImage img(item->boundingRect().size().toSize(), QImage::Format_RGB32);
|
||||
img.fill(QColor(255, 255, 255).rgb());
|
||||
QPainter painter(&img);
|
||||
QStyleOptionGraphicsItem styleOption;
|
||||
item->paint(&painter, &styleOption);
|
||||
|
||||
if(offsetX == 0 && offsetY == 0 && width == 0 && height == 0)
|
||||
return img;
|
||||
else
|
||||
{
|
||||
return img.copy(offsetX, offsetY, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
void ImageHandler::save(QObject *imageObj, const QString &path,
|
||||
const double offsetX, const double offsetY,
|
||||
const double width, const double height)
|
||||
{
|
||||
QImage img = extractQImage(imageObj, offsetX, offsetY, width, height);
|
||||
img.save(path);
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
#ifndef IMAGEHANDLER_H
|
||||
#define IMAGEHANDLER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QImage>
|
||||
|
||||
class ImageHandler : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ImageHandler(QObject *parent = 0);
|
||||
|
||||
QImage extractQImage(QObject *imageObj,
|
||||
const double offsetX = 0 , const double offsetY = 0,
|
||||
const double width = 0, const double height = 0);
|
||||
|
||||
public slots:
|
||||
void save(QObject *item, const QString &path,
|
||||
const double offsetX = 0, const double offsetY = 0,
|
||||
const double width = 0, const double height = 0);
|
||||
};
|
||||
|
||||
#endif // IMAGEHANDLER_H
|
|
@ -1,19 +1,19 @@
|
|||
#include "qzxing.h"
|
||||
|
||||
#include <QtCore>
|
||||
#include <zxing/common/GlobalHistogramBinarizer.h>
|
||||
#include <zxing/Binarizer.h>
|
||||
#include <zxing/BinaryBitmap.h>
|
||||
#include <zxing/MultiFormatReader.h>
|
||||
#include <zxing/DecodeHints.h>
|
||||
#include "CameraImageWrapper.h"
|
||||
#include "imagehandler.h"
|
||||
#include <QTime>
|
||||
|
||||
using namespace zxing;
|
||||
|
||||
QZXing::QZXing(QObject *parent) : QObject(parent)
|
||||
{
|
||||
decoder = new MultiFormatReader();
|
||||
setDecoder(DecoderFormat_QR_CODE);
|
||||
/*setDecoder(DecoderFormat_QR_CODE |
|
||||
DecoderFormat_DATA_MATRIX |
|
||||
DecoderFormat_UPC_E |
|
||||
|
@ -24,165 +24,156 @@ QZXing::QZXing(QObject *parent) : QObject(parent)
|
|||
DecoderFormat_CODE_39 |
|
||||
DecoderFormat_ITF |
|
||||
DecoderFormat_Aztec);*/
|
||||
imageHandler = new ImageHandler();
|
||||
}
|
||||
|
||||
QZXing::QZXing(QZXing::DecoderFormat decodeHints, QObject *parent) : QObject(parent)
|
||||
{
|
||||
decoder = new MultiFormatReader();
|
||||
imageHandler = new ImageHandler();
|
||||
|
||||
setDecoder(decodeHints);
|
||||
QZXing::~QZXing() {
|
||||
delete (MultiFormatReader*)decoder;
|
||||
decoder = 0;
|
||||
}
|
||||
|
||||
void QZXing::setDecoder(const uint &hint)
|
||||
void QZXing::setDecoder(DecoderFormatType hint)
|
||||
{
|
||||
unsigned int newHints = 0;
|
||||
|
||||
if(hint & DecoderFormat_Aztec)
|
||||
newHints |= DecodeHints::AZTEC_HINT;
|
||||
|
||||
if(hint & DecoderFormat_CODABAR)
|
||||
newHints |= DecodeHints::CODABAR_HINT;
|
||||
|
||||
if(hint & DecoderFormat_CODE_39)
|
||||
newHints |= DecodeHints::CODE_39_HINT;
|
||||
|
||||
if(hint & DecoderFormat_CODE_93)
|
||||
newHints |= DecodeHints::CODE_93_HINT;
|
||||
|
||||
if(hint & DecoderFormat_CODE_128)
|
||||
newHints |= DecodeHints::CODE_128_HINT;
|
||||
|
||||
if(hint & DecoderFormat_DATA_MATRIX)
|
||||
newHints |= DecodeHints::DATA_MATRIX_HINT;
|
||||
|
||||
if(hint & DecoderFormat_EAN_8)
|
||||
newHints |= DecodeHints::EAN_8_HINT;
|
||||
|
||||
if(hint & DecoderFormat_EAN_13)
|
||||
newHints |= DecodeHints::EAN_13_HINT;
|
||||
|
||||
if(hint & DecoderFormat_ITF)
|
||||
newHints |= DecodeHints::ITF_HINT;
|
||||
|
||||
if(hint & DecoderFormat_MAXICODE)
|
||||
newHints |= DecodeHints::MAXICODE_HINT;
|
||||
|
||||
if(hint & DecoderFormat_PDF_417)
|
||||
newHints |= DecodeHints::PDF_417_HINT;
|
||||
DecodeHints newHints;
|
||||
|
||||
if(hint & DecoderFormat_QR_CODE)
|
||||
newHints |= DecodeHints::QR_CODE_HINT;
|
||||
newHints.addFormat((BarcodeFormat)BarcodeFormat_QR_CODE);
|
||||
|
||||
if(hint & DecoderFormat_RSS_14)
|
||||
newHints |= DecodeHints::RSS_14_HINT;
|
||||
|
||||
if(hint & DecoderFormat_RSS_EXPANDED)
|
||||
newHints |= DecodeHints::RSS_EXPANDED_HINT;
|
||||
|
||||
if(hint & DecoderFormat_UPC_A)
|
||||
newHints |= DecodeHints::UPC_A_HINT;
|
||||
if(hint & DecoderFormat_DATA_MATRIX)
|
||||
newHints.addFormat((BarcodeFormat)BarcodeFormat_DATA_MATRIX);
|
||||
|
||||
if(hint & DecoderFormat_UPC_E)
|
||||
newHints |= DecodeHints::UPC_E_HINT;
|
||||
newHints.addFormat((BarcodeFormat)BarcodeFormat_UPC_E);
|
||||
|
||||
if(hint & DecoderFormat_UPC_EAN_EXTENSION)
|
||||
newHints |= DecodeHints::UPC_EAN_EXTENSION_HINT;
|
||||
if(hint & DecoderFormat_UPC_A)
|
||||
newHints.addFormat((BarcodeFormat)BarcodeFormat_UPC_A);
|
||||
|
||||
enabledDecoders = newHints;
|
||||
if(hint & DecoderFormat_EAN_8)
|
||||
newHints.addFormat((BarcodeFormat)BarcodeFormat_EAN_8);
|
||||
|
||||
emit enabledFormatsChanged();
|
||||
if(hint & DecoderFormat_EAN_13)
|
||||
newHints.addFormat((BarcodeFormat)BarcodeFormat_EAN_13);
|
||||
|
||||
if(hint & DecoderFormat_CODE_128)
|
||||
newHints.addFormat((BarcodeFormat)BarcodeFormat_CODE_128);
|
||||
|
||||
if(hint & DecoderFormat_CODE_39)
|
||||
newHints.addFormat((BarcodeFormat)BarcodeFormat_CODE_39);
|
||||
|
||||
if(hint & DecoderFormat_ITF)
|
||||
newHints.addFormat((BarcodeFormat)BarcodeFormat_ITF);
|
||||
|
||||
if(hint & DecoderFormat_Aztec)
|
||||
newHints.addFormat((BarcodeFormat)BarcodeFormat_AZTEC);
|
||||
|
||||
supportedFormats = newHints.getCurrentHint();
|
||||
}
|
||||
|
||||
QString QZXing::decodeImage(QImage image, int maxWidth, int maxHeight, bool smoothTransformation)
|
||||
|
||||
QString QZXing::decodeImage(QImage image)
|
||||
{
|
||||
QTime t;
|
||||
t.start();
|
||||
Ref<Result> res;
|
||||
Ref<Result> result;
|
||||
emit decodingStarted();
|
||||
|
||||
if(image.isNull())
|
||||
{
|
||||
emit decodingFinished(false);
|
||||
processingTime = -1;
|
||||
return "";
|
||||
}
|
||||
try {
|
||||
Ref<LuminanceSource> source(new CameraImageWrapper(image));
|
||||
|
||||
try{
|
||||
CameraImageWrapper* ciw;
|
||||
Ref<Binarizer> binarizer;
|
||||
binarizer = new GlobalHistogramBinarizer(source);
|
||||
|
||||
if(maxWidth > 0 || maxHeight > 0)
|
||||
{
|
||||
ciw = new CameraImageWrapper();
|
||||
ciw->setSmoothTransformation(smoothTransformation);
|
||||
ciw->setImage(image, maxWidth, maxHeight);
|
||||
}
|
||||
else
|
||||
ciw = new CameraImageWrapper(image);
|
||||
Ref<BinaryBitmap> binary(new BinaryBitmap(binarizer));
|
||||
|
||||
Ref<LuminanceSource> imageRef(ciw);
|
||||
GlobalHistogramBinarizer* binz = new GlobalHistogramBinarizer(imageRef);
|
||||
DecodeHints hints((int)supportedFormats);
|
||||
|
||||
Ref<Binarizer> bz (binz);
|
||||
BinaryBitmap* bb = new BinaryBitmap(bz);
|
||||
result = ((MultiFormatReader*)decoder)->decode(binary, hints);
|
||||
|
||||
Ref<BinaryBitmap> ref(bb);
|
||||
|
||||
res = ((MultiFormatReader*)decoder)->decode(ref, DecodeHints((int)enabledDecoders));
|
||||
|
||||
QString string = QString(res->getText()->getText().c_str());
|
||||
processingTime = t.elapsed();
|
||||
QString string = QString(result->getText()->getText().c_str());
|
||||
emit tagFound(string);
|
||||
emit decodingFinished(true);
|
||||
return string;
|
||||
}
|
||||
catch(zxing::Exception& e)
|
||||
{
|
||||
qDebug() << "[decodeImage()] Exception:" << e.what();
|
||||
emit decodingFinished(false);
|
||||
processingTime = -1;
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
QString QZXing::decodeImageFromFile(QString imageFilePath, int maxWidth, int maxHeight, bool smoothTransformation)
|
||||
QVariantHash QZXing::decodeImageEx(QImage 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.
|
||||
return decodeImage(QImage(imageFilePath), maxWidth, maxHeight, smoothTransformation);
|
||||
QVariantHash resultMap;
|
||||
Ref<Result> result;
|
||||
emit decodingStarted();
|
||||
|
||||
try {
|
||||
Ref<LuminanceSource> source(new CameraImageWrapper(image));
|
||||
|
||||
Ref<Binarizer> binarizer;
|
||||
binarizer = new GlobalHistogramBinarizer(source);
|
||||
|
||||
Ref<BinaryBitmap> binary(new BinaryBitmap(binarizer));
|
||||
|
||||
DecodeHints hints((int)supportedFormats);
|
||||
|
||||
result = ((MultiFormatReader*)decoder)->decode(binary, hints);
|
||||
|
||||
QString string = QString(result->getText()->getText().c_str());
|
||||
QList<QVariant> points;
|
||||
emit tagFound(string);
|
||||
emit decodingFinished(true);
|
||||
resultMap.insert("content", string);
|
||||
|
||||
std::vector<Ref<ResultPoint> > resultPoints = result->getResultPoints();
|
||||
for (unsigned int i = 0; i < resultPoints.size(); i++) {
|
||||
points.append(QPoint(resultPoints[i]->getX(), resultPoints[i]->getY()));
|
||||
}
|
||||
resultMap.insert("points", points);
|
||||
}
|
||||
catch(zxing::Exception& e)
|
||||
{
|
||||
qDebug() << "[decodeImage()] Exception:" << e.what();
|
||||
emit decodingFinished(false);
|
||||
resultMap.insert("content", QString(""));
|
||||
resultMap.insert("points", QList<QVariant>());
|
||||
}
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
QString QZXing::decodeImageQML(QObject *item)
|
||||
QString QZXing::decodeImageFromFile(QString imageFilePath)
|
||||
{
|
||||
return decodeSubImageQML(item);
|
||||
//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.
|
||||
return decodeImage(QImage(imageFilePath));
|
||||
}
|
||||
|
||||
QString QZXing::decodeSubImageQML(QObject* item,
|
||||
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)
|
||||
{
|
||||
if(item == NULL)
|
||||
{
|
||||
|
||||
QString imagePath = imageUrl.path();
|
||||
imagePath = imagePath.trimmed();
|
||||
QFile file(imagePath);
|
||||
|
||||
if (!file.exists()) {
|
||||
qDebug() << "[decodeSubImageQML()] The file" << file.fileName() << "does not exist.";
|
||||
emit decodingFinished(false);
|
||||
return "";
|
||||
}
|
||||
|
||||
QImage img = ((ImageHandler*)imageHandler)->extractQImage(item, offsetX, offsetY, width, height);
|
||||
QImage img(imageUrl.path());
|
||||
|
||||
if(!(offsetX == 0 && offsetY == 0 && width == 0 && height == 0)) {
|
||||
img = img.copy(offsetX, offsetY, width, height);
|
||||
}
|
||||
|
||||
return decodeImage(img);
|
||||
|
||||
}
|
||||
|
||||
int QZXing::getProcessTimeOfLastDecoding()
|
||||
{
|
||||
return processingTime;
|
||||
}
|
||||
|
||||
uint QZXing::getEnabledFormats() const
|
||||
{
|
||||
return enabledDecoders;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
#ifndef QZXING_H
|
||||
#define QZXING_H
|
||||
|
||||
#include "QZXing_global.h"
|
||||
#include "qzxing_global.h"
|
||||
#include <QObject>
|
||||
#include <QImage>
|
||||
#include <QtQuick> // Use QTQuick instead of QTDeclarative in QT5
|
||||
#include <QVariantHash>
|
||||
#include <QtQuick>
|
||||
|
||||
/**
|
||||
* A class containing a very very small subset of the ZXing library.
|
||||
|
@ -15,120 +16,78 @@
|
|||
*
|
||||
* Regarding DecoderFormat, by default all of those are enabled (except DataMatrix will is still not supported)
|
||||
*/
|
||||
class
|
||||
#ifndef DISABLE_LIBRARY_FEATURES
|
||||
QZXINGSHARED_EXPORT
|
||||
#endif
|
||||
QZXing : public QObject{
|
||||
|
||||
class QZXing : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_ENUMS(DecoderFormat)
|
||||
Q_PROPERTY(int processingTime READ getProcessTimeOfLastDecoding)
|
||||
Q_PROPERTY(uint enabledDecoders READ getEnabledFormats WRITE setDecoder NOTIFY enabledFormatsChanged)
|
||||
|
||||
public:
|
||||
/*
|
||||
*
|
||||
*/
|
||||
enum DecoderFormat {
|
||||
DecoderFormat_None = 0,
|
||||
DecoderFormat_Aztec = 1 << 1,
|
||||
DecoderFormat_CODABAR = 1 << 2,
|
||||
DecoderFormat_CODE_39 = 1 << 3,
|
||||
DecoderFormat_CODE_93 = 1 << 4,
|
||||
DecoderFormat_CODE_128 = 1 << 5,
|
||||
DecoderFormat_DATA_MATRIX = 1 << 6,
|
||||
DecoderFormat_EAN_8 = 1 << 7,
|
||||
DecoderFormat_EAN_13 = 1 << 8,
|
||||
DecoderFormat_ITF = 1 << 9,
|
||||
DecoderFormat_MAXICODE = 1 << 10,
|
||||
DecoderFormat_PDF_417 = 1 << 11,
|
||||
DecoderFormat_QR_CODE = 1 << 12,
|
||||
DecoderFormat_RSS_14 = 1 << 13,
|
||||
DecoderFormat_RSS_EXPANDED = 1 << 14,
|
||||
DecoderFormat_UPC_A = 1 << 15,
|
||||
DecoderFormat_UPC_E = 1 << 16,
|
||||
DecoderFormat_UPC_EAN_EXTENSION = 1 << 17
|
||||
} ;
|
||||
DecoderFormat_None = 0,
|
||||
DecoderFormat_QR_CODE = 1,
|
||||
DecoderFormat_DATA_MATRIX = 2,
|
||||
DecoderFormat_UPC_E = 4,
|
||||
DecoderFormat_UPC_A = 8,
|
||||
DecoderFormat_EAN_8 = 16,
|
||||
DecoderFormat_EAN_13 = 32,
|
||||
DecoderFormat_CODE_128 = 64,
|
||||
DecoderFormat_CODE_39 = 128,
|
||||
DecoderFormat_ITF = 256,
|
||||
DecoderFormat_Aztec = 512
|
||||
} ;
|
||||
typedef unsigned int DecoderFormatType;
|
||||
|
||||
public:
|
||||
QZXing(QObject *parent = NULL);
|
||||
virtual ~QZXing();
|
||||
|
||||
QZXing(DecoderFormat decodeHints, QObject *parent = NULL);
|
||||
|
||||
#if QT_VERSION >= 0x040700
|
||||
static void registerQMLTypes()
|
||||
{
|
||||
qmlRegisterType<QZXing>("harbour.sailotp.QZXing", 2, 2, "QZXing");
|
||||
}
|
||||
#endif
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* The decoding function. Will try to decode the given image based on the enabled decoders.
|
||||
* If the image width is larger than maxWidth or image height is larger
|
||||
* than maxHeight then the image will be scaled down. Either way, in case of scaling, the aspect
|
||||
* ratio of the image will be kept.
|
||||
*
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* 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(QString imageFilePath, int maxWidth=-1, int maxHeight=-1, bool smoothTransformation = false);
|
||||
|
||||
/**
|
||||
* The decoding function accessible from QML
|
||||
*/
|
||||
QString decodeImageQML(QObject *item);
|
||||
|
||||
/**
|
||||
* The decoding function accessible from QML. Able to set the decoding
|
||||
* of a portion of the image.
|
||||
*/
|
||||
QString decodeSubImageQML(QObject* item,
|
||||
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.
|
||||
* Decoding operation fails, the processing time equals to -1.
|
||||
*/
|
||||
int getProcessTimeOfLastDecoding();
|
||||
|
||||
/**
|
||||
* Get the decoders that are enabled at the moment.
|
||||
* Returns a uint which is a bitwise OR of DecoderFormat enumeration values.
|
||||
*/
|
||||
uint getEnabledFormats() const;
|
||||
/**
|
||||
* Set the enabled decoders.
|
||||
* 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(DecoderFormatType hint);
|
||||
|
||||
#if QT_VERSION >= 0x040700
|
||||
static void registerQMLTypes()
|
||||
{
|
||||
qmlRegisterType<QZXing>("harbour.sailotp.QZXing", 2, 2, "QZXing");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* The decoding function. Will try to decode the given image based on the enabled decoders.
|
||||
*
|
||||
*/
|
||||
QString decodeImage(QImage image);
|
||||
QVariantHash decodeImageEx(QImage image);
|
||||
|
||||
/**
|
||||
* The decoding function accessible from QML
|
||||
*/
|
||||
QString decodeImageQML(const QUrl &imageUrl);
|
||||
|
||||
|
||||
QString decodeImageFromFile(QString imageFilePath);
|
||||
|
||||
/**
|
||||
* The decoding function accessible from QML. Able to set the decoding
|
||||
* of a portion of the image.
|
||||
*/
|
||||
QString decodeSubImageQML(const QUrl &imageUrl,
|
||||
const double offsetX = 0 , const double offsetY = 0,
|
||||
const double width = 0, const double height = 0);
|
||||
|
||||
signals:
|
||||
void decodingStarted();
|
||||
void decodingFinished(bool succeeded);
|
||||
void tagFound(QString tag);
|
||||
void enabledFormatsChanged();
|
||||
|
||||
private:
|
||||
void* decoder;
|
||||
DecoderFormatType enabledDecoders;
|
||||
QObject* imageHandler;
|
||||
int processingTime;
|
||||
|
||||
/**
|
||||
* If true, the decoding operation will take place at a different thread.
|
||||
*/
|
||||
bool isThreaded;
|
||||
DecoderFormatType supportedFormats;
|
||||
};
|
||||
|
||||
#endif // QZXING_H
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
#ifndef QZXING_GLOBAL_H
|
||||
#define QZXING_GLOBAL_H
|
||||
|
||||
#include <QtCore>
|
||||
#include <qglobal.h>
|
||||
#include <QtCore/QtGlobal>
|
||||
|
||||
#if defined(QZXING_LIBRARY)
|
||||
# define QZXINGSHARED_EXPORT Q_DECL_EXPORT
|
|
@ -18,23 +18,20 @@
|
|||
|
||||
#include <zxing/BarcodeFormat.h>
|
||||
|
||||
const char* zxing::BarcodeFormat::barcodeFormatNames[] = {
|
||||
0,
|
||||
"AZTEC",
|
||||
"CODABAR",
|
||||
"CODE_39",
|
||||
"CODE_93",
|
||||
"CODE_128",
|
||||
"DATA_MATRIX",
|
||||
"EAN_8",
|
||||
"EAN_13",
|
||||
"ITF",
|
||||
"MAXICODE",
|
||||
"PDF_417",
|
||||
"QR_CODE",
|
||||
"RSS_14",
|
||||
"RSS_EXPANDED",
|
||||
"UPC_A",
|
||||
"UPC_E",
|
||||
"UPC_EAN_EXTENSION"
|
||||
namespace zxing {
|
||||
|
||||
const char *barcodeFormatNames[] = {
|
||||
"None",
|
||||
"QR_CODE",
|
||||
"DATA_MATRIX",
|
||||
"UPC_E",
|
||||
"UPC_A",
|
||||
"EAN_8",
|
||||
"EAN_13",
|
||||
"CODE_128",
|
||||
"CODE_39",
|
||||
"ITF",
|
||||
"AZTEC"
|
||||
};
|
||||
|
||||
}
|
|
@ -23,38 +23,22 @@
|
|||
|
||||
namespace zxing {
|
||||
|
||||
class BarcodeFormat {
|
||||
public:
|
||||
// if you update the enum, update BarcodeFormat.cpp
|
||||
|
||||
enum Value {
|
||||
NONE,
|
||||
AZTEC,
|
||||
CODABAR,
|
||||
CODE_39,
|
||||
CODE_93,
|
||||
CODE_128,
|
||||
DATA_MATRIX,
|
||||
EAN_8,
|
||||
EAN_13,
|
||||
ITF,
|
||||
MAXICODE,
|
||||
PDF_417,
|
||||
QR_CODE,
|
||||
RSS_14,
|
||||
RSS_EXPANDED,
|
||||
UPC_A,
|
||||
UPC_E,
|
||||
UPC_EAN_EXTENSION
|
||||
};
|
||||
|
||||
BarcodeFormat(Value v) : value(v) {}
|
||||
const Value value;
|
||||
operator Value () const {return value;}
|
||||
|
||||
static char const* barcodeFormatNames[];
|
||||
};
|
||||
typedef enum BarcodeFormat {
|
||||
BarcodeFormat_None = 0,
|
||||
BarcodeFormat_QR_CODE,
|
||||
BarcodeFormat_DATA_MATRIX,
|
||||
BarcodeFormat_UPC_E,
|
||||
BarcodeFormat_UPC_A,
|
||||
BarcodeFormat_EAN_8,
|
||||
BarcodeFormat_EAN_13,
|
||||
BarcodeFormat_CODE_128,
|
||||
BarcodeFormat_CODE_39,
|
||||
BarcodeFormat_ITF,
|
||||
BarcodeFormat_AZTEC
|
||||
} BarcodeFormat;
|
||||
|
||||
/* if you update the enum, please update the name in BarcodeFormat.cpp */
|
||||
extern const char *barcodeFormatNames[];
|
||||
}
|
||||
|
||||
#endif // __BARCODE_FORMAT_H__
|
|
@ -34,12 +34,4 @@ namespace zxing {
|
|||
return source_;
|
||||
}
|
||||
|
||||
int Binarizer::getWidth() const {
|
||||
return source_->getWidth();
|
||||
}
|
||||
|
||||
int Binarizer::getHeight() const {
|
||||
return source_->getHeight();
|
||||
}
|
||||
|
||||
}
|
|
@ -40,10 +40,6 @@ class Binarizer : public Counted {
|
|||
|
||||
Ref<LuminanceSource> getLuminanceSource() const ;
|
||||
virtual Ref<Binarizer> createBinarizer(Ref<LuminanceSource> source) = 0;
|
||||
|
||||
int getWidth() const;
|
||||
int getHeight() const;
|
||||
|
||||
};
|
||||
|
||||
}
|
67
src/qzxing/zxing/BinaryBitmap.cpp
Normal file
67
src/qzxing/zxing/BinaryBitmap.cpp
Normal file
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* BinaryBitmap.cpp
|
||||
* zxing
|
||||
*
|
||||
* Copyright 2010 ZXing authors All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <zxing/BinaryBitmap.h>
|
||||
|
||||
namespace zxing {
|
||||
|
||||
BinaryBitmap::BinaryBitmap(Ref<Binarizer> binarizer) : binarizer_(binarizer) {
|
||||
|
||||
}
|
||||
|
||||
BinaryBitmap::~BinaryBitmap() {
|
||||
}
|
||||
|
||||
Ref<BitArray> BinaryBitmap::getBlackRow(int y, Ref<BitArray> row) {
|
||||
return binarizer_->getBlackRow(y, row);
|
||||
}
|
||||
|
||||
Ref<BitMatrix> BinaryBitmap::getBlackMatrix() {
|
||||
return binarizer_->getBlackMatrix();
|
||||
}
|
||||
|
||||
int BinaryBitmap::getWidth() const {
|
||||
return getLuminanceSource()->getWidth();
|
||||
}
|
||||
|
||||
int BinaryBitmap::getHeight() const {
|
||||
return getLuminanceSource()->getHeight();
|
||||
}
|
||||
|
||||
Ref<LuminanceSource> BinaryBitmap::getLuminanceSource() const {
|
||||
return binarizer_->getLuminanceSource();
|
||||
}
|
||||
|
||||
|
||||
bool BinaryBitmap::isCropSupported() const {
|
||||
return getLuminanceSource()->isCropSupported();
|
||||
}
|
||||
|
||||
Ref<BinaryBitmap> BinaryBitmap::crop(int left, int top, int width, int height) {
|
||||
return Ref<BinaryBitmap> (new BinaryBitmap(binarizer_->createBinarizer(getLuminanceSource()->crop(left, top, width, height))));
|
||||
}
|
||||
|
||||
bool BinaryBitmap::isRotateSupported() const {
|
||||
return getLuminanceSource()->isRotateSupported();
|
||||
}
|
||||
|
||||
Ref<BinaryBitmap> BinaryBitmap::rotateCounterClockwise() {
|
||||
return Ref<BinaryBitmap> (new BinaryBitmap(binarizer_->createBinarizer(getLuminanceSource()->rotateCounterClockwise())));
|
||||
}
|
||||
}
|
|
@ -30,6 +30,7 @@ namespace zxing {
|
|||
class BinaryBitmap : public Counted {
|
||||
private:
|
||||
Ref<Binarizer> binarizer_;
|
||||
int cached_y_;
|
||||
|
||||
public:
|
||||
BinaryBitmap(Ref<Binarizer> binarizer);
|
120
src/qzxing/zxing/DecodeHints.cpp
Normal file
120
src/qzxing/zxing/DecodeHints.cpp
Normal file
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
* DecodeHintType.cpp
|
||||
* zxing
|
||||
*
|
||||
* Copyright 2010 ZXing authors All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <zxing/DecodeHints.h>
|
||||
#include <zxing/common/IllegalArgumentException.h>
|
||||
namespace zxing {
|
||||
|
||||
const DecodeHintType DecodeHints::CHARACTER_SET;
|
||||
|
||||
const DecodeHints DecodeHints::PRODUCT_HINT(
|
||||
BARCODEFORMAT_UPC_E_HINT |
|
||||
BARCODEFORMAT_UPC_A_HINT |
|
||||
BARCODEFORMAT_EAN_8_HINT |
|
||||
BARCODEFORMAT_EAN_13_HINT);
|
||||
|
||||
const DecodeHints DecodeHints::ONED_HINT(
|
||||
BARCODEFORMAT_UPC_E_HINT |
|
||||
BARCODEFORMAT_UPC_A_HINT |
|
||||
BARCODEFORMAT_EAN_8_HINT |
|
||||
BARCODEFORMAT_EAN_13_HINT |
|
||||
BARCODEFORMAT_CODE_128_HINT |
|
||||
BARCODEFORMAT_CODE_39_HINT |
|
||||
BARCODEFORMAT_ITF_HINT);
|
||||
|
||||
const DecodeHints DecodeHints::DEFAULT_HINT(
|
||||
BARCODEFORMAT_UPC_E_HINT |
|
||||
BARCODEFORMAT_UPC_A_HINT |
|
||||
BARCODEFORMAT_EAN_8_HINT |
|
||||
BARCODEFORMAT_EAN_13_HINT |
|
||||
BARCODEFORMAT_CODE_128_HINT |
|
||||
BARCODEFORMAT_CODE_39_HINT |
|
||||
BARCODEFORMAT_ITF_HINT |
|
||||
BARCODEFORMAT_DATA_MATRIX_HINT |
|
||||
BARCODEFORMAT_AZTEC_HINT |
|
||||
BARCODEFORMAT_QR_CODE_HINT);
|
||||
|
||||
DecodeHints::DecodeHints() {
|
||||
hints = 0;
|
||||
}
|
||||
|
||||
DecodeHints::DecodeHints(DecodeHintType init) {
|
||||
hints = init;
|
||||
}
|
||||
|
||||
void DecodeHints::addFormat(BarcodeFormat toadd) {
|
||||
switch (toadd) {
|
||||
case BarcodeFormat_AZTEC: hints |= BARCODEFORMAT_AZTEC_HINT; break;
|
||||
case BarcodeFormat_QR_CODE: hints |= BARCODEFORMAT_QR_CODE_HINT; break;
|
||||
case BarcodeFormat_DATA_MATRIX: hints |= BARCODEFORMAT_DATA_MATRIX_HINT; break;
|
||||
case BarcodeFormat_UPC_E: hints |= BARCODEFORMAT_UPC_E_HINT; break;
|
||||
case BarcodeFormat_UPC_A: hints |= BARCODEFORMAT_UPC_A_HINT; break;
|
||||
case BarcodeFormat_EAN_8: hints |= BARCODEFORMAT_EAN_8_HINT; break;
|
||||
case BarcodeFormat_EAN_13: hints |= BARCODEFORMAT_EAN_13_HINT; break;
|
||||
case BarcodeFormat_CODE_128: hints |= BARCODEFORMAT_CODE_128_HINT; break;
|
||||
case BarcodeFormat_CODE_39: hints |= BARCODEFORMAT_CODE_39_HINT; break;
|
||||
case BarcodeFormat_ITF: hints |= BARCODEFORMAT_ITF_HINT; break;
|
||||
default: throw IllegalArgumentException("Unrecognizd barcode format");
|
||||
}
|
||||
}
|
||||
|
||||
bool DecodeHints::containsFormat(BarcodeFormat tocheck) const {
|
||||
DecodeHintType checkAgainst;
|
||||
switch (tocheck) {
|
||||
case BarcodeFormat_AZTEC: checkAgainst = BARCODEFORMAT_AZTEC_HINT; break;
|
||||
case BarcodeFormat_QR_CODE: checkAgainst = BARCODEFORMAT_QR_CODE_HINT; break;
|
||||
case BarcodeFormat_DATA_MATRIX: checkAgainst = BARCODEFORMAT_DATA_MATRIX_HINT; break;
|
||||
case BarcodeFormat_UPC_E: checkAgainst = BARCODEFORMAT_UPC_E_HINT; break;
|
||||
case BarcodeFormat_UPC_A: checkAgainst = BARCODEFORMAT_UPC_A_HINT; break;
|
||||
case BarcodeFormat_EAN_8: checkAgainst = BARCODEFORMAT_EAN_8_HINT; break;
|
||||
case BarcodeFormat_EAN_13: checkAgainst = BARCODEFORMAT_EAN_13_HINT; break;
|
||||
case BarcodeFormat_CODE_128: checkAgainst = BARCODEFORMAT_CODE_128_HINT; break;
|
||||
case BarcodeFormat_CODE_39: checkAgainst = BARCODEFORMAT_CODE_39_HINT; break;
|
||||
case BarcodeFormat_ITF: checkAgainst = BARCODEFORMAT_ITF_HINT; break;
|
||||
default: throw IllegalArgumentException("Unrecognizd barcode format");
|
||||
}
|
||||
return (hints & checkAgainst);
|
||||
}
|
||||
|
||||
void DecodeHints::setTryHarder(bool toset) {
|
||||
if (toset) {
|
||||
hints |= TRYHARDER_HINT;
|
||||
} else {
|
||||
hints &= ~TRYHARDER_HINT;
|
||||
}
|
||||
}
|
||||
|
||||
bool DecodeHints::getTryHarder() const {
|
||||
return (hints & TRYHARDER_HINT);
|
||||
}
|
||||
|
||||
void DecodeHints::setResultPointCallback(Ref<ResultPointCallback> const& _callback) {
|
||||
callback = _callback;
|
||||
}
|
||||
|
||||
Ref<ResultPointCallback> DecodeHints::getResultPointCallback() const {
|
||||
return callback;
|
||||
}
|
||||
|
||||
DecodeHintType DecodeHints::getCurrentHint()
|
||||
{
|
||||
return hints;
|
||||
}
|
||||
|
||||
} /* namespace */
|
72
src/qzxing/zxing/DecodeHints.h
Normal file
72
src/qzxing/zxing/DecodeHints.h
Normal file
|
@ -0,0 +1,72 @@
|
|||
#ifndef __DECODEHINTS_H_
|
||||
#define __DECODEHINTS_H_
|
||||
/*
|
||||
* DecodeHintType.h
|
||||
* zxing
|
||||
*
|
||||
* Copyright 2010 ZXing authors All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <zxing/BarcodeFormat.h>
|
||||
#include <zxing/ResultPointCallback.h>
|
||||
|
||||
namespace zxing {
|
||||
|
||||
typedef unsigned int DecodeHintType;
|
||||
|
||||
class DecodeHints {
|
||||
|
||||
private:
|
||||
|
||||
DecodeHintType hints;
|
||||
|
||||
Ref<ResultPointCallback> callback;
|
||||
|
||||
public:
|
||||
|
||||
static const DecodeHintType BARCODEFORMAT_QR_CODE_HINT = 1 << BarcodeFormat_QR_CODE;
|
||||
static const DecodeHintType BARCODEFORMAT_DATA_MATRIX_HINT = 1 << BarcodeFormat_DATA_MATRIX;
|
||||
static const DecodeHintType BARCODEFORMAT_UPC_E_HINT = 1 << BarcodeFormat_UPC_E;
|
||||
static const DecodeHintType BARCODEFORMAT_UPC_A_HINT = 1 << BarcodeFormat_UPC_A;
|
||||
static const DecodeHintType BARCODEFORMAT_EAN_8_HINT = 1 << BarcodeFormat_EAN_8;
|
||||
static const DecodeHintType BARCODEFORMAT_EAN_13_HINT = 1 << BarcodeFormat_EAN_13;
|
||||
static const DecodeHintType BARCODEFORMAT_CODE_128_HINT = 1 << BarcodeFormat_CODE_128;
|
||||
static const DecodeHintType BARCODEFORMAT_CODE_39_HINT = 1 << BarcodeFormat_CODE_39;
|
||||
static const DecodeHintType BARCODEFORMAT_ITF_HINT = 1 << BarcodeFormat_ITF;
|
||||
static const DecodeHintType BARCODEFORMAT_AZTEC_HINT = 1 << BarcodeFormat_AZTEC;
|
||||
static const DecodeHintType CHARACTER_SET = 1 << 30;
|
||||
static const DecodeHintType TRYHARDER_HINT = 1 << 31;
|
||||
|
||||
static const DecodeHints PRODUCT_HINT;
|
||||
static const DecodeHints ONED_HINT;
|
||||
static const DecodeHints DEFAULT_HINT;
|
||||
|
||||
DecodeHints();
|
||||
DecodeHints(DecodeHintType init);
|
||||
|
||||
void addFormat(BarcodeFormat toadd);
|
||||
bool containsFormat(BarcodeFormat tocheck) const;
|
||||
void setTryHarder(bool toset);
|
||||
bool getTryHarder() const;
|
||||
|
||||
void setResultPointCallback(Ref<ResultPointCallback> const&);
|
||||
Ref<ResultPointCallback> getResultPointCallback() const;
|
||||
|
||||
DecodeHintType getCurrentHint();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -20,24 +20,21 @@
|
|||
|
||||
*/
|
||||
|
||||
#include <zxing/ZXing.h>
|
||||
#include <zxing/Exception.h>
|
||||
#include <string.h>
|
||||
|
||||
using zxing::Exception;
|
||||
namespace zxing {
|
||||
|
||||
void Exception::deleteMessage() {
|
||||
delete [] message;
|
||||
Exception::Exception() {}
|
||||
|
||||
Exception::Exception(const char *msg) :
|
||||
message(msg) {
|
||||
}
|
||||
|
||||
const char* Exception::what() const throw() {
|
||||
return message.c_str();
|
||||
}
|
||||
|
||||
Exception::~Exception() throw() {
|
||||
}
|
||||
|
||||
char const* Exception::copy(char const* msg) {
|
||||
char* message = 0;
|
||||
if (msg) {
|
||||
int l = strlen(msg)+1;
|
||||
if (l) {
|
||||
message = new char[l];
|
||||
strcpy(message, msg);
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
|
@ -1,4 +1,3 @@
|
|||
// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
|
||||
#ifndef __EXCEPTION_H__
|
||||
#define __EXCEPTION_H__
|
||||
|
||||
|
@ -28,24 +27,14 @@ namespace zxing {
|
|||
|
||||
class Exception : public std::exception {
|
||||
private:
|
||||
char const* const message;
|
||||
std::string message;
|
||||
|
||||
public:
|
||||
Exception() throw() : message(0) {}
|
||||
Exception(const char* msg) throw() : message(copy(msg)) {}
|
||||
Exception(Exception const& that) throw() : std::exception(that), message(copy(that.message)) {}
|
||||
~Exception() throw() {
|
||||
if(message) {
|
||||
deleteMessage();
|
||||
}
|
||||
}
|
||||
char const* what() const throw() {return message ? message : "";}
|
||||
|
||||
private:
|
||||
static char const* copy(char const*);
|
||||
void deleteMessage();
|
||||
Exception();
|
||||
Exception(const char *msg);
|
||||
virtual const char* what() const throw();
|
||||
virtual ~Exception() throw();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // __EXCEPTION_H__
|
|
@ -32,10 +32,4 @@ FormatException::FormatException(const char *msg) :
|
|||
FormatException::~FormatException() throw() {
|
||||
}
|
||||
|
||||
FormatException const&
|
||||
FormatException::getFormatInstance() {
|
||||
static FormatException instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
}
|
|
@ -29,8 +29,6 @@ public:
|
|||
FormatException();
|
||||
FormatException(const char *msg);
|
||||
~FormatException() throw();
|
||||
|
||||
static FormatException const& getFormatInstance();
|
||||
};
|
||||
|
||||
}
|
|
@ -20,21 +20,25 @@
|
|||
|
||||
#include <sstream>
|
||||
#include <zxing/LuminanceSource.h>
|
||||
#include <zxing/InvertedLuminanceSource.h>
|
||||
#include <zxing/common/IllegalArgumentException.h>
|
||||
|
||||
using zxing::Ref;
|
||||
using zxing::LuminanceSource;
|
||||
namespace zxing {
|
||||
|
||||
LuminanceSource::LuminanceSource(int width_, int height_) :width(width_), height(height_) {}
|
||||
LuminanceSource::LuminanceSource() {
|
||||
}
|
||||
|
||||
LuminanceSource::~LuminanceSource() {}
|
||||
LuminanceSource::~LuminanceSource() {
|
||||
}
|
||||
|
||||
bool LuminanceSource::isCropSupported() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
Ref<LuminanceSource> LuminanceSource::crop(int, int, int, int) const {
|
||||
Ref<LuminanceSource> LuminanceSource::crop(int left, int top, int width, int height) {
|
||||
(void)left;
|
||||
(void)top;
|
||||
(void)width;
|
||||
(void)height;
|
||||
throw IllegalArgumentException("This luminance source does not support cropping.");
|
||||
}
|
||||
|
||||
|
@ -42,12 +46,12 @@ bool LuminanceSource::isRotateSupported() const {
|
|||
return false;
|
||||
}
|
||||
|
||||
Ref<LuminanceSource> LuminanceSource::rotateCounterClockwise() const {
|
||||
Ref<LuminanceSource> LuminanceSource::rotateCounterClockwise() {
|
||||
throw IllegalArgumentException("This luminance source does not support rotation.");
|
||||
}
|
||||
|
||||
LuminanceSource::operator std::string() const {
|
||||
ArrayRef<char> row;
|
||||
LuminanceSource::operator std::string() {
|
||||
unsigned char* row = 0;
|
||||
std::ostringstream oss;
|
||||
for (int y = 0; y < getHeight(); y++) {
|
||||
row = getRow(y, row);
|
||||
|
@ -67,20 +71,10 @@ LuminanceSource::operator std::string() const {
|
|||
}
|
||||
oss << '\n';
|
||||
}
|
||||
delete [] row;
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
Ref<LuminanceSource> LuminanceSource::invert() const {
|
||||
|
||||
// N.B.: this only works because we use counted objects with the
|
||||
// count in the object. This is _not_ how things like shared_ptr
|
||||
// work. They do not allow you to make a smart pointer from a native
|
||||
// pointer more than once. If we ever switch to (something like)
|
||||
// shared_ptr's, the luminace source is going to have keep a weak
|
||||
// pointer to itself from which it can create a strong pointer as
|
||||
// needed. And, FWIW, that has nasty semantics in the face of
|
||||
// exceptions during construction.
|
||||
|
||||
return Ref<LuminanceSource>
|
||||
(new InvertedLuminanceSource(Ref<LuminanceSource>(const_cast<LuminanceSource*>(this))));
|
||||
}
|
|
@ -21,37 +21,30 @@
|
|||
*/
|
||||
|
||||
#include <zxing/common/Counted.h>
|
||||
#include <zxing/common/Array.h>
|
||||
#include <string.h>
|
||||
|
||||
namespace zxing {
|
||||
|
||||
class LuminanceSource : public Counted {
|
||||
protected:
|
||||
int width;
|
||||
int height;
|
||||
|
||||
public:
|
||||
LuminanceSource(int width, int height);
|
||||
public:
|
||||
LuminanceSource();
|
||||
virtual ~LuminanceSource();
|
||||
|
||||
int getWidth() const { return width; }
|
||||
int getHeight() const { return height; }
|
||||
virtual int getWidth() const = 0;
|
||||
virtual int getHeight() const = 0;
|
||||
|
||||
// Callers take ownership of the returned memory and must call delete [] on it themselves.
|
||||
virtual ArrayRef<char> getRow(int y, ArrayRef<char> row) const = 0;
|
||||
virtual ArrayRef<char> getMatrix() const = 0;
|
||||
virtual unsigned char* getRow(int y, unsigned char* row) = 0;
|
||||
virtual unsigned char* getMatrix() = 0;
|
||||
|
||||
virtual bool isCropSupported() const;
|
||||
virtual Ref<LuminanceSource> crop(int left, int top, int width, int height) const;
|
||||
virtual Ref<LuminanceSource> crop(int left, int top, int width, int height);
|
||||
|
||||
virtual bool isRotateSupported() const;
|
||||
virtual Ref<LuminanceSource> rotateCounterClockwise();
|
||||
|
||||
virtual Ref<LuminanceSource> invert() const;
|
||||
|
||||
virtual Ref<LuminanceSource> rotateCounterClockwise() const;
|
||||
|
||||
operator std::string () const;
|
||||
operator std::string (); // should be const but don't want to make sure a
|
||||
// large breaking change right now
|
||||
};
|
||||
|
||||
}
|
106
src/qzxing/zxing/MultiFormatReader.cpp
Normal file
106
src/qzxing/zxing/MultiFormatReader.cpp
Normal file
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* MultiFormatBarcodeReader.cpp
|
||||
* ZXing
|
||||
*
|
||||
* Created by Lukasz Warchol on 10-01-26.
|
||||
* Modified by Luiz Silva on 09/02/2010.
|
||||
* Copyright 2010 ZXing authors All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <zxing/MultiFormatReader.h>
|
||||
#include <zxing/qrcode/QRCodeReader.h>
|
||||
#include <zxing/datamatrix/DataMatrixReader.h>
|
||||
#include <zxing/aztec/AztecReader.h>
|
||||
#include <zxing/oned/MultiFormatUPCEANReader.h>
|
||||
#include <zxing/oned/MultiFormatOneDReader.h>
|
||||
#include <zxing/ReaderException.h>
|
||||
|
||||
namespace zxing {
|
||||
MultiFormatReader::MultiFormatReader() {
|
||||
|
||||
}
|
||||
|
||||
Ref<Result> MultiFormatReader::decode(Ref<BinaryBitmap> image) {
|
||||
setHints(DecodeHints::DEFAULT_HINT);
|
||||
return decodeInternal(image);
|
||||
}
|
||||
|
||||
Ref<Result> MultiFormatReader::decode(Ref<BinaryBitmap> image, DecodeHints hints) {
|
||||
setHints(hints);
|
||||
return decodeInternal(image);
|
||||
}
|
||||
|
||||
Ref<Result> MultiFormatReader::decodeWithState(Ref<BinaryBitmap> image) {
|
||||
// Make sure to set up the default state so we don't crash
|
||||
if (readers_.size() == 0) {
|
||||
setHints(DecodeHints::DEFAULT_HINT);
|
||||
}
|
||||
return decodeInternal(image);
|
||||
}
|
||||
|
||||
void MultiFormatReader::setHints(DecodeHints hints) {
|
||||
hints_ = hints;
|
||||
readers_.clear();
|
||||
bool tryHarder = hints.getTryHarder();
|
||||
|
||||
bool addOneDReader = hints.containsFormat(BarcodeFormat_UPC_E) ||
|
||||
hints.containsFormat(BarcodeFormat_UPC_A) ||
|
||||
hints.containsFormat(BarcodeFormat_EAN_8) ||
|
||||
hints.containsFormat(BarcodeFormat_EAN_13) ||
|
||||
hints.containsFormat(BarcodeFormat_CODE_128) ||
|
||||
hints.containsFormat(BarcodeFormat_CODE_39) ||
|
||||
hints.containsFormat(BarcodeFormat_ITF);
|
||||
if (addOneDReader && !tryHarder) {
|
||||
readers_.push_back(Ref<Reader>(new zxing::oned::MultiFormatOneDReader(hints)));
|
||||
}
|
||||
if (hints.containsFormat(BarcodeFormat_QR_CODE)) {
|
||||
readers_.push_back(Ref<Reader>(new zxing::qrcode::QRCodeReader()));
|
||||
}
|
||||
if (hints.containsFormat(BarcodeFormat_DATA_MATRIX)) {
|
||||
readers_.push_back(Ref<Reader>(new zxing::datamatrix::DataMatrixReader()));
|
||||
}
|
||||
if (hints.containsFormat(BarcodeFormat_AZTEC)) {
|
||||
readers_.push_back(Ref<Reader>(new zxing::aztec::AztecReader()));
|
||||
}
|
||||
//TODO: add PDF417 here once PDF417 reader is implemented
|
||||
if (addOneDReader && tryHarder) {
|
||||
readers_.push_back(Ref<Reader>(new zxing::oned::MultiFormatOneDReader(hints)));
|
||||
}
|
||||
if (readers_.size() == 0) {
|
||||
if (!tryHarder) {
|
||||
readers_.push_back(Ref<Reader>(new zxing::oned::MultiFormatOneDReader(hints)));
|
||||
}
|
||||
readers_.push_back(Ref<Reader>(new zxing::qrcode::QRCodeReader()));
|
||||
if (tryHarder) {
|
||||
readers_.push_back(Ref<Reader>(new zxing::oned::MultiFormatOneDReader(hints)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ref<Result> MultiFormatReader::decodeInternal(Ref<BinaryBitmap> image) {
|
||||
for (unsigned int i = 0; i < readers_.size(); i++) {
|
||||
try {
|
||||
return readers_[i]->decode(image, hints_);
|
||||
} catch (ReaderException const& re) {
|
||||
// continue
|
||||
}
|
||||
}
|
||||
throw ReaderException("No code detected");
|
||||
}
|
||||
|
||||
MultiFormatReader::~MultiFormatReader() {
|
||||
|
||||
}
|
||||
}
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
namespace zxing {
|
||||
class MultiFormatReader : public Reader {
|
||||
|
||||
private:
|
||||
Ref<Result> decodeInternal(Ref<BinaryBitmap> image);
|
||||
|
|
@ -1,8 +1,4 @@
|
|||
// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
|
||||
|
||||
#ifndef __CHECKSUM_EXCEPTION_H__
|
||||
#define __NOT_FOUND_EXCEPTION_H__
|
||||
|
||||
/*
|
||||
* Copyright 20011 ZXing authors
|
||||
*
|
||||
|
@ -19,16 +15,14 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <zxing/ReaderException.h>
|
||||
#include <zxing/NotFoundException.h>
|
||||
|
||||
namespace zxing {
|
||||
class ChecksumException : public ReaderException {
|
||||
typedef ReaderException Base;
|
||||
public:
|
||||
ChecksumException() throw();
|
||||
ChecksumException(const char *msg) throw();
|
||||
~ChecksumException() throw();
|
||||
};
|
||||
}
|
||||
|
||||
#endif // __CHECKSUM_EXCEPTION_H__
|
||||
NotFoundException::NotFoundException(const char *msg)
|
||||
: ReaderException(msg) {}
|
||||
|
||||
NotFoundException::~NotFoundException() throw() {
|
||||
}
|
||||
|
||||
}
|
|
@ -23,13 +23,11 @@
|
|||
|
||||
namespace zxing {
|
||||
|
||||
class NotFoundException : public ReaderException {
|
||||
public:
|
||||
NotFoundException() throw() {}
|
||||
NotFoundException(const char *msg) throw() : ReaderException(msg) {}
|
||||
~NotFoundException() throw() {}
|
||||
};
|
||||
class NotFoundException : public ReaderException {
|
||||
public:
|
||||
NotFoundException(const char *msg);
|
||||
~NotFoundException() throw();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // __NOT_FOUND_EXCEPTION_H__
|
|
@ -1,10 +1,10 @@
|
|||
// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
|
||||
/*
|
||||
* ChecksumException.cpp
|
||||
* ReaderException.cpp
|
||||
* zxing
|
||||
*
|
||||
* Created by Christian Brunschen on 13/05/2008.
|
||||
* Copyright 2008 ZXing authors All rights reserved.
|
||||
* Copyright 2008-2011 ZXing authors All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -19,10 +19,17 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <zxing/ChecksumException.h>
|
||||
#include <zxing/ReaderException.h>
|
||||
|
||||
using zxing::ChecksumException;
|
||||
namespace zxing {
|
||||
|
||||
ChecksumException::ChecksumException() throw() {}
|
||||
ChecksumException::ChecksumException(const char *msg) throw() : ReaderException(msg) {}
|
||||
ChecksumException::~ChecksumException() throw() {}
|
||||
ReaderException::ReaderException() {}
|
||||
|
||||
ReaderException::ReaderException(const char *msg) :
|
||||
Exception(msg) {
|
||||
}
|
||||
|
||||
ReaderException::~ReaderException() throw() {
|
||||
}
|
||||
|
||||
}
|
|
@ -1,4 +1,3 @@
|
|||
// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
|
||||
#ifndef __READER_EXCEPTION_H__
|
||||
#define __READER_EXCEPTION_H__
|
||||
|
||||
|
@ -26,12 +25,11 @@
|
|||
namespace zxing {
|
||||
|
||||
class ReaderException : public Exception {
|
||||
public:
|
||||
ReaderException() throw() {}
|
||||
ReaderException(char const* msg) throw() : Exception(msg) {}
|
||||
~ReaderException() throw() {}
|
||||
public:
|
||||
ReaderException();
|
||||
ReaderException(const char *msg);
|
||||
~ReaderException() throw();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // __READER_EXCEPTION_H__
|
|
@ -21,18 +21,10 @@
|
|||
|
||||
#include <zxing/Result.h>
|
||||
|
||||
using zxing::Result;
|
||||
using zxing::Ref;
|
||||
using zxing::ArrayRef;
|
||||
using zxing::String;
|
||||
using zxing::ResultPoint;
|
||||
namespace zxing {
|
||||
using namespace std;
|
||||
|
||||
// VC++
|
||||
using zxing::BarcodeFormat;
|
||||
|
||||
Result::Result(Ref<String> text,
|
||||
ArrayRef<char> rawBytes,
|
||||
ArrayRef< Ref<ResultPoint> > resultPoints,
|
||||
Result::Result(Ref<String> text, ArrayRef<unsigned char> rawBytes, std::vector<Ref<ResultPoint> > resultPoints,
|
||||
BarcodeFormat format) :
|
||||
text_(text), rawBytes_(rawBytes), resultPoints_(resultPoints), format_(format) {
|
||||
}
|
||||
|
@ -44,18 +36,29 @@ Ref<String> Result::getText() {
|
|||
return text_;
|
||||
}
|
||||
|
||||
ArrayRef<char> Result::getRawBytes() {
|
||||
ArrayRef<unsigned char> Result::getRawBytes() {
|
||||
return rawBytes_;
|
||||
}
|
||||
|
||||
ArrayRef< Ref<ResultPoint> > const& Result::getResultPoints() const {
|
||||
const std::vector<Ref<ResultPoint> >& Result::getResultPoints() const {
|
||||
return resultPoints_;
|
||||
}
|
||||
|
||||
ArrayRef< Ref<ResultPoint> >& Result::getResultPoints() {
|
||||
std::vector<Ref<ResultPoint> >& Result::getResultPoints() {
|
||||
return resultPoints_;
|
||||
}
|
||||
|
||||
zxing::BarcodeFormat Result::getBarcodeFormat() const {
|
||||
BarcodeFormat Result::getBarcodeFormat() const {
|
||||
return format_;
|
||||
}
|
||||
|
||||
ostream& operator<<(ostream &out, Result& result) {
|
||||
if (result.text_ != 0) {
|
||||
out << result.text_->getText();
|
||||
} else {
|
||||
out << "[" << result.rawBytes_->size() << " bytes]";
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
}
|
|
@ -21,6 +21,7 @@
|
|||
*/
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <zxing/common/Array.h>
|
||||
#include <zxing/common/Counted.h>
|
||||
#include <zxing/common/Str.h>
|
||||
|
@ -32,20 +33,18 @@ namespace zxing {
|
|||
class Result : public Counted {
|
||||
private:
|
||||
Ref<String> text_;
|
||||
ArrayRef<char> rawBytes_;
|
||||
ArrayRef< Ref<ResultPoint> > resultPoints_;
|
||||
ArrayRef<unsigned char> rawBytes_;
|
||||
std::vector<Ref<ResultPoint> > resultPoints_;
|
||||
BarcodeFormat format_;
|
||||
|
||||
public:
|
||||
Result(Ref<String> text,
|
||||
ArrayRef<char> rawBytes,
|
||||
ArrayRef< Ref<ResultPoint> > resultPoints,
|
||||
Result(Ref<String> text, ArrayRef<unsigned char> rawBytes, std::vector<Ref<ResultPoint> > resultPoints,
|
||||
BarcodeFormat format);
|
||||
~Result();
|
||||
Ref<String> getText();
|
||||
ArrayRef<char> getRawBytes();
|
||||
ArrayRef< Ref<ResultPoint> > const& getResultPoints() const;
|
||||
ArrayRef< Ref<ResultPoint> >& getResultPoints();
|
||||
ArrayRef<unsigned char> getRawBytes();
|
||||
const std::vector<Ref<ResultPoint> >& getResultPoints() const;
|
||||
std::vector<Ref<ResultPoint> >& getResultPoints();
|
||||
BarcodeFormat getBarcodeFormat() const;
|
||||
|
||||
friend std::ostream& operator<<(std::ostream &out, Result& result);
|
|
@ -1,4 +1,3 @@
|
|||
// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
|
||||
/*
|
||||
* ResultPoint.cpp
|
||||
* zxing
|
||||
|
@ -20,9 +19,7 @@
|
|||
*/
|
||||
|
||||
#include <zxing/ResultPoint.h>
|
||||
#include <zxing/common/detector/MathUtils.h>
|
||||
|
||||
using zxing::common::detector::MathUtils;
|
||||
#include <math.h>
|
||||
|
||||
namespace zxing {
|
||||
|
||||
|
@ -30,8 +27,6 @@ ResultPoint::ResultPoint() : posX_(0), posY_(0) {}
|
|||
|
||||
ResultPoint::ResultPoint(float x, float y) : posX_(x), posY_(y) {}
|
||||
|
||||
ResultPoint::ResultPoint(int x, int y) : posX_(float(x)), posY_(float(y)) {}
|
||||
|
||||
ResultPoint::~ResultPoint() {}
|
||||
|
||||
float ResultPoint::getX() const {
|
||||
|
@ -87,11 +82,8 @@ void ResultPoint::orderBestPatterns(std::vector<Ref<ResultPoint> > &patterns) {
|
|||
patterns[2] = pointC;
|
||||
}
|
||||
|
||||
float ResultPoint::distance(Ref<ResultPoint> pattern1, Ref<ResultPoint> pattern2) {
|
||||
return MathUtils::distance(pattern1->posX_,
|
||||
pattern1->posY_,
|
||||
pattern2->posX_,
|
||||
pattern2->posY_);
|
||||
float ResultPoint::distance(Ref<ResultPoint> point1, Ref<ResultPoint> point2) {
|
||||
return distance(point1->getX(), point1->getY(), point2->getX(), point2->getY());
|
||||
}
|
||||
|
||||
float ResultPoint::distance(float x1, float x2, float y1, float y2) {
|
|
@ -28,13 +28,12 @@ namespace zxing {
|
|||
|
||||
class ResultPoint : public Counted {
|
||||
protected:
|
||||
const float posX_;
|
||||
const float posY_;
|
||||
float posX_;
|
||||
float posY_;
|
||||
|
||||
public:
|
||||
ResultPoint();
|
||||
ResultPoint(float x, float y);
|
||||
ResultPoint(int x, int y);
|
||||
virtual ~ResultPoint();
|
||||
|
||||
virtual float getX() const;
|
|
@ -21,34 +21,25 @@
|
|||
|
||||
#include <zxing/aztec/AztecDetectorResult.h>
|
||||
|
||||
using zxing::aztec::AztecDetectorResult;
|
||||
namespace zxing {
|
||||
namespace aztec {
|
||||
AztecDetectorResult::AztecDetectorResult(Ref<BitMatrix> bits, std::vector<Ref<ResultPoint> > points, bool compact, int nbDatablocks, int nbLayers)
|
||||
: DetectorResult(bits, points),
|
||||
compact_(compact),
|
||||
nbDatablocks_(nbDatablocks),
|
||||
nbLayers_(nbLayers) {
|
||||
}
|
||||
|
||||
// VC++
|
||||
using zxing::Ref;
|
||||
using zxing::ArrayRef;
|
||||
using zxing::BitMatrix;
|
||||
using zxing::ResultPoint;
|
||||
bool AztecDetectorResult::isCompact() {
|
||||
return compact_;
|
||||
}
|
||||
|
||||
int AztecDetectorResult::getNBDatablocks() {
|
||||
return nbDatablocks_;
|
||||
}
|
||||
|
||||
AztecDetectorResult::AztecDetectorResult(Ref<BitMatrix> bits,
|
||||
ArrayRef< Ref<ResultPoint> > points,
|
||||
bool compact,
|
||||
int nbDatablocks,
|
||||
int nbLayers)
|
||||
: DetectorResult(bits, points),
|
||||
compact_(compact),
|
||||
nbDatablocks_(nbDatablocks),
|
||||
nbLayers_(nbLayers) {
|
||||
int AztecDetectorResult::getNBLayers() {
|
||||
return nbLayers_;
|
||||
}
|
||||
}
|
||||
|
||||
bool AztecDetectorResult::isCompact() {
|
||||
return compact_;
|
||||
}
|
||||
|
||||
int AztecDetectorResult::getNBDatablocks() {
|
||||
return nbDatablocks_;
|
||||
}
|
||||
|
||||
int AztecDetectorResult::getNBLayers() {
|
||||
return nbLayers_;
|
||||
}
|
|
@ -25,24 +25,18 @@
|
|||
#define ZXingWidget_AtztecDetecorResult_h
|
||||
|
||||
namespace zxing {
|
||||
namespace aztec {
|
||||
|
||||
class AztecDetectorResult : public DetectorResult {
|
||||
private:
|
||||
bool compact_;
|
||||
int nbDatablocks_, nbLayers_;
|
||||
public:
|
||||
AztecDetectorResult(Ref<BitMatrix> bits,
|
||||
ArrayRef< Ref<ResultPoint> > points,
|
||||
bool compact,
|
||||
int nbDatablocks,
|
||||
int nbLayers);
|
||||
bool isCompact();
|
||||
int getNBDatablocks();
|
||||
int getNBLayers();
|
||||
};
|
||||
|
||||
}
|
||||
namespace aztec {
|
||||
class AztecDetectorResult : public DetectorResult {
|
||||
private:
|
||||
bool compact_;
|
||||
int nbDatablocks_, nbLayers_;
|
||||
public:
|
||||
AztecDetectorResult(Ref<BitMatrix> bits, std::vector<Ref<ResultPoint> > points, bool compact, int nbDatablocks, int nbLayers);
|
||||
bool isCompact();
|
||||
int getNBDatablocks();
|
||||
int getNBLayers();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
64
src/qzxing/zxing/aztec/AztecReader.cpp
Normal file
64
src/qzxing/zxing/aztec/AztecReader.cpp
Normal file
|
@ -0,0 +1,64 @@
|
|||
// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
|
||||
/*
|
||||
* AztecReader.cpp
|
||||
* zxing
|
||||
*
|
||||
* Created by Lukas Stabe on 08/02/2012.
|
||||
* Copyright 2012 ZXing authors All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <zxing/aztec/AztecReader.h>
|
||||
#include <zxing/aztec/detector/Detector.h>
|
||||
#include <iostream>
|
||||
|
||||
namespace zxing {
|
||||
namespace aztec {
|
||||
|
||||
AztecReader::AztecReader() : decoder_() {
|
||||
// nothing
|
||||
}
|
||||
|
||||
Ref<Result> AztecReader::decode(Ref<zxing::BinaryBitmap> image) {
|
||||
Detector detector(image->getBlackMatrix());
|
||||
|
||||
Ref<AztecDetectorResult> detectorResult(detector.detect());
|
||||
|
||||
std::vector<Ref<ResultPoint> > points(detectorResult->getPoints());
|
||||
|
||||
Ref<DecoderResult> decoderResult(decoder_.decode(detectorResult));
|
||||
|
||||
Ref<Result> result(new Result(decoderResult->getText(),
|
||||
decoderResult->getRawBytes(),
|
||||
points,
|
||||
BarcodeFormat_AZTEC));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Ref<Result> AztecReader::decode(Ref<BinaryBitmap> image, DecodeHints) {
|
||||
//cout << "decoding with hints not supported for aztec" << "\n" << flush;
|
||||
return this->decode(image);
|
||||
}
|
||||
|
||||
AztecReader::~AztecReader() {
|
||||
// nothing
|
||||
}
|
||||
|
||||
Decoder& AztecReader::getDecoder() {
|
||||
return decoder_;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -27,23 +27,23 @@
|
|||
#define ZXingWidget_AztecReader_h
|
||||
|
||||
namespace zxing {
|
||||
namespace aztec {
|
||||
namespace aztec {
|
||||
|
||||
class AztecReader : public Reader {
|
||||
private:
|
||||
Decoder decoder_;
|
||||
class AztecReader : public Reader {
|
||||
private:
|
||||
Decoder decoder_;
|
||||
|
||||
protected:
|
||||
Decoder &getDecoder();
|
||||
protected:
|
||||
Decoder &getDecoder();
|
||||
|
||||
public:
|
||||
AztecReader();
|
||||
virtual Ref<Result> decode(Ref<BinaryBitmap> image);
|
||||
virtual Ref<Result> decode(Ref<BinaryBitmap> image, DecodeHints hints);
|
||||
virtual ~AztecReader();
|
||||
};
|
||||
public:
|
||||
AztecReader();
|
||||
virtual Ref<Result> decode(Ref<BinaryBitmap> image);
|
||||
virtual Ref<Result> decode(Ref<BinaryBitmap> image, DecodeHints hints);
|
||||
virtual ~AztecReader();
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
496
src/qzxing/zxing/aztec/decoder/AztecDecoder.cpp
Normal file
496
src/qzxing/zxing/aztec/decoder/AztecDecoder.cpp
Normal file
|
@ -0,0 +1,496 @@
|
|||
// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
|
||||
/*
|
||||
* Decoder.cpp
|
||||
* zxing
|
||||
*
|
||||
* Created by Lukas Stabe on 08/02/2012.
|
||||
* Copyright 2012 ZXing authors All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <zxing/aztec/decoder/Decoder.h>
|
||||
#ifndef NO_ICONV
|
||||
#include <iconv.h>
|
||||
#endif
|
||||
#include <iostream>
|
||||
#include <zxing/FormatException.h>
|
||||
#include <zxing/common/reedsolomon/ReedSolomonDecoder.h>
|
||||
#include <zxing/common/reedsolomon/ReedSolomonException.h>
|
||||
#include <zxing/common/reedsolomon/GenericGF.h>
|
||||
#include <zxing/common/IllegalArgumentException.h>
|
||||
|
||||
#include <qglobal.h>
|
||||
|
||||
using zxing::aztec::Decoder;
|
||||
using zxing::DecoderResult;
|
||||
using zxing::String;
|
||||
using zxing::BitArray;
|
||||
using zxing::BitMatrix;
|
||||
using zxing::Ref;
|
||||
|
||||
using std::string;
|
||||
|
||||
namespace {
|
||||
void add(string& result, unsigned char character) {
|
||||
#ifndef NO_ICONV
|
||||
char s[] = { character & 0xff };
|
||||
char* ss = s;
|
||||
size_t sl = sizeof(s);
|
||||
char d[4];
|
||||
char* ds = d;
|
||||
size_t dl = sizeof(d);
|
||||
iconv_t ic = iconv_open("UTF-8", "ISO-8859-1");
|
||||
|
||||
|
||||
#if defined(Q_OS_SYMBIAN)
|
||||
iconv(ic, (const char**)&ss, &sl, &ds, &dl); // for Symbian and Mingw
|
||||
#else
|
||||
iconv(ic, (char**)&ss, &sl, &ds, &dl); // for Harmattan
|
||||
#endif
|
||||
iconv_close(ic);
|
||||
d[sizeof(d)-dl] = 0;
|
||||
result.append(d);
|
||||
#else
|
||||
result.push_back(character);
|
||||
#endif
|
||||
}
|
||||
|
||||
const int NB_BITS_COMPACT[] = {
|
||||
0, 104, 240, 408, 608
|
||||
};
|
||||
|
||||
const int NB_BITS[] = {
|
||||
0, 128, 288, 480, 704, 960, 1248, 1568, 1920, 2304, 2720, 3168, 3648, 4160, 4704, 5280, 5888, 6528,
|
||||
7200, 7904, 8640, 9408, 10208, 11040, 11904, 12800, 13728, 14688, 15680, 16704, 17760, 18848, 19968
|
||||
};
|
||||
|
||||
const int NB_DATABLOCK_COMPACT[] = {
|
||||
0, 17, 40, 51, 76
|
||||
};
|
||||
|
||||
const int NB_DATABLOCK[] = {
|
||||
0, 21, 48, 60, 88, 120, 156, 196, 240, 230, 272, 316, 364, 416, 470, 528, 588, 652, 720, 790, 864,
|
||||
940, 1020, 920, 992, 1066, 1144, 1224, 1306, 1392, 1480, 1570, 1664
|
||||
};
|
||||
|
||||
const char* UPPER_TABLE[] = {
|
||||
"CTRL_PS", " ", "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", "CTRL_LL", "CTRL_ML", "CTRL_DL", "CTRL_BS"
|
||||
};
|
||||
|
||||
const char* LOWER_TABLE[] = {
|
||||
"CTRL_PS", " ", "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", "CTRL_US", "CTRL_ML", "CTRL_DL", "CTRL_BS"
|
||||
};
|
||||
|
||||
const char* MIXED_TABLE[] = {
|
||||
"CTRL_PS", " ", "\1", "\2", "\3", "\4", "\5", "\6", "\7", "\b", "\t", "\n",
|
||||
"\13", "\f", "\r", "\33", "\34", "\35", "\36", "\37", "@", "\\", "^", "_",
|
||||
"`", "|", "~", "\177", "CTRL_LL", "CTRL_UL", "CTRL_PL", "CTRL_BS"
|
||||
};
|
||||
|
||||
const char* PUNCT_TABLE[] = {
|
||||
"", "\r", "\r\n", ". ", ", ", ": ", "!", "\"", "#", "$", "%", "&", "'", "(", ")",
|
||||
"*", "+", ",", "-", ".", "/", ":", ";", "<", "=", ">", "?", "[", "]", "{", "}", "CTRL_UL"
|
||||
};
|
||||
|
||||
const char* DIGIT_TABLE[] = {
|
||||
"CTRL_PS", " ", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ",", ".", "CTRL_UL", "CTRL_US"
|
||||
};
|
||||
}
|
||||
|
||||
Decoder::Table Decoder::getTable(char t) {
|
||||
switch (t) {
|
||||
case 'L':
|
||||
return LOWER;
|
||||
case 'P':
|
||||
return PUNCT;
|
||||
case 'M':
|
||||
return MIXED;
|
||||
case 'D':
|
||||
return DIGIT;
|
||||
case 'B':
|
||||
return BINARY;
|
||||
case 'U':
|
||||
default:
|
||||
return UPPER;
|
||||
}
|
||||
}
|
||||
|
||||
const char* Decoder::getCharacter(zxing::aztec::Decoder::Table table, int code) {
|
||||
switch (table) {
|
||||
case UPPER:
|
||||
return UPPER_TABLE[code];
|
||||
case LOWER:
|
||||
return LOWER_TABLE[code];
|
||||
case MIXED:
|
||||
return MIXED_TABLE[code];
|
||||
case PUNCT:
|
||||
return PUNCT_TABLE[code];
|
||||
case DIGIT:
|
||||
return DIGIT_TABLE[code];
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
Decoder::Decoder() {
|
||||
// nothing
|
||||
}
|
||||
|
||||
Ref<DecoderResult> Decoder::decode(Ref<zxing::aztec::AztecDetectorResult> detectorResult) {
|
||||
ddata_ = detectorResult;
|
||||
|
||||
// std::printf("getting bits\n");
|
||||
|
||||
Ref<BitMatrix> matrix = detectorResult->getBits();
|
||||
|
||||
if (!ddata_->isCompact()) {
|
||||
// std::printf("removing lines\n");
|
||||
matrix = removeDashedLines(ddata_->getBits());
|
||||
}
|
||||
|
||||
// std::printf("extracting bits\n");
|
||||
Ref<BitArray> rawbits = extractBits(matrix);
|
||||
|
||||
// std::printf("correcting bits\n");
|
||||
Ref<BitArray> aCorrectedBits = correctBits(rawbits);
|
||||
|
||||
// std::printf("decoding bits\n");
|
||||
Ref<String> result = getEncodedData(aCorrectedBits);
|
||||
|
||||
// std::printf("constructing array\n");
|
||||
ArrayRef<unsigned char> arrayOut(aCorrectedBits->getSize());
|
||||
for (int i = 0; i < aCorrectedBits->count(); i++) {
|
||||
arrayOut[i] = (unsigned char)aCorrectedBits->get(i);
|
||||
}
|
||||
|
||||
// std::printf("returning\n");
|
||||
|
||||
return Ref<DecoderResult>(new DecoderResult(arrayOut, result));
|
||||
}
|
||||
|
||||
Ref<String> Decoder::getEncodedData(Ref<zxing::BitArray> correctedBits) {
|
||||
int endIndex = codewordSize_ * ddata_->getNBDatablocks() - invertedBitCount_;
|
||||
if (endIndex > (int)correctedBits->getSize()) {
|
||||
// std::printf("invalid input\n");
|
||||
throw FormatException("invalid input data");
|
||||
}
|
||||
|
||||
Table lastTable = UPPER;
|
||||
Table table = UPPER;
|
||||
int startIndex = 0;
|
||||
std::string result;
|
||||
bool end = false;
|
||||
bool shift = false;
|
||||
bool switchShift = false;
|
||||
bool binaryShift = false;
|
||||
|
||||
while (!end) {
|
||||
// std::printf("decoooooding\n");
|
||||
|
||||
if (shift) {
|
||||
switchShift = true;
|
||||
} else {
|
||||
lastTable = table;
|
||||
}
|
||||
|
||||
int code;
|
||||
if (binaryShift) {
|
||||
if (endIndex - startIndex < 5) {
|
||||
break;
|
||||
}
|
||||
|
||||
int length = readCode(correctedBits, startIndex, 5);
|
||||
startIndex += 5;
|
||||
if (length == 0) {
|
||||
if (endIndex - startIndex < 11) {
|
||||
break;
|
||||
}
|
||||
|
||||
length = readCode(correctedBits, startIndex, 11) + 31;
|
||||
startIndex += 11;
|
||||
}
|
||||
for (int charCount = 0; charCount < length; charCount++) {
|
||||
if (endIndex - startIndex < 8) {
|
||||
end = true;
|
||||
break;
|
||||
}
|
||||
|
||||
code = readCode(correctedBits, startIndex, 8);
|
||||
add(result, code);
|
||||
startIndex += 8;
|
||||
}
|
||||
binaryShift = false;
|
||||
} else {
|
||||
if (table == BINARY) {
|
||||
if (endIndex - startIndex < 8) {
|
||||
end = true;
|
||||
break;
|
||||
}
|
||||
code = readCode(correctedBits, startIndex, 8);
|
||||
startIndex += 8;
|
||||
|
||||
add(result, code);
|
||||
} else {
|
||||
int size = 5;
|
||||
|
||||
if (table == DIGIT) {
|
||||
size = 4;
|
||||
}
|
||||
|
||||
if (endIndex - startIndex < size) {
|
||||
end = true;
|
||||
break;
|
||||
}
|
||||
|
||||
code = readCode(correctedBits, startIndex, size);
|
||||
startIndex += size;
|
||||
|
||||
const char *str = getCharacter(table, code);
|
||||
std::string string(str);
|
||||
if ((int)string.find("CTRL_") != -1) {
|
||||
table = getTable(str[5]);
|
||||
|
||||
if (str[6] == 'S') {
|
||||
shift = true;
|
||||
if (str[5] == 'B') {
|
||||
binaryShift = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result.append(string);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (switchShift) {
|
||||
table = lastTable;
|
||||
shift = false;
|
||||
switchShift = false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
return Ref<String>(new String(result));
|
||||
|
||||
}
|
||||
|
||||
Ref<zxing::BitArray> Decoder::correctBits(Ref<zxing::BitArray> rawbits) {
|
||||
//return rawbits;
|
||||
// std::printf("decoding stuff:%d datablocks in %d layers\n", ddata_->getNBDatablocks(), ddata_->getNBLayers());
|
||||
|
||||
Ref<GenericGF> gf = GenericGF::AZTEC_DATA_6;
|
||||
|
||||
if (ddata_->getNBLayers() <= 2) {
|
||||
codewordSize_ = 6;
|
||||
gf = GenericGF::AZTEC_DATA_6;
|
||||
} else if (ddata_->getNBLayers() <= 8) {
|
||||
codewordSize_ = 8;
|
||||
gf = GenericGF::AZTEC_DATA_8;
|
||||
} else if (ddata_->getNBLayers() <= 22) {
|
||||
codewordSize_ = 10;
|
||||
gf = GenericGF::AZTEC_DATA_10;
|
||||
} else {
|
||||
codewordSize_ = 12;
|
||||
gf = GenericGF::AZTEC_DATA_12;
|
||||
}
|
||||
|
||||
int numDataCodewords = ddata_->getNBDatablocks();
|
||||
int numECCodewords;
|
||||
int offset;
|
||||
|
||||
if (ddata_->isCompact()) {
|
||||
offset = NB_BITS_COMPACT[ddata_->getNBLayers()] - numCodewords_ * codewordSize_;
|
||||
numECCodewords = NB_DATABLOCK_COMPACT[ddata_->getNBLayers()] - numDataCodewords;
|
||||
} else {
|
||||
offset = NB_BITS[ddata_->getNBLayers()] - numCodewords_ * codewordSize_;
|
||||
numECCodewords = NB_DATABLOCK[ddata_->getNBLayers()] - numDataCodewords;
|
||||
}
|
||||
|
||||
ArrayRef<int> dataWords(numCodewords_);
|
||||
|
||||
for (int i = 0; i < numCodewords_; i++) {
|
||||
int flag = 1;
|
||||
for (int j = 1; j <= codewordSize_; j++) {
|
||||
if (rawbits->get(codewordSize_ * i + codewordSize_ - j + offset)) {
|
||||
dataWords[i] += flag;
|
||||
}
|
||||
flag <<= 1;
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
}
|
||||
|
||||
try {
|
||||
// std::printf("trying reed solomon, numECCodewords:%d\n", numECCodewords);
|
||||
ReedSolomonDecoder rsDecoder(gf);
|
||||
rsDecoder.decode(dataWords, numECCodewords);
|
||||
} catch (ReedSolomonException& rse) {
|
||||
// std::printf("got reed solomon exception:%s, throwing formatexception\n", rse.what());
|
||||
throw FormatException("rs decoding failed");
|
||||
} catch (IllegalArgumentException& iae) {
|
||||
// std::printf("illegal argument exception: %s", iae.what());
|
||||
}
|
||||
|
||||
offset = 0;
|
||||
invertedBitCount_ = 0;
|
||||
|
||||
Ref<BitArray> correctedBits(new BitArray(numDataCodewords * codewordSize_));
|
||||
for (int i = 0; i < numDataCodewords; i++) {
|
||||
|
||||
bool seriesColor = false;
|
||||
int seriesCount = 0;
|
||||
int flag = 1 << (codewordSize_ - 1);
|
||||
|
||||
for (int j = 0; j < codewordSize_; j++) {
|
||||
|
||||
bool color = (dataWords[i] & flag) == flag;
|
||||
|
||||
if (seriesCount == codewordSize_ - 1) {
|
||||
|
||||
if (color == seriesColor) {
|
||||
throw FormatException("bit was not inverted");
|
||||
}
|
||||
|
||||
seriesColor = false;
|
||||
seriesCount = 0;
|
||||
offset++;
|
||||
invertedBitCount_++;
|
||||
|
||||
} else {
|
||||
|
||||
if (seriesColor == color) {
|
||||
seriesCount++;
|
||||
} else {
|
||||
seriesCount = 1;
|
||||
seriesColor = color;
|
||||
}
|
||||
|
||||
if (color) correctedBits->set(i * codewordSize_ + j - offset);
|
||||
|
||||
}
|
||||
|
||||
flag = (unsigned int)flag >> 1;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return correctedBits;
|
||||
}
|
||||
|
||||
Ref<BitArray> Decoder::extractBits(Ref<zxing::BitMatrix> matrix) {
|
||||
std::vector<bool> rawbits;
|
||||
|
||||
if (ddata_->isCompact()) {
|
||||
if (ddata_->getNBLayers() > 5) { //NB_BITS_COMPACT length
|
||||
throw FormatException("data is too long");
|
||||
}
|
||||
rawbits = std::vector<bool>(NB_BITS_COMPACT[ddata_->getNBLayers()]);
|
||||
numCodewords_ = NB_DATABLOCK_COMPACT[ddata_->getNBLayers()];
|
||||
} else {
|
||||
if (ddata_->getNBLayers() > 33) { //NB_BITS length
|
||||
throw FormatException("data is too long");
|
||||
}
|
||||
rawbits = std::vector<bool>(NB_BITS[ddata_->getNBLayers()]);
|
||||
numCodewords_ = NB_DATABLOCK[ddata_->getNBLayers()];
|
||||
}
|
||||
|
||||
int layer = ddata_->getNBLayers();
|
||||
int size = matrix->getHeight();
|
||||
int rawbitsOffset = 0;
|
||||
int matrixOffset = 0;
|
||||
|
||||
|
||||
while (layer != 0) {
|
||||
|
||||
int flip = 0;
|
||||
for (int i = 0; i < 2 * size - 4; i++) {
|
||||
rawbits[rawbitsOffset + i] = matrix->get(matrixOffset + flip, matrixOffset + i / 2);
|
||||
rawbits[rawbitsOffset + 2 * size - 4 + i] = matrix->get(matrixOffset + i / 2, matrixOffset + size - 1 - flip);
|
||||
flip = (flip + 1) % 2;
|
||||
}
|
||||
|
||||
flip = 0;
|
||||
for (int i = 2 * size + 1; i > 5; i--) {
|
||||
rawbits[rawbitsOffset + 4 * size - 8 + (2 * size - i) + 1] =
|
||||
matrix->get(matrixOffset + size - 1 - flip, matrixOffset + i / 2 - 1);
|
||||
rawbits[rawbitsOffset + 6 * size - 12 + (2 * size - i) + 1] =
|
||||
matrix->get(matrixOffset + i / 2 - 1, matrixOffset + flip);
|
||||
flip = (flip + 1) % 2;
|
||||
}
|
||||
|
||||
matrixOffset += 2;
|
||||
rawbitsOffset += 8 * size - 16;
|
||||
layer--;
|
||||
size -= 4;
|
||||
|
||||
}
|
||||
|
||||
Ref<BitArray> returnValue(new BitArray(rawbits.size()));
|
||||
for (int i = 0; i < (int)rawbits.size(); i++) {
|
||||
if (rawbits[i]) returnValue->set(i);
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
|
||||
}
|
||||
|
||||
Ref<BitMatrix> Decoder::removeDashedLines(Ref<zxing::BitMatrix> matrix) {
|
||||
int nbDashed = 1 + 2 * ((matrix->getWidth() - 1) / 2 / 16);
|
||||
Ref<BitMatrix> newMatrix(new BitMatrix(matrix->getWidth() - nbDashed, matrix->getHeight() - nbDashed));
|
||||
|
||||
int nx = 0;
|
||||
|
||||
for (int x = 0; x < (int)matrix->getWidth(); x++) {
|
||||
|
||||
if ((matrix->getWidth() / 2 - x) % 16 == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int ny = 0;
|
||||
for (int y = 0; y < (int)matrix->getHeight(); y++) {
|
||||
|
||||
if ((matrix->getWidth() / 2 - y) % 16 == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (matrix->get(x, y)) {
|
||||
newMatrix->set(nx, ny);
|
||||
}
|
||||
ny++;
|
||||
|
||||
}
|
||||
nx++;
|
||||
|
||||
}
|
||||
return newMatrix;
|
||||
}
|
||||
|
||||
int Decoder::readCode(Ref<zxing::BitArray> rawbits, int startIndex, int length) {
|
||||
int res = 0;
|
||||
|
||||
for (int i = startIndex; i < startIndex + length; i++) {
|
||||
res <<= 1;
|
||||
if (rawbits->get(i)) {
|
||||
res ++;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
63
src/qzxing/zxing/aztec/decoder/Decoder.h
Normal file
63
src/qzxing/zxing/aztec/decoder/Decoder.h
Normal file
|
@ -0,0 +1,63 @@
|
|||
// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
|
||||
/*
|
||||
* Decoder.h
|
||||
* zxing
|
||||
*
|
||||
* Created by Lukas Stabe on 08/02/2012.
|
||||
* Copyright 2012 ZXing authors All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <zxing/common/DecoderResult.h>
|
||||
#include <zxing/common/BitMatrix.h>
|
||||
#include <zxing/common/Str.h>
|
||||
#include <zxing/aztec/AztecDetectorResult.h>
|
||||
|
||||
namespace zxing {
|
||||
namespace aztec {
|
||||
|
||||
class Decoder : public Counted {
|
||||
private:
|
||||
enum Table {
|
||||
UPPER,
|
||||
LOWER,
|
||||
MIXED,
|
||||
DIGIT,
|
||||
PUNCT,
|
||||
BINARY
|
||||
};
|
||||
|
||||
static Table getTable(char t);
|
||||
static const char* getCharacter(Table table, int code);
|
||||
|
||||
int numCodewords_;
|
||||
int codewordSize_;
|
||||
Ref<AztecDetectorResult> ddata_;
|
||||
int invertedBitCount_;
|
||||
|
||||
Ref<String> getEncodedData(Ref<BitArray> correctedBits);
|
||||
Ref<BitArray> correctBits(Ref<BitArray> rawbits);
|
||||
Ref<BitArray> extractBits(Ref<BitMatrix> matrix);
|
||||
static Ref<BitMatrix> removeDashedLines(Ref<BitMatrix> matrix);
|
||||
static int readCode(Ref<BitArray> rawbits, int startIndex, int length);
|
||||
|
||||
|
||||
public:
|
||||
Decoder();
|
||||
Ref<DecoderResult> decode(Ref<AztecDetectorResult> detectorResult);
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -26,19 +26,16 @@
|
|||
#include <zxing/common/reedsolomon/ReedSolomonException.h>
|
||||
#include <zxing/common/reedsolomon/GenericGF.h>
|
||||
#include <iostream>
|
||||
#include <zxing/common/detector/MathUtils.h>
|
||||
#include <cmath>
|
||||
#include <zxing/NotFoundException.h>
|
||||
|
||||
using std::vector;
|
||||
using zxing::aztec::Detector;
|
||||
using zxing::aztec::Point;
|
||||
using zxing::aztec::AztecDetectorResult;
|
||||
using zxing::Ref;
|
||||
using zxing::ArrayRef;
|
||||
using zxing::ResultPoint;
|
||||
using zxing::BitArray;
|
||||
using zxing::BitMatrix;
|
||||
using zxing::common::detector::MathUtils;
|
||||
|
||||
Detector::Detector(Ref<BitMatrix> image):
|
||||
image_(image),
|
||||
|
@ -48,6 +45,8 @@ Detector::Detector(Ref<BitMatrix> image):
|
|||
|
||||
}
|
||||
|
||||
// using namespace std;
|
||||
|
||||
Ref<AztecDetectorResult> Detector::detect() {
|
||||
Ref<Point> pCenter = getMatrixCenter();
|
||||
|
||||
|
@ -55,14 +54,9 @@ Ref<AztecDetectorResult> Detector::detect() {
|
|||
|
||||
extractParameters(bullEyeCornerPoints);
|
||||
|
||||
ArrayRef< Ref<ResultPoint> > corners = getMatrixCornerPoints(bullEyeCornerPoints);
|
||||
std::vector<Ref<ResultPoint> > corners = getMatrixCornerPoints(bullEyeCornerPoints);
|
||||
|
||||
Ref<BitMatrix> bits =
|
||||
sampleGrid(image_,
|
||||
corners[shift_%4],
|
||||
corners[(shift_+3)%4],
|
||||
corners[(shift_+2)%4],
|
||||
corners[(shift_+1)%4]);
|
||||
Ref<BitMatrix> bits = sampleGrid(image_, corners[shift_%4], corners[(shift_+3)%4], corners[(shift_+2)%4], corners[(shift_+1)%4]);
|
||||
|
||||
// std::printf("------------\ndetected: compact:%s, nbDataBlocks:%d, nbLayers:%d\n------------\n",compact_?"YES":"NO", nbDataBlocks_, nbLayers_);
|
||||
|
||||
|
@ -70,21 +64,20 @@ Ref<AztecDetectorResult> Detector::detect() {
|
|||
}
|
||||
|
||||
void Detector::extractParameters(std::vector<Ref<Point> > bullEyeCornerPoints) {
|
||||
int twoCenterLayers = 2 * nbCenterLayers_;
|
||||
// get the bits around the bull's eye
|
||||
Ref<BitArray> resab = sampleLine(bullEyeCornerPoints[0], bullEyeCornerPoints[1], twoCenterLayers+1);
|
||||
Ref<BitArray> resbc = sampleLine(bullEyeCornerPoints[1], bullEyeCornerPoints[2], twoCenterLayers+1);
|
||||
Ref<BitArray> rescd = sampleLine(bullEyeCornerPoints[2], bullEyeCornerPoints[3], twoCenterLayers+1);
|
||||
Ref<BitArray> resda = sampleLine(bullEyeCornerPoints[3], bullEyeCornerPoints[0], twoCenterLayers+1);
|
||||
Ref<BitArray> resab = sampleLine(bullEyeCornerPoints[0], bullEyeCornerPoints[1], 2*nbCenterLayers_+1);
|
||||
Ref<BitArray> resbc = sampleLine(bullEyeCornerPoints[1], bullEyeCornerPoints[2], 2*nbCenterLayers_+1);
|
||||
Ref<BitArray> rescd = sampleLine(bullEyeCornerPoints[2], bullEyeCornerPoints[3], 2*nbCenterLayers_+1);
|
||||
Ref<BitArray> resda = sampleLine(bullEyeCornerPoints[3], bullEyeCornerPoints[0], 2*nbCenterLayers_+1);
|
||||
|
||||
// determin the orientation of the matrix
|
||||
if (resab->get(0) && resab->get(twoCenterLayers)) {
|
||||
if (resab->get(0) && resab->get(2 * nbCenterLayers_)) {
|
||||
shift_ = 0;
|
||||
} else if (resbc->get(0) && resbc->get(twoCenterLayers)) {
|
||||
} else if (resbc->get(0) && resbc->get(2 * nbCenterLayers_)) {
|
||||
shift_ = 1;
|
||||
} else if (rescd->get(0) && rescd->get(twoCenterLayers)) {
|
||||
} else if (rescd->get(0) && rescd->get(2 * nbCenterLayers_)) {
|
||||
shift_ = 2;
|
||||
} else if (resda->get(0) && resda->get(twoCenterLayers)) {
|
||||
} else if (resda->get(0) && resda->get(2 * nbCenterLayers_)) {
|
||||
shift_ = 3;
|
||||
} else {
|
||||
// std::printf("could not detemine orientation\n");
|
||||
|
@ -120,9 +113,9 @@ void Detector::extractParameters(std::vector<Ref<Point> > bullEyeCornerPoints) {
|
|||
}
|
||||
if (i > 5) {
|
||||
if (resab->get(2+i)) shiftedParameterData->set(i-1);
|
||||
if (resbc->get(2+i)) shiftedParameterData->set(i+9);
|
||||
if (rescd->get(2+i)) shiftedParameterData->set(i+19);
|
||||
if (resda->get(2+i)) shiftedParameterData->set(i+29);
|
||||
if (resbc->get(2+i)) shiftedParameterData->set(i+10-1);
|
||||
if (rescd->get(2+i)) shiftedParameterData->set(i+20-1);
|
||||
if (resda->get(2+i)) shiftedParameterData->set(i+30-1);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < 40; i++) {
|
||||
|
@ -135,45 +128,44 @@ void Detector::extractParameters(std::vector<Ref<Point> > bullEyeCornerPoints) {
|
|||
getParameters(parameterData);
|
||||
}
|
||||
|
||||
ArrayRef< Ref<ResultPoint> >
|
||||
Detector::getMatrixCornerPoints(std::vector<Ref<Point> > bullEyeCornerPoints) {
|
||||
std::vector<Ref<ResultPoint> > Detector::getMatrixCornerPoints(std::vector<Ref<Point> > bullEyeCornerPoints) {
|
||||
float ratio = (2 * nbLayers_ + (nbLayers_ > 4 ? 1 : 0) + (nbLayers_ - 4) / 8) / (2.0f * nbCenterLayers_);
|
||||
|
||||
int dx = bullEyeCornerPoints[0]->getX() - bullEyeCornerPoints[2]->getX();
|
||||
int dx = bullEyeCornerPoints[0]->x - bullEyeCornerPoints[2]->x;
|
||||
dx += dx > 0 ? 1 : -1;
|
||||
int dy = bullEyeCornerPoints[0]->getY() - bullEyeCornerPoints[2]->getY();
|
||||
int dy = bullEyeCornerPoints[0]->y - bullEyeCornerPoints[2]->y;
|
||||
dy += dy > 0 ? 1 : -1;
|
||||
|
||||
int targetcx = MathUtils::round(bullEyeCornerPoints[2]->getX() - ratio * dx);
|
||||
int targetcy = MathUtils::round(bullEyeCornerPoints[2]->getY() - ratio * dy);
|
||||
int targetcx = ROUND(bullEyeCornerPoints[2]->x - ratio * dx);
|
||||
int targetcy = ROUND(bullEyeCornerPoints[2]->y - ratio * dy);
|
||||
|
||||
int targetax = MathUtils::round(bullEyeCornerPoints[0]->getX() + ratio * dx);
|
||||
int targetay = MathUtils::round(bullEyeCornerPoints[0]->getY() + ratio * dy);
|
||||
int targetax = ROUND(bullEyeCornerPoints[0]->x + ratio * dx);
|
||||
int targetay = ROUND(bullEyeCornerPoints[0]->y + ratio * dy);
|
||||
|
||||
dx = bullEyeCornerPoints[1]->getX() - bullEyeCornerPoints[3]->getX();
|
||||
dx = bullEyeCornerPoints[1]->x - bullEyeCornerPoints[3]->x;
|
||||
dx += dx > 0 ? 1 : -1;
|
||||
dy = bullEyeCornerPoints[1]->getY() - bullEyeCornerPoints[3]->getY();
|
||||
dy = bullEyeCornerPoints[1]->y - bullEyeCornerPoints[3]->y;
|
||||
dy += dy > 0 ? 1 : -1;
|
||||
|
||||
int targetdx = MathUtils::round(bullEyeCornerPoints[3]->getX() - ratio * dx);
|
||||
int targetdy = MathUtils::round(bullEyeCornerPoints[3]->getY() - ratio * dy);
|
||||
int targetbx = MathUtils::round(bullEyeCornerPoints[1]->getX() + ratio * dx);
|
||||
int targetby = MathUtils::round(bullEyeCornerPoints[1]->getY() + ratio * dy);
|
||||
int targetdx = ROUND(bullEyeCornerPoints[3]->x - ratio * dx);
|
||||
int targetdy = ROUND(bullEyeCornerPoints[3]->y - ratio * dy);
|
||||
int targetbx = ROUND(bullEyeCornerPoints[1]->x + ratio * dx);
|
||||
int targetby = ROUND(bullEyeCornerPoints[1]->y + ratio * dy);
|
||||
|
||||
if (!isValid(targetax, targetay) ||
|
||||
!isValid(targetbx, targetby) ||
|
||||
|
||||
!isValid(targetcx, targetcy) ||
|
||||
!isValid(targetdx, targetdy)) {
|
||||
throw ReaderException("matrix extends over image bounds");
|
||||
}
|
||||
Array< Ref<ResultPoint> >* array = new Array< Ref<ResultPoint> >();
|
||||
vector< Ref<ResultPoint> >& returnValue (array->values());
|
||||
returnValue.push_back(Ref<ResultPoint>(new ResultPoint(float(targetax), float(targetay))));
|
||||
returnValue.push_back(Ref<ResultPoint>(new ResultPoint(float(targetbx), float(targetby))));
|
||||
returnValue.push_back(Ref<ResultPoint>(new ResultPoint(float(targetcx), float(targetcy))));
|
||||
returnValue.push_back(Ref<ResultPoint>(new ResultPoint(float(targetdx), float(targetdy))));
|
||||
return ArrayRef< Ref<ResultPoint> >(array);
|
||||
std::vector<Ref<ResultPoint> > returnValue;
|
||||
returnValue.push_back(Ref<ResultPoint>(new ResultPoint(targetax, targetay)));
|
||||
returnValue.push_back(Ref<ResultPoint>(new ResultPoint(targetbx, targetby)));
|
||||
returnValue.push_back(Ref<ResultPoint>(new ResultPoint(targetcx, targetcy)));
|
||||
returnValue.push_back(Ref<ResultPoint>(new ResultPoint(targetdx, targetdy)));
|
||||
|
||||
return returnValue;
|
||||
|
||||
}
|
||||
|
||||
void Detector::correctParameterData(Ref<zxing::BitArray> parameterData, bool compact) {
|
||||
|
@ -207,8 +199,7 @@ void Detector::correctParameterData(Ref<zxing::BitArray> parameterData, bool com
|
|||
// std::printf("parameter data reed solomon\n");
|
||||
ReedSolomonDecoder rsDecoder(GenericGF::AZTEC_PARAM);
|
||||
rsDecoder.decode(parameterWords, numECCodewords);
|
||||
} catch (ReedSolomonException const& ignored) {
|
||||
(void)ignored;
|
||||
} catch (ReedSolomonException& e) {
|
||||
// std::printf("reed solomon decoding failed\n");
|
||||
throw ReaderException("failed to decode parameter data");
|
||||
}
|
||||
|
@ -268,21 +259,21 @@ std::vector<Ref<Point> > Detector::getBullEyeCornerPoints(Ref<zxing::aztec::Poin
|
|||
|
||||
float ratio = 0.75f*2 / (2*nbCenterLayers_-3);
|
||||
|
||||
int dx = pina->getX() - pind->getX();
|
||||
int dy = pina->getY() - pinc->getY();
|
||||
int dx = pina->x - pind->x;
|
||||
int dy = pina->y - pinc->y;
|
||||
|
||||
int targetcx = MathUtils::round(pinc->getX() - ratio * dx);
|
||||
int targetcy = MathUtils::round(pinc->getY() - ratio * dy);
|
||||
int targetax = MathUtils::round(pina->getX() + ratio * dx);
|
||||
int targetay = MathUtils::round(pina->getY() + ratio * dy);
|
||||
int targetcx = ROUND(pinc->x - ratio * dx);
|
||||
int targetcy = ROUND(pinc->y - ratio * dy);
|
||||
int targetax = ROUND(pina->x + ratio * dx);
|
||||
int targetay = ROUND(pina->y + ratio * dy);
|
||||
|
||||
dx = pinb->getX() - pind->getX();
|
||||
dy = pinb->getY() - pind->getY();
|
||||
dx = pinb->x - pind->x;
|
||||
dy = pinb->y - pind->y;
|
||||
|
||||
int targetdx = MathUtils::round(pind->getX() - ratio * dx);
|
||||
int targetdy = MathUtils::round(pind->getY() - ratio * dy);
|
||||
int targetbx = MathUtils::round(pinb->getX() + ratio * dx);
|
||||
int targetby = MathUtils::round(pinb->getY() + ratio * dy);
|
||||
int targetdx = ROUND(pind->x - ratio * dx);
|
||||
int targetdy = ROUND(pind->y - ratio * dy);
|
||||
int targetbx = ROUND(pinb->x + ratio * dx);
|
||||
int targetby = ROUND(pinb->y + ratio * dy);
|
||||
|
||||
if (!isValid(targetax, targetay) ||
|
||||
!isValid(targetbx, targetby) ||
|
||||
|
@ -311,21 +302,20 @@ Ref<Point> Detector::getMatrixCenter() {
|
|||
pointC = cornerPoints[2];
|
||||
pointD = cornerPoints[3];
|
||||
|
||||
} catch (NotFoundException const& e) {
|
||||
(void)e;
|
||||
} catch (NotFoundException& e) {
|
||||
|
||||
int cx = image_->getWidth() / 2;
|
||||
int cy = image_->getHeight() / 2;
|
||||
|
||||
pointA = getFirstDifferent(Ref<Point>(new Point(cx+7, cy-7)), false, 1, -1)->toResultPoint();
|
||||
pointB = getFirstDifferent(Ref<Point>(new Point(cx+7, cy+7)), false, 1, 1)->toResultPoint();
|
||||
pointC = getFirstDifferent(Ref<Point>(new Point(cx-7, cy+7)), false, -1, -1)->toResultPoint();
|
||||
pointD = getFirstDifferent(Ref<Point>(new Point(cx-7, cy-7)), false, -1, -1)->toResultPoint();
|
||||
pointA = getFirstDifferent(Ref<Point>(new Point(cx+15/2, cy-15/2)), false, 1, -1)->toResultPoint();
|
||||
pointB = getFirstDifferent(Ref<Point>(new Point(cx+15/2, cy+15/2)), false, 1, 1)->toResultPoint();
|
||||
pointC = getFirstDifferent(Ref<Point>(new Point(cx-15/2, cy+15/2)), false, -1, -1)->toResultPoint();
|
||||
pointD = getFirstDifferent(Ref<Point>(new Point(cx-15/2, cy-15/2)), false, -1, -1)->toResultPoint();
|
||||
|
||||
}
|
||||
|
||||
int cx = MathUtils::round((pointA->getX() + pointD->getX() + pointB->getX() + pointC->getX()) / 4.0f);
|
||||
int cy = MathUtils::round((pointA->getY() + pointD->getY() + pointB->getY() + pointC->getY()) / 4.0f);
|
||||
int cx = ROUND((pointA->getX() + pointD->getX() + pointB->getX() + pointC->getX()) / 4);
|
||||
int cy = ROUND((pointA->getY() + pointD->getY() + pointB->getY() + pointC->getY()) / 4);
|
||||
|
||||
try {
|
||||
|
||||
|
@ -335,18 +325,17 @@ Ref<Point> Detector::getMatrixCenter() {
|
|||
pointC = cornerPoints[2];
|
||||
pointD = cornerPoints[3];
|
||||
|
||||
} catch (NotFoundException const& e) {
|
||||
(void)e;
|
||||
} catch (NotFoundException& e) {
|
||||
|
||||
pointA = getFirstDifferent(Ref<Point>(new Point(cx+7, cy-7)), false, 1, -1)->toResultPoint();
|
||||
pointB = getFirstDifferent(Ref<Point>(new Point(cx+7, cy+7)), false, 1, 1)->toResultPoint();
|
||||
pointC = getFirstDifferent(Ref<Point>(new Point(cx-7, cy+7)), false, -1, 1)->toResultPoint();
|
||||
pointD = getFirstDifferent(Ref<Point>(new Point(cx-7, cy-7)), false, -1, -1)->toResultPoint();
|
||||
pointA = getFirstDifferent(Ref<Point>(new Point(cx+15/2, cy-15/2)), false, 1, -1)->toResultPoint();
|
||||
pointB = getFirstDifferent(Ref<Point>(new Point(cx+15/2, cy+15/2)), false, 1, 1)->toResultPoint();
|
||||
pointC = getFirstDifferent(Ref<Point>(new Point(cx-15/2, cy+15/2)), false, -1, -1)->toResultPoint();
|
||||
pointD = getFirstDifferent(Ref<Point>(new Point(cx-15/2, cy-15/2)), false, -1, -1)->toResultPoint();
|
||||
|
||||
}
|
||||
|
||||
cx = MathUtils::round((pointA->getX() + pointD->getX() + pointB->getX() + pointC->getX()) / 4.0f);
|
||||
cy = MathUtils::round((pointA->getY() + pointD->getY() + pointB->getY() + pointC->getY()) / 4.0f);
|
||||
cx = ROUND((pointA->getX() + pointD->getX() + pointB->getX() + pointC->getX()) / 4);
|
||||
cy = ROUND((pointA->getY() + pointD->getY() + pointB->getY() + pointC->getY()) / 4);
|
||||
|
||||
return Ref<Point>(new Point(cx, cy));
|
||||
|
||||
|
@ -408,19 +397,19 @@ void Detector::getParameters(Ref<zxing::BitArray> parameterData) {
|
|||
for (int i = 0; i < nbBitsForNbLayers; i++) {
|
||||
nbLayers_ <<= 1;
|
||||
if (parameterData->get(i)) {
|
||||
nbLayers_++;
|
||||
nbLayers_ += 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = nbBitsForNbLayers; i < nbBitsForNbLayers + nbBitsForNbDatablocks; i++) {
|
||||
nbDataBlocks_ <<= 1;
|
||||
if (parameterData->get(i)) {
|
||||
nbDataBlocks_++;
|
||||
nbDataBlocks_ += 1;
|
||||
}
|
||||
}
|
||||
|
||||
nbLayers_++;
|
||||
nbDataBlocks_++;
|
||||
nbLayers_ ++;
|
||||
nbDataBlocks_ ++;
|
||||
}
|
||||
|
||||
Ref<BitArray> Detector::sampleLine(Ref<zxing::aztec::Point> p1, Ref<zxing::aztec::Point> p2, int size) {
|
||||
|
@ -428,16 +417,16 @@ Ref<BitArray> Detector::sampleLine(Ref<zxing::aztec::Point> p1, Ref<zxing::aztec
|
|||
|
||||
float d = distance(p1, p2);
|
||||
float moduleSize = d / (size-1);
|
||||
float dx = moduleSize * float(p2->getX() - p1->getX())/d;
|
||||
float dy = moduleSize * float(p2->getY() - p1->getY())/d;
|
||||
float dx = moduleSize * (p2->x - p1->x)/d;
|
||||
float dy = moduleSize * (p2->y - p1->y)/d;
|
||||
|
||||
float px = float(p1->getX());
|
||||
float py = float(p1->getY());
|
||||
float px = p1->x;
|
||||
float py = p1->y;
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
if (image_->get(MathUtils::round(px), MathUtils::round(py))) res->set(i);
|
||||
px+=dx;
|
||||
py+=dy;
|
||||
if (image_->get(ROUND(px), ROUND(py))) res->set(i);
|
||||
px += dx;
|
||||
py += dy;
|
||||
}
|
||||
|
||||
return res;
|
||||
|
@ -449,10 +438,10 @@ bool Detector::isWhiteOrBlackRectangle(Ref<zxing::aztec::Point> p1,
|
|||
Ref<zxing::aztec::Point> p4) {
|
||||
int corr = 3;
|
||||
|
||||
p1 = new Point(p1->getX() - corr, p1->getY() + corr);
|
||||
p2 = new Point(p2->getX() - corr, p2->getY() - corr);
|
||||
p3 = new Point(p3->getX() + corr, p3->getY() - corr);
|
||||
p4 = new Point(p4->getX() + corr, p4->getY() + corr);
|
||||
p1 = new Point(p1->x - corr, p1->y + corr);
|
||||
p2 = new Point(p2->x - corr, p2->y - corr);
|
||||
p3 = new Point(p3->x + corr, p3->y - corr);
|
||||
p4 = new Point(p4->x + corr, p4->y + corr);
|
||||
|
||||
int cInit = getColor(p4, p1);
|
||||
|
||||
|
@ -484,20 +473,20 @@ bool Detector::isWhiteOrBlackRectangle(Ref<zxing::aztec::Point> p1,
|
|||
int Detector::getColor(Ref<zxing::aztec::Point> p1, Ref<zxing::aztec::Point> p2) {
|
||||
float d = distance(p1, p2);
|
||||
|
||||
float dx = (p2->getX() - p1->getX()) / d;
|
||||
float dy = (p2->getY() - p1->getY()) / d;
|
||||
float dx = (p2->x - p1->x) / d;
|
||||
float dy = (p2->y - p1->y) / d;
|
||||
|
||||
int error = 0;
|
||||
|
||||
float px = float(p1->getX());
|
||||
float py = float(p1->getY());
|
||||
float px = p1->x;
|
||||
float py = p1->y;
|
||||
|
||||
bool colorModel = image_->get(p1->getX(), p1->getY());
|
||||
bool colorModel = image_->get(p1->x, p1->y);
|
||||
|
||||
for (int i = 0; i < d; i++) {
|
||||
px += dx;
|
||||
py += dy;
|
||||
if (image_->get(MathUtils::round(px), MathUtils::round(py)) != colorModel) {
|
||||
if (image_->get(ROUND(px), ROUND(py)) != colorModel) {
|
||||
error ++;
|
||||
}
|
||||
}
|
||||
|
@ -505,16 +494,20 @@ int Detector::getColor(Ref<zxing::aztec::Point> p1, Ref<zxing::aztec::Point> p2)
|
|||
float errRatio = (float)error/d;
|
||||
|
||||
|
||||
if (errRatio > 0.1f && errRatio < 0.9f) {
|
||||
if (errRatio > 0.1 && errRatio < 0.9) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (errRatio <= 0.1) == colorModel ? 1 : -1;
|
||||
if (errRatio <= 0.1) {
|
||||
return colorModel?1:-1;
|
||||
} else {
|
||||
return colorModel?-1:1;
|
||||
}
|
||||
}
|
||||
|
||||
Ref<Point> Detector::getFirstDifferent(Ref<zxing::aztec::Point> init, bool color, int dx, int dy) {
|
||||
int x = init->getX() + dx;
|
||||
int y = init->getY() + dy;
|
||||
int x = init->x + dx;
|
||||
int y = init->y + dy;
|
||||
|
||||
while (isValid(x, y) && image_->get(x, y) == color) {
|
||||
x += dx;
|
||||
|
@ -544,5 +537,5 @@ bool Detector::isValid(int x, int y) {
|
|||
}
|
||||
|
||||
float Detector::distance(Ref<zxing::aztec::Point> a, Ref<zxing::aztec::Point> b) {
|
||||
return sqrtf((float)((a->getX() - b->getX()) * (a->getX() - b->getX()) + (a->getY() - b->getY()) * (a->getY() - b->getY())));
|
||||
return sqrtf((float)((a->x - b->x) * (a->x - b->x) + (a->y - b->y) * (a->y - b->y)));
|
||||
}
|
87
src/qzxing/zxing/aztec/detector/Detector.h
Normal file
87
src/qzxing/zxing/aztec/detector/Detector.h
Normal file
|
@ -0,0 +1,87 @@
|
|||
// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
|
||||
/*
|
||||
* Detector.h
|
||||
* zxing
|
||||
*
|
||||
* Created by Lukas Stabe on 08/02/2012.
|
||||
* Copyright 2012 ZXing authors All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <zxing/common/BitArray.h>
|
||||
#include <zxing/ResultPoint.h>
|
||||
#include <zxing/common/BitMatrix.h>
|
||||
#include <zxing/DecodeHints.h>
|
||||
#include <zxing/aztec/AztecDetectorResult.h>
|
||||
|
||||
#define ROUND(a) ((int)(a + 0.5f))
|
||||
|
||||
namespace zxing {
|
||||
namespace aztec {
|
||||
|
||||
class Point : public Counted {
|
||||
public:
|
||||
int x;
|
||||
int y;
|
||||
|
||||
Ref<ResultPoint> toResultPoint() {
|
||||
return Ref<ResultPoint>(new ResultPoint(x, y));
|
||||
}
|
||||
|
||||
Point(int ax, int ay):x(ax),y(ay) {};
|
||||
|
||||
};
|
||||
|
||||
class Detector : public Counted {
|
||||
|
||||
private:
|
||||
Ref<BitMatrix> image_;
|
||||
|
||||
bool compact_;
|
||||
int nbLayers_;
|
||||
int nbDataBlocks_;
|
||||
int nbCenterLayers_;
|
||||
int shift_;
|
||||
|
||||
void extractParameters(std::vector<Ref<Point> > bullEyeCornerPoints);
|
||||
std::vector<Ref<ResultPoint> > getMatrixCornerPoints(std::vector<Ref<Point> > bullEyeCornerPoints);
|
||||
static void correctParameterData(Ref<BitArray> parameterData, bool compact);
|
||||
std::vector<Ref<Point> > getBullEyeCornerPoints(Ref<Point> pCenter);
|
||||
Ref<Point> getMatrixCenter();
|
||||
Ref<BitMatrix> sampleGrid(Ref<BitMatrix> image,
|
||||
Ref<ResultPoint> topLeft,
|
||||
Ref<ResultPoint> bottomLeft,
|
||||
Ref<ResultPoint> bottomRight,
|
||||
Ref<ResultPoint> topRight);
|
||||
void getParameters(Ref<BitArray> parameterData);
|
||||
Ref<BitArray> sampleLine(Ref<Point> p1, Ref<Point> p2, int size);
|
||||
bool isWhiteOrBlackRectangle(Ref<Point> p1,
|
||||
Ref<Point> p2,
|
||||
Ref<Point> p3,
|
||||
Ref<Point> p4);
|
||||
int getColor(Ref<Point> p1, Ref<Point> p2);
|
||||
Ref<Point> getFirstDifferent(Ref<Point> init, bool color, int dx, int dy);
|
||||
bool isValid(int x, int y);
|
||||
static float distance(Ref<Point> a, Ref<Point> b);
|
||||
|
||||
public:
|
||||
Detector(Ref<BitMatrix> image);
|
||||
Ref<AztecDetectorResult> detect();
|
||||
};
|
||||
|
||||
}
|
||||
}
|
|
@ -1,405 +0,0 @@
|
|||
#include "BigInteger.hh"
|
||||
|
||||
void BigInteger::operator =(const BigInteger &x) {
|
||||
// Calls like a = a have no effect
|
||||
if (this == &x)
|
||||
return;
|
||||
// Copy sign
|
||||
sign = x.sign;
|
||||
// Copy the rest
|
||||
mag = x.mag;
|
||||
}
|
||||
|
||||
BigInteger::BigInteger(const Blk *b, Index blen, Sign s) : mag(b, blen) {
|
||||
switch (s) {
|
||||
case zero:
|
||||
if (!mag.isZero())
|
||||
throw "BigInteger::BigInteger(const Blk *, Index, Sign): Cannot use a sign of zero with a nonzero magnitude";
|
||||
sign = zero;
|
||||
break;
|
||||
case positive:
|
||||
case negative:
|
||||
// If the magnitude is zero, force the sign to zero.
|
||||
sign = mag.isZero() ? zero : s;
|
||||
break;
|
||||
default:
|
||||
/* g++ seems to be optimizing out this case on the assumption
|
||||
* that the sign is a valid member of the enumeration. Oh well. */
|
||||
throw "BigInteger::BigInteger(const Blk *, Index, Sign): Invalid sign";
|
||||
}
|
||||
}
|
||||
|
||||
BigInteger::BigInteger(const BigUnsigned &x, Sign s) : mag(x) {
|
||||
switch (s) {
|
||||
case zero:
|
||||
if (!mag.isZero())
|
||||
throw "BigInteger::BigInteger(const BigUnsigned &, Sign): Cannot use a sign of zero with a nonzero magnitude";
|
||||
sign = zero;
|
||||
break;
|
||||
case positive:
|
||||
case negative:
|
||||
// If the magnitude is zero, force the sign to zero.
|
||||
sign = mag.isZero() ? zero : s;
|
||||
break;
|
||||
default:
|
||||
/* g++ seems to be optimizing out this case on the assumption
|
||||
* that the sign is a valid member of the enumeration. Oh well. */
|
||||
throw "BigInteger::BigInteger(const BigUnsigned &, Sign): Invalid sign";
|
||||
}
|
||||
}
|
||||
|
||||
/* CONSTRUCTION FROM PRIMITIVE INTEGERS
|
||||
* Same idea as in BigUnsigned.cc, except that negative input results in a
|
||||
* negative BigInteger instead of an exception. */
|
||||
|
||||
// Done longhand to let us use initialization.
|
||||
BigInteger::BigInteger(unsigned long x) : mag(x) { sign = mag.isZero() ? zero : positive; }
|
||||
BigInteger::BigInteger(unsigned int x) : mag(x) { sign = mag.isZero() ? zero : positive; }
|
||||
BigInteger::BigInteger(unsigned short x) : mag(x) { sign = mag.isZero() ? zero : positive; }
|
||||
|
||||
// For signed input, determine the desired magnitude and sign separately.
|
||||
|
||||
namespace {
|
||||
template <class X, class UX>
|
||||
BigInteger::Blk magOf(X x) {
|
||||
/* UX(...) cast needed to stop short(-2^15), which negates to
|
||||
* itself, from sign-extending in the conversion to Blk. */
|
||||
return BigInteger::Blk(x < 0 ? UX(-x) : x);
|
||||
}
|
||||
template <class X>
|
||||
BigInteger::Sign signOf(X x) {
|
||||
return (x == 0) ? BigInteger::zero
|
||||
: (x > 0) ? BigInteger::positive
|
||||
: BigInteger::negative;
|
||||
}
|
||||
}
|
||||
|
||||
BigInteger::BigInteger(long x) : sign(signOf(x)), mag(magOf<long , unsigned long >(x)) {}
|
||||
BigInteger::BigInteger(int x) : sign(signOf(x)), mag(magOf<int , unsigned int >(x)) {}
|
||||
BigInteger::BigInteger(short x) : sign(signOf(x)), mag(magOf<short, unsigned short>(x)) {}
|
||||
|
||||
// CONVERSION TO PRIMITIVE INTEGERS
|
||||
|
||||
/* Reuse BigUnsigned's conversion to an unsigned primitive integer.
|
||||
* The friend is a separate function rather than
|
||||
* BigInteger::convertToUnsignedPrimitive to avoid requiring BigUnsigned to
|
||||
* declare BigInteger. */
|
||||
template <class X>
|
||||
inline X convertBigUnsignedToPrimitiveAccess(const BigUnsigned &a) {
|
||||
return a.convertToPrimitive<X>();
|
||||
}
|
||||
|
||||
template <class X>
|
||||
X BigInteger::convertToUnsignedPrimitive() const {
|
||||
if (sign == negative)
|
||||
throw "BigInteger::to<Primitive>: "
|
||||
"Cannot convert a negative integer to an unsigned type";
|
||||
else
|
||||
return convertBigUnsignedToPrimitiveAccess<X>(mag);
|
||||
}
|
||||
|
||||
/* Similar to BigUnsigned::convertToPrimitive, but split into two cases for
|
||||
* nonnegative and negative numbers. */
|
||||
template <class X, class UX>
|
||||
X BigInteger::convertToSignedPrimitive() const {
|
||||
if (sign == zero)
|
||||
return 0;
|
||||
else if (mag.getLength() == 1) {
|
||||
// The single block might fit in an X. Try the conversion.
|
||||
Blk b = mag.getBlock(0);
|
||||
if (sign == positive) {
|
||||
X x = X(b);
|
||||
if (x >= 0 && Blk(x) == b)
|
||||
return x;
|
||||
} else {
|
||||
X x = -X(b);
|
||||
/* UX(...) needed to avoid rejecting conversion of
|
||||
* -2^15 to a short. */
|
||||
if (x < 0 && Blk(UX(-x)) == b)
|
||||
return x;
|
||||
}
|
||||
// Otherwise fall through.
|
||||
}
|
||||
throw "BigInteger::to<Primitive>: "
|
||||
"Value is too big to fit in the requested type";
|
||||
}
|
||||
|
||||
unsigned long BigInteger::toUnsignedLong () const { return convertToUnsignedPrimitive<unsigned long > (); }
|
||||
unsigned int BigInteger::toUnsignedInt () const { return convertToUnsignedPrimitive<unsigned int > (); }
|
||||
unsigned short BigInteger::toUnsignedShort() const { return convertToUnsignedPrimitive<unsigned short> (); }
|
||||
long BigInteger::toLong () const { return convertToSignedPrimitive <long , unsigned long> (); }
|
||||
int BigInteger::toInt () const { return convertToSignedPrimitive <int , unsigned int> (); }
|
||||
short BigInteger::toShort () const { return convertToSignedPrimitive <short, unsigned short>(); }
|
||||
|
||||
// COMPARISON
|
||||
BigInteger::CmpRes BigInteger::compareTo(const BigInteger &x) const {
|
||||
// A greater sign implies a greater number
|
||||
if (sign < x.sign)
|
||||
return less;
|
||||
else if (sign > x.sign)
|
||||
return greater;
|
||||
else switch (sign) {
|
||||
// If the signs are the same...
|
||||
case zero:
|
||||
return equal; // Two zeros are equal
|
||||
case positive:
|
||||
// Compare the magnitudes
|
||||
return mag.compareTo(x.mag);
|
||||
case negative:
|
||||
// Compare the magnitudes, but return the opposite result
|
||||
return CmpRes(-mag.compareTo(x.mag));
|
||||
default:
|
||||
throw "BigInteger internal error";
|
||||
}
|
||||
}
|
||||
|
||||
/* COPY-LESS OPERATIONS
|
||||
* These do some messing around to determine the sign of the result,
|
||||
* then call one of BigUnsigned's copy-less operations. */
|
||||
|
||||
// See remarks about aliased calls in BigUnsigned.cc .
|
||||
#define DTRT_ALIASED(cond, op) \
|
||||
if (cond) { \
|
||||
BigInteger tmpThis; \
|
||||
tmpThis.op; \
|
||||
*this = tmpThis; \
|
||||
return; \
|
||||
}
|
||||
|
||||
void BigInteger::add(const BigInteger &a, const BigInteger &b) {
|
||||
DTRT_ALIASED(this == &a || this == &b, add(a, b));
|
||||
// If one argument is zero, copy the other.
|
||||
if (a.sign == zero)
|
||||
operator =(b);
|
||||
else if (b.sign == zero)
|
||||
operator =(a);
|
||||
// If the arguments have the same sign, take the
|
||||
// common sign and add their magnitudes.
|
||||
else if (a.sign == b.sign) {
|
||||
sign = a.sign;
|
||||
mag.add(a.mag, b.mag);
|
||||
} else {
|
||||
// Otherwise, their magnitudes must be compared.
|
||||
switch (a.mag.compareTo(b.mag)) {
|
||||
case equal:
|
||||
// If their magnitudes are the same, copy zero.
|
||||
mag = 0;
|
||||
sign = zero;
|
||||
break;
|
||||
// Otherwise, take the sign of the greater, and subtract
|
||||
// the lesser magnitude from the greater magnitude.
|
||||
case greater:
|
||||
sign = a.sign;
|
||||
mag.subtract(a.mag, b.mag);
|
||||
break;
|
||||
case less:
|
||||
sign = b.sign;
|
||||
mag.subtract(b.mag, a.mag);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BigInteger::subtract(const BigInteger &a, const BigInteger &b) {
|
||||
// Notice that this routine is identical to BigInteger::add,
|
||||
// if one replaces b.sign by its opposite.
|
||||
DTRT_ALIASED(this == &a || this == &b, subtract(a, b));
|
||||
// If a is zero, copy b and flip its sign. If b is zero, copy a.
|
||||
if (a.sign == zero) {
|
||||
mag = b.mag;
|
||||
// Take the negative of _b_'s, sign, not ours.
|
||||
// Bug pointed out by Sam Larkin on 2005.03.30.
|
||||
sign = Sign(-b.sign);
|
||||
} else if (b.sign == zero)
|
||||
operator =(a);
|
||||
// If their signs differ, take a.sign and add the magnitudes.
|
||||
else if (a.sign != b.sign) {
|
||||
sign = a.sign;
|
||||
mag.add(a.mag, b.mag);
|
||||
} else {
|
||||
// Otherwise, their magnitudes must be compared.
|
||||
switch (a.mag.compareTo(b.mag)) {
|
||||
// If their magnitudes are the same, copy zero.
|
||||
case equal:
|
||||
mag = 0;
|
||||
sign = zero;
|
||||
break;
|
||||
// If a's magnitude is greater, take a.sign and
|
||||
// subtract a from b.
|
||||
case greater:
|
||||
sign = a.sign;
|
||||
mag.subtract(a.mag, b.mag);
|
||||
break;
|
||||
// If b's magnitude is greater, take the opposite
|
||||
// of b.sign and subtract b from a.
|
||||
case less:
|
||||
sign = Sign(-b.sign);
|
||||
mag.subtract(b.mag, a.mag);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BigInteger::multiply(const BigInteger &a, const BigInteger &b) {
|
||||
DTRT_ALIASED(this == &a || this == &b, multiply(a, b));
|
||||
// If one object is zero, copy zero and return.
|
||||
if (a.sign == zero || b.sign == zero) {
|
||||
sign = zero;
|
||||
mag = 0;
|
||||
return;
|
||||
}
|
||||
// If the signs of the arguments are the same, the result
|
||||
// is positive, otherwise it is negative.
|
||||
sign = (a.sign == b.sign) ? positive : negative;
|
||||
// Multiply the magnitudes.
|
||||
mag.multiply(a.mag, b.mag);
|
||||
}
|
||||
|
||||
/*
|
||||
* DIVISION WITH REMAINDER
|
||||
* Please read the comments before the definition of
|
||||
* `BigUnsigned::divideWithRemainder' in `BigUnsigned.cc' for lots of
|
||||
* information you should know before reading this function.
|
||||
*
|
||||
* Following Knuth, I decree that x / y is to be
|
||||
* 0 if y==0 and floor(real-number x / y) if y!=0.
|
||||
* Then x % y shall be x - y*(integer x / y).
|
||||
*
|
||||
* Note that x = y * (x / y) + (x % y) always holds.
|
||||
* In addition, (x % y) is from 0 to y - 1 if y > 0,
|
||||
* and from -(|y| - 1) to 0 if y < 0. (x % y) = x if y = 0.
|
||||
*
|
||||
* Examples: (q = a / b, r = a % b)
|
||||
* a b q r
|
||||
* === === === ===
|
||||
* 4 3 1 1
|
||||
* -4 3 -2 2
|
||||
* 4 -3 -2 -2
|
||||
* -4 -3 1 -1
|
||||
*/
|
||||
void BigInteger::divideWithRemainder(const BigInteger &b, BigInteger &q) {
|
||||
// Defend against aliased calls;
|
||||
// same idea as in BigUnsigned::divideWithRemainder .
|
||||
if (this == &q)
|
||||
throw "BigInteger::divideWithRemainder: Cannot write quotient and remainder into the same variable";
|
||||
if (this == &b || &q == &b) {
|
||||
BigInteger tmpB(b);
|
||||
divideWithRemainder(tmpB, q);
|
||||
return;
|
||||
}
|
||||
|
||||
// Division by zero gives quotient 0 and remainder *this
|
||||
if (b.sign == zero) {
|
||||
q.mag = 0;
|
||||
q.sign = zero;
|
||||
return;
|
||||
}
|
||||
// 0 / b gives quotient 0 and remainder 0
|
||||
if (sign == zero) {
|
||||
q.mag = 0;
|
||||
q.sign = zero;
|
||||
return;
|
||||
}
|
||||
|
||||
// Here *this != 0, b != 0.
|
||||
|
||||
// Do the operands have the same sign?
|
||||
if (sign == b.sign) {
|
||||
// Yes: easy case. Quotient is zero or positive.
|
||||
q.sign = positive;
|
||||
} else {
|
||||
// No: harder case. Quotient is negative.
|
||||
q.sign = negative;
|
||||
// Decrease the magnitude of the dividend by one.
|
||||
mag--;
|
||||
/*
|
||||
* We tinker with the dividend before and with the
|
||||
* quotient and remainder after so that the result
|
||||
* comes out right. To see why it works, consider the following
|
||||
* list of examples, where A is the magnitude-decreased
|
||||
* a, Q and R are the results of BigUnsigned division
|
||||
* with remainder on A and |b|, and q and r are the
|
||||
* final results we want:
|
||||
*
|
||||
* a A b Q R q r
|
||||
* -3 -2 3 0 2 -1 0
|
||||
* -4 -3 3 1 0 -2 2
|
||||
* -5 -4 3 1 1 -2 1
|
||||
* -6 -5 3 1 2 -2 0
|
||||
*
|
||||
* It appears that we need a total of 3 corrections:
|
||||
* Decrease the magnitude of a to get A. Increase the
|
||||
* magnitude of Q to get q (and make it negative).
|
||||
* Find r = (b - 1) - R and give it the desired sign.
|
||||
*/
|
||||
}
|
||||
|
||||
// Divide the magnitudes.
|
||||
mag.divideWithRemainder(b.mag, q.mag);
|
||||
|
||||
if (sign != b.sign) {
|
||||
// More for the harder case (as described):
|
||||
// Increase the magnitude of the quotient by one.
|
||||
q.mag++;
|
||||
// Modify the remainder.
|
||||
mag.subtract(b.mag, mag);
|
||||
mag--;
|
||||
}
|
||||
|
||||
// Sign of the remainder is always the sign of the divisor b.
|
||||
sign = b.sign;
|
||||
|
||||
// Set signs to zero as necessary. (Thanks David Allen!)
|
||||
if (mag.isZero())
|
||||
sign = zero;
|
||||
if (q.mag.isZero())
|
||||
q.sign = zero;
|
||||
|
||||
// WHEW!!!
|
||||
}
|
||||
|
||||
// Negation
|
||||
void BigInteger::negate(const BigInteger &a) {
|
||||
DTRT_ALIASED(this == &a, negate(a));
|
||||
// Copy a's magnitude
|
||||
mag = a.mag;
|
||||
// Copy the opposite of a.sign
|
||||
sign = Sign(-a.sign);
|
||||
}
|
||||
|
||||
// INCREMENT/DECREMENT OPERATORS
|
||||
|
||||
// Prefix increment
|
||||
void BigInteger::operator ++() {
|
||||
if (sign == negative) {
|
||||
mag--;
|
||||
if (mag == 0)
|
||||
sign = zero;
|
||||
} else {
|
||||
mag++;
|
||||
sign = positive; // if not already
|
||||
}
|
||||
}
|
||||
|
||||
// Postfix increment: same as prefix
|
||||
void BigInteger::operator ++(int) {
|
||||
operator ++();
|
||||
}
|
||||
|
||||
// Prefix decrement
|
||||
void BigInteger::operator --() {
|
||||
if (sign == positive) {
|
||||
mag--;
|
||||
if (mag == 0)
|
||||
sign = zero;
|
||||
} else {
|
||||
mag++;
|
||||
sign = negative;
|
||||
}
|
||||
}
|
||||
|
||||
// Postfix decrement: same as prefix
|
||||
void BigInteger::operator --(int) {
|
||||
operator --();
|
||||
}
|
||||
|
|
@ -1,215 +0,0 @@
|
|||
#ifndef BIGINTEGER_H
|
||||
#define BIGINTEGER_H
|
||||
|
||||
#include "BigUnsigned.hh"
|
||||
|
||||
/* A BigInteger object represents a signed integer of size limited only by
|
||||
* available memory. BigUnsigneds support most mathematical operators and can
|
||||
* be converted to and from most primitive integer types.
|
||||
*
|
||||
* A BigInteger is just an aggregate of a BigUnsigned and a sign. (It is no
|
||||
* longer derived from BigUnsigned because that led to harmful implicit
|
||||
* conversions.) */
|
||||
class BigInteger {
|
||||
|
||||
public:
|
||||
typedef BigUnsigned::Blk Blk;
|
||||
typedef BigUnsigned::Index Index;
|
||||
typedef BigUnsigned::CmpRes CmpRes;
|
||||
static const CmpRes
|
||||
less = BigUnsigned::less ,
|
||||
equal = BigUnsigned::equal ,
|
||||
greater = BigUnsigned::greater;
|
||||
// Enumeration for the sign of a BigInteger.
|
||||
enum Sign { negative = -1, zero = 0, positive = 1 };
|
||||
|
||||
protected:
|
||||
Sign sign;
|
||||
BigUnsigned mag;
|
||||
|
||||
public:
|
||||
// Constructs zero.
|
||||
BigInteger() : sign(zero), mag() {}
|
||||
|
||||
// Copy constructor
|
||||
BigInteger(const BigInteger &x) : sign(x.sign), mag(x.mag) {};
|
||||
|
||||
// Assignment operator
|
||||
void operator=(const BigInteger &x);
|
||||
|
||||
// Constructor that copies from a given array of blocks with a sign.
|
||||
BigInteger(const Blk *b, Index blen, Sign s);
|
||||
|
||||
// Nonnegative constructor that copies from a given array of blocks.
|
||||
BigInteger(const Blk *b, Index blen) : mag(b, blen) {
|
||||
sign = mag.isZero() ? zero : positive;
|
||||
}
|
||||
|
||||
// Constructor from a BigUnsigned and a sign
|
||||
BigInteger(const BigUnsigned &x, Sign s);
|
||||
|
||||
// Nonnegative constructor from a BigUnsigned
|
||||
BigInteger(const BigUnsigned &x) : mag(x) {
|
||||
sign = mag.isZero() ? zero : positive;
|
||||
}
|
||||
|
||||
// Constructors from primitive integer types
|
||||
BigInteger(unsigned long x);
|
||||
BigInteger( long x);
|
||||
BigInteger(unsigned int x);
|
||||
BigInteger( int x);
|
||||
BigInteger(unsigned short x);
|
||||
BigInteger( short x);
|
||||
|
||||
/* Converters to primitive integer types
|
||||
* The implicit conversion operators caused trouble, so these are now
|
||||
* named. */
|
||||
unsigned long toUnsignedLong () const;
|
||||
long toLong () const;
|
||||
unsigned int toUnsignedInt () const;
|
||||
int toInt () const;
|
||||
unsigned short toUnsignedShort() const;
|
||||
short toShort () const;
|
||||
protected:
|
||||
// Helper
|
||||
template <class X> X convertToUnsignedPrimitive() const;
|
||||
template <class X, class UX> X convertToSignedPrimitive() const;
|
||||
public:
|
||||
|
||||
// ACCESSORS
|
||||
Sign getSign() const { return sign; }
|
||||
/* The client can't do any harm by holding a read-only reference to the
|
||||
* magnitude. */
|
||||
const BigUnsigned &getMagnitude() const { return mag; }
|
||||
|
||||
// Some accessors that go through to the magnitude
|
||||
Index getLength() const { return mag.getLength(); }
|
||||
Index getCapacity() const { return mag.getCapacity(); }
|
||||
Blk getBlock(Index i) const { return mag.getBlock(i); }
|
||||
bool isZero() const { return sign == zero; } // A bit special
|
||||
|
||||
// COMPARISONS
|
||||
|
||||
// Compares this to x like Perl's <=>
|
||||
CmpRes compareTo(const BigInteger &x) const;
|
||||
|
||||
// Ordinary comparison operators
|
||||
bool operator ==(const BigInteger &x) const {
|
||||
return sign == x.sign && mag == x.mag;
|
||||
}
|
||||
bool operator !=(const BigInteger &x) const { return !operator ==(x); };
|
||||
bool operator < (const BigInteger &x) const { return compareTo(x) == less ; }
|
||||
bool operator <=(const BigInteger &x) const { return compareTo(x) != greater; }
|
||||
bool operator >=(const BigInteger &x) const { return compareTo(x) != less ; }
|
||||
bool operator > (const BigInteger &x) const { return compareTo(x) == greater; }
|
||||
|
||||
// OPERATORS -- See the discussion in BigUnsigned.hh.
|
||||
void add (const BigInteger &a, const BigInteger &b);
|
||||
void subtract(const BigInteger &a, const BigInteger &b);
|
||||
void multiply(const BigInteger &a, const BigInteger &b);
|
||||
/* See the comment on BigUnsigned::divideWithRemainder. Semantics
|
||||
* differ from those of primitive integers when negatives and/or zeros
|
||||
* are involved. */
|
||||
void divideWithRemainder(const BigInteger &b, BigInteger &q);
|
||||
void negate(const BigInteger &a);
|
||||
|
||||
/* Bitwise operators are not provided for BigIntegers. Use
|
||||
* getMagnitude to get the magnitude and operate on that instead. */
|
||||
|
||||
BigInteger operator +(const BigInteger &x) const;
|
||||
BigInteger operator -(const BigInteger &x) const;
|
||||
BigInteger operator *(const BigInteger &x) const;
|
||||
BigInteger operator /(const BigInteger &x) const;
|
||||
BigInteger operator %(const BigInteger &x) const;
|
||||
BigInteger operator -() const;
|
||||
|
||||
void operator +=(const BigInteger &x);
|
||||
void operator -=(const BigInteger &x);
|
||||
void operator *=(const BigInteger &x);
|
||||
void operator /=(const BigInteger &x);
|
||||
void operator %=(const BigInteger &x);
|
||||
void flipSign();
|
||||
|
||||
// INCREMENT/DECREMENT OPERATORS
|
||||
void operator ++( );
|
||||
void operator ++(int);
|
||||
void operator --( );
|
||||
void operator --(int);
|
||||
};
|
||||
|
||||
// NORMAL OPERATORS
|
||||
/* These create an object to hold the result and invoke
|
||||
* the appropriate put-here operation on it, passing
|
||||
* this and x. The new object is then returned. */
|
||||
inline BigInteger BigInteger::operator +(const BigInteger &x) const {
|
||||
BigInteger ans;
|
||||
ans.add(*this, x);
|
||||
return ans;
|
||||
}
|
||||
inline BigInteger BigInteger::operator -(const BigInteger &x) const {
|
||||
BigInteger ans;
|
||||
ans.subtract(*this, x);
|
||||
return ans;
|
||||
}
|
||||
inline BigInteger BigInteger::operator *(const BigInteger &x) const {
|
||||
BigInteger ans;
|
||||
ans.multiply(*this, x);
|
||||
return ans;
|
||||
}
|
||||
inline BigInteger BigInteger::operator /(const BigInteger &x) const {
|
||||
if (x.isZero()) throw "BigInteger::operator /: division by zero";
|
||||
BigInteger q, r;
|
||||
r = *this;
|
||||
r.divideWithRemainder(x, q);
|
||||
return q;
|
||||
}
|
||||
inline BigInteger BigInteger::operator %(const BigInteger &x) const {
|
||||
if (x.isZero()) throw "BigInteger::operator %: division by zero";
|
||||
BigInteger q, r;
|
||||
r = *this;
|
||||
r.divideWithRemainder(x, q);
|
||||
return r;
|
||||
}
|
||||
inline BigInteger BigInteger::operator -() const {
|
||||
BigInteger ans;
|
||||
ans.negate(*this);
|
||||
return ans;
|
||||
}
|
||||
|
||||
/*
|
||||
* ASSIGNMENT OPERATORS
|
||||
*
|
||||
* Now the responsibility for making a temporary copy if necessary
|
||||
* belongs to the put-here operations. See Assignment Operators in
|
||||
* BigUnsigned.hh.
|
||||
*/
|
||||
inline void BigInteger::operator +=(const BigInteger &x) {
|
||||
add(*this, x);
|
||||
}
|
||||
inline void BigInteger::operator -=(const BigInteger &x) {
|
||||
subtract(*this, x);
|
||||
}
|
||||
inline void BigInteger::operator *=(const BigInteger &x) {
|
||||
multiply(*this, x);
|
||||
}
|
||||
inline void BigInteger::operator /=(const BigInteger &x) {
|
||||
if (x.isZero()) throw "BigInteger::operator /=: division by zero";
|
||||
/* The following technique is slightly faster than copying *this first
|
||||
* when x is large. */
|
||||
BigInteger q;
|
||||
divideWithRemainder(x, q);
|
||||
// *this contains the remainder, but we overwrite it with the quotient.
|
||||
*this = q;
|
||||
}
|
||||
inline void BigInteger::operator %=(const BigInteger &x) {
|
||||
if (x.isZero()) throw "BigInteger::operator %=: division by zero";
|
||||
BigInteger q;
|
||||
// Mods *this by x. Don't care about quotient left in q.
|
||||
divideWithRemainder(x, q);
|
||||
}
|
||||
// This one is trivial
|
||||
inline void BigInteger::flipSign() {
|
||||
sign = Sign(-sign);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,70 +0,0 @@
|
|||
#include "BigIntegerAlgorithms.hh"
|
||||
|
||||
BigUnsigned gcd(BigUnsigned a, BigUnsigned b) {
|
||||
BigUnsigned trash;
|
||||
// Neat in-place alternating technique.
|
||||
for (;;) {
|
||||
if (b.isZero())
|
||||
return a;
|
||||
a.divideWithRemainder(b, trash);
|
||||
if (a.isZero())
|
||||
return b;
|
||||
b.divideWithRemainder(a, trash);
|
||||
}
|
||||
}
|
||||
|
||||
void extendedEuclidean(BigInteger m, BigInteger n,
|
||||
BigInteger &g, BigInteger &r, BigInteger &s) {
|
||||
if (&g == &r || &g == &s || &r == &s)
|
||||
throw "BigInteger extendedEuclidean: Outputs are aliased";
|
||||
BigInteger r1(1), s1(0), r2(0), s2(1), q;
|
||||
/* Invariants:
|
||||
* r1*m(orig) + s1*n(orig) == m(current)
|
||||
* r2*m(orig) + s2*n(orig) == n(current) */
|
||||
for (;;) {
|
||||
if (n.isZero()) {
|
||||
r = r1; s = s1; g = m;
|
||||
return;
|
||||
}
|
||||
// Subtract q times the second invariant from the first invariant.
|
||||
m.divideWithRemainder(n, q);
|
||||
r1 -= q*r2; s1 -= q*s2;
|
||||
|
||||
if (m.isZero()) {
|
||||
r = r2; s = s2; g = n;
|
||||
return;
|
||||
}
|
||||
// Subtract q times the first invariant from the second invariant.
|
||||
n.divideWithRemainder(m, q);
|
||||
r2 -= q*r1; s2 -= q*s1;
|
||||
}
|
||||
}
|
||||
|
||||
BigUnsigned modinv(const BigInteger &x, const BigUnsigned &n) {
|
||||
BigInteger g, r, s;
|
||||
extendedEuclidean(x, n, g, r, s);
|
||||
if (g == 1)
|
||||
// r*x + s*n == 1, so r*x === 1 (mod n), so r is the answer.
|
||||
return (r % n).getMagnitude(); // (r % n) will be nonnegative
|
||||
else
|
||||
throw "BigInteger modinv: x and n have a common factor";
|
||||
}
|
||||
|
||||
BigUnsigned modexp(const BigInteger &base, const BigUnsigned &exponent,
|
||||
const BigUnsigned &modulus) {
|
||||
BigUnsigned ans = 1, base2 = (base % modulus).getMagnitude();
|
||||
BigUnsigned::Index i = exponent.bitLength();
|
||||
// For each bit of the exponent, most to least significant...
|
||||
while (i > 0) {
|
||||
i--;
|
||||
// Square.
|
||||
ans *= ans;
|
||||
ans %= modulus;
|
||||
// And multiply if the bit is a 1.
|
||||
if (exponent.getBit(i)) {
|
||||
ans *= base2;
|
||||
ans %= modulus;
|
||||
}
|
||||
}
|
||||
return ans;
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
#ifndef BIGINTEGERALGORITHMS_H
|
||||
#define BIGINTEGERALGORITHMS_H
|
||||
|
||||
#include "BigInteger.hh"
|
||||
|
||||
/* Some mathematical algorithms for big integers.
|
||||
* This code is new and, as such, experimental. */
|
||||
|
||||
// Returns the greatest common divisor of a and b.
|
||||
BigUnsigned gcd(BigUnsigned a, BigUnsigned b);
|
||||
|
||||
/* Extended Euclidean algorithm.
|
||||
* Given m and n, finds gcd g and numbers r, s such that r*m + s*n == g. */
|
||||
void extendedEuclidean(BigInteger m, BigInteger n,
|
||||
BigInteger &g, BigInteger &r, BigInteger &s);
|
||||
|
||||
/* Returns the multiplicative inverse of x modulo n, or throws an exception if
|
||||
* they have a common factor. */
|
||||
BigUnsigned modinv(const BigInteger &x, const BigUnsigned &n);
|
||||
|
||||
// Returns (base ^ exponent) % modulus.
|
||||
BigUnsigned modexp(const BigInteger &base, const BigUnsigned &exponent,
|
||||
const BigUnsigned &modulus);
|
||||
|
||||
#endif
|
|
@ -1,8 +0,0 @@
|
|||
// This header file includes all of the library header files.
|
||||
|
||||
#include "NumberlikeArray.hh"
|
||||
#include "BigUnsigned.hh"
|
||||
#include "BigInteger.hh"
|
||||
#include "BigIntegerAlgorithms.hh"
|
||||
#include "BigUnsignedInABase.hh"
|
||||
#include "BigIntegerUtils.hh"
|
|
@ -1,50 +0,0 @@
|
|||
#include "BigIntegerUtils.hh"
|
||||
#include "BigUnsignedInABase.hh"
|
||||
|
||||
std::string bigUnsignedToString(const BigUnsigned &x) {
|
||||
return std::string(BigUnsignedInABase(x, 10));
|
||||
}
|
||||
|
||||
std::string bigIntegerToString(const BigInteger &x) {
|
||||
return (x.getSign() == BigInteger::negative)
|
||||
? (std::string("-") + bigUnsignedToString(x.getMagnitude()))
|
||||
: (bigUnsignedToString(x.getMagnitude()));
|
||||
}
|
||||
|
||||
BigUnsigned stringToBigUnsigned(const std::string &s) {
|
||||
return BigUnsigned(BigUnsignedInABase(s, 10));
|
||||
}
|
||||
|
||||
BigInteger stringToBigInteger(const std::string &s) {
|
||||
// Recognize a sign followed by a BigUnsigned.
|
||||
return (s[0] == '-') ? BigInteger(stringToBigUnsigned(s.substr(1, s.length() - 1)), BigInteger::negative)
|
||||
: (s[0] == '+') ? BigInteger(stringToBigUnsigned(s.substr(1, s.length() - 1)))
|
||||
: BigInteger(stringToBigUnsigned(s));
|
||||
}
|
||||
|
||||
std::ostream &operator <<(std::ostream &os, const BigUnsigned &x) {
|
||||
BigUnsignedInABase::Base base;
|
||||
long osFlags = os.flags();
|
||||
if (osFlags & os.dec)
|
||||
base = 10;
|
||||
else if (osFlags & os.hex) {
|
||||
base = 16;
|
||||
if (osFlags & os.showbase)
|
||||
os << "0x";
|
||||
} else if (osFlags & os.oct) {
|
||||
base = 8;
|
||||
if (osFlags & os.showbase)
|
||||
os << '0';
|
||||
} else
|
||||
throw "std::ostream << BigUnsigned: Could not determine the desired base from output-stream flags";
|
||||
std::string s = std::string(BigUnsignedInABase(x, base));
|
||||
os << s;
|
||||
return os;
|
||||
}
|
||||
|
||||
std::ostream &operator <<(std::ostream &os, const BigInteger &x) {
|
||||
if (x.getSign() == BigInteger::negative)
|
||||
os << '-';
|
||||
os << x.getMagnitude();
|
||||
return os;
|
||||
}
|
|
@ -1,72 +0,0 @@
|
|||
#ifndef BIGINTEGERUTILS_H
|
||||
#define BIGINTEGERUTILS_H
|
||||
|
||||
#include "BigInteger.hh"
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
/* This file provides:
|
||||
* - Convenient std::string <-> BigUnsigned/BigInteger conversion routines
|
||||
* - std::ostream << operators for BigUnsigned/BigInteger */
|
||||
|
||||
// std::string conversion routines. Base 10 only.
|
||||
std::string bigUnsignedToString(const BigUnsigned &x);
|
||||
std::string bigIntegerToString(const BigInteger &x);
|
||||
BigUnsigned stringToBigUnsigned(const std::string &s);
|
||||
BigInteger stringToBigInteger(const std::string &s);
|
||||
|
||||
// Creates a BigInteger from data such as `char's; read below for details.
|
||||
template <class T>
|
||||
BigInteger dataToBigInteger(const T* data, BigInteger::Index length, BigInteger::Sign sign);
|
||||
|
||||
// Outputs x to os, obeying the flags `dec', `hex', `bin', and `showbase'.
|
||||
std::ostream &operator <<(std::ostream &os, const BigUnsigned &x);
|
||||
|
||||
// Outputs x to os, obeying the flags `dec', `hex', `bin', and `showbase'.
|
||||
// My somewhat arbitrary policy: a negative sign comes before a base indicator (like -0xFF).
|
||||
std::ostream &operator <<(std::ostream &os, const BigInteger &x);
|
||||
|
||||
// BEGIN TEMPLATE DEFINITIONS.
|
||||
|
||||
/*
|
||||
* Converts binary data to a BigInteger.
|
||||
* Pass an array `data', its length, and the desired sign.
|
||||
*
|
||||
* Elements of `data' may be of any type `T' that has the following
|
||||
* two properties (this includes almost all integral types):
|
||||
*
|
||||
* (1) `sizeof(T)' correctly gives the amount of binary data in one
|
||||
* value of `T' and is a factor of `sizeof(Blk)'.
|
||||
*
|
||||
* (2) When a value of `T' is casted to a `Blk', the low bytes of
|
||||
* the result contain the desired binary data.
|
||||
*/
|
||||
template <class T>
|
||||
BigInteger dataToBigInteger(const T* data, BigInteger::Index length, BigInteger::Sign sign) {
|
||||
// really ceiling(numBytes / sizeof(BigInteger::Blk))
|
||||
unsigned int pieceSizeInBits = 8 * sizeof(T);
|
||||
unsigned int piecesPerBlock = sizeof(BigInteger::Blk) / sizeof(T);
|
||||
unsigned int numBlocks = (length + piecesPerBlock - 1) / piecesPerBlock;
|
||||
|
||||
// Allocate our block array
|
||||
BigInteger::Blk *blocks = new BigInteger::Blk[numBlocks];
|
||||
|
||||
BigInteger::Index blockNum, pieceNum, pieceNumHere;
|
||||
|
||||
// Convert
|
||||
for (blockNum = 0, pieceNum = 0; blockNum < numBlocks; blockNum++) {
|
||||
BigInteger::Blk curBlock = 0;
|
||||
for (pieceNumHere = 0; pieceNumHere < piecesPerBlock && pieceNum < length;
|
||||
pieceNumHere++, pieceNum++)
|
||||
curBlock |= (BigInteger::Blk(data[pieceNum]) << (pieceSizeInBits * pieceNumHere));
|
||||
blocks[blockNum] = curBlock;
|
||||
}
|
||||
|
||||
// Create the BigInteger.
|
||||
BigInteger x(blocks, numBlocks, sign);
|
||||
|
||||
delete [] blocks;
|
||||
return x;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,697 +0,0 @@
|
|||
#include "BigUnsigned.hh"
|
||||
|
||||
// Memory management definitions have moved to the bottom of NumberlikeArray.hh.
|
||||
|
||||
// The templates used by these constructors and converters are at the bottom of
|
||||
// BigUnsigned.hh.
|
||||
|
||||
BigUnsigned::BigUnsigned(unsigned long x) { initFromPrimitive (x); }
|
||||
BigUnsigned::BigUnsigned(unsigned int x) { initFromPrimitive (x); }
|
||||
BigUnsigned::BigUnsigned(unsigned short x) { initFromPrimitive (x); }
|
||||
BigUnsigned::BigUnsigned( long x) { initFromSignedPrimitive(x); }
|
||||
BigUnsigned::BigUnsigned( int x) { initFromSignedPrimitive(x); }
|
||||
BigUnsigned::BigUnsigned( short x) { initFromSignedPrimitive(x); }
|
||||
|
||||
unsigned long BigUnsigned::toUnsignedLong () const { return convertToPrimitive <unsigned long >(); }
|
||||
unsigned int BigUnsigned::toUnsignedInt () const { return convertToPrimitive <unsigned int >(); }
|
||||
unsigned short BigUnsigned::toUnsignedShort() const { return convertToPrimitive <unsigned short>(); }
|
||||
long BigUnsigned::toLong () const { return convertToSignedPrimitive< long >(); }
|
||||
int BigUnsigned::toInt () const { return convertToSignedPrimitive< int >(); }
|
||||
short BigUnsigned::toShort () const { return convertToSignedPrimitive< short>(); }
|
||||
|
||||
// BIT/BLOCK ACCESSORS
|
||||
|
||||
void BigUnsigned::setBlock(Index i, Blk newBlock) {
|
||||
if (newBlock == 0) {
|
||||
if (i < len) {
|
||||
blk[i] = 0;
|
||||
zapLeadingZeros();
|
||||
}
|
||||
// If i >= len, no effect.
|
||||
} else {
|
||||
if (i >= len) {
|
||||
// The nonzero block extends the number.
|
||||
allocateAndCopy(i+1);
|
||||
// Zero any added blocks that we aren't setting.
|
||||
for (Index j = len; j < i; j++)
|
||||
blk[j] = 0;
|
||||
len = i+1;
|
||||
}
|
||||
blk[i] = newBlock;
|
||||
}
|
||||
}
|
||||
|
||||
/* Evidently the compiler wants BigUnsigned:: on the return type because, at
|
||||
* that point, it hasn't yet parsed the BigUnsigned:: on the name to get the
|
||||
* proper scope. */
|
||||
BigUnsigned::Index BigUnsigned::bitLength() const {
|
||||
if (isZero())
|
||||
return 0;
|
||||
else {
|
||||
Blk leftmostBlock = getBlock(len - 1);
|
||||
Index leftmostBlockLen = 0;
|
||||
while (leftmostBlock != 0) {
|
||||
leftmostBlock >>= 1;
|
||||
leftmostBlockLen++;
|
||||
}
|
||||
return leftmostBlockLen + (len - 1) * N;
|
||||
}
|
||||
}
|
||||
|
||||
void BigUnsigned::setBit(Index bi, bool newBit) {
|
||||
Index blockI = bi / N;
|
||||
Blk block = getBlock(blockI), mask = Blk(1) << (bi % N);
|
||||
block = newBit ? (block | mask) : (block & ~mask);
|
||||
setBlock(blockI, block);
|
||||
}
|
||||
|
||||
// COMPARISON
|
||||
BigUnsigned::CmpRes BigUnsigned::compareTo(const BigUnsigned &x) const {
|
||||
// A bigger length implies a bigger number.
|
||||
if (len < x.len)
|
||||
return less;
|
||||
else if (len > x.len)
|
||||
return greater;
|
||||
else {
|
||||
// Compare blocks one by one from left to right.
|
||||
Index i = len;
|
||||
while (i > 0) {
|
||||
i--;
|
||||
if (blk[i] == x.blk[i])
|
||||
continue;
|
||||
else if (blk[i] > x.blk[i])
|
||||
return greater;
|
||||
else
|
||||
return less;
|
||||
}
|
||||
// If no blocks differed, the numbers are equal.
|
||||
return equal;
|
||||
}
|
||||
}
|
||||
|
||||
// COPY-LESS OPERATIONS
|
||||
|
||||
/*
|
||||
* On most calls to copy-less operations, it's safe to read the inputs little by
|
||||
* little and write the outputs little by little. However, if one of the
|
||||
* inputs is coming from the same variable into which the output is to be
|
||||
* stored (an "aliased" call), we risk overwriting the input before we read it.
|
||||
* In this case, we first compute the result into a temporary BigUnsigned
|
||||
* variable and then copy it into the requested output variable *this.
|
||||
* Each put-here operation uses the DTRT_ALIASED macro (Do The Right Thing on
|
||||
* aliased calls) to generate code for this check.
|
||||
*
|
||||
* I adopted this approach on 2007.02.13 (see Assignment Operators in
|
||||
* BigUnsigned.hh). Before then, put-here operations rejected aliased calls
|
||||
* with an exception. I think doing the right thing is better.
|
||||
*
|
||||
* Some of the put-here operations can probably handle aliased calls safely
|
||||
* without the extra copy because (for example) they process blocks strictly
|
||||
* right-to-left. At some point I might determine which ones don't need the
|
||||
* copy, but my reasoning would need to be verified very carefully. For now
|
||||
* I'll leave in the copy.
|
||||
*/
|
||||
#define DTRT_ALIASED(cond, op) \
|
||||
if (cond) { \
|
||||
BigUnsigned tmpThis; \
|
||||
tmpThis.op; \
|
||||
*this = tmpThis; \
|
||||
return; \
|
||||
}
|
||||
|
||||
|
||||
|
||||
void BigUnsigned::add(const BigUnsigned &a, const BigUnsigned &b) {
|
||||
DTRT_ALIASED(this == &a || this == &b, add(a, b));
|
||||
// If one argument is zero, copy the other.
|
||||
if (a.len == 0) {
|
||||
operator =(b);
|
||||
return;
|
||||
} else if (b.len == 0) {
|
||||
operator =(a);
|
||||
return;
|
||||
}
|
||||
// Some variables...
|
||||
// Carries in and out of an addition stage
|
||||
bool carryIn, carryOut;
|
||||
Blk temp;
|
||||
Index i;
|
||||
// a2 points to the longer input, b2 points to the shorter
|
||||
const BigUnsigned *a2, *b2;
|
||||
if (a.len >= b.len) {
|
||||
a2 = &a;
|
||||
b2 = &b;
|
||||
} else {
|
||||
a2 = &b;
|
||||
b2 = &a;
|
||||
}
|
||||
// Set prelimiary length and make room in this BigUnsigned
|
||||
len = a2->len + 1;
|
||||
allocate(len);
|
||||
// For each block index that is present in both inputs...
|
||||
for (i = 0, carryIn = false; i < b2->len; i++) {
|
||||
// Add input blocks
|
||||
temp = a2->blk[i] + b2->blk[i];
|
||||
// If a rollover occurred, the result is less than either input.
|
||||
// This test is used many times in the BigUnsigned code.
|
||||
carryOut = (temp < a2->blk[i]);
|
||||
// If a carry was input, handle it
|
||||
if (carryIn) {
|
||||
temp++;
|
||||
carryOut |= (temp == 0);
|
||||
}
|
||||
blk[i] = temp; // Save the addition result
|
||||
carryIn = carryOut; // Pass the carry along
|
||||
}
|
||||
// If there is a carry left over, increase blocks until
|
||||
// one does not roll over.
|
||||
for (; i < a2->len && carryIn; i++) {
|
||||
temp = a2->blk[i] + 1;
|
||||
carryIn = (temp == 0);
|
||||
blk[i] = temp;
|
||||
}
|
||||
// If the carry was resolved but the larger number
|
||||
// still has blocks, copy them over.
|
||||
for (; i < a2->len; i++)
|
||||
blk[i] = a2->blk[i];
|
||||
// Set the extra block if there's still a carry, decrease length otherwise
|
||||
if (carryIn)
|
||||
blk[i] = 1;
|
||||
else
|
||||
len--;
|
||||
}
|
||||
|
||||
void BigUnsigned::subtract(const BigUnsigned &a, const BigUnsigned &b) {
|
||||
DTRT_ALIASED(this == &a || this == &b, subtract(a, b));
|
||||
if (b.len == 0) {
|
||||
// If b is zero, copy a.
|
||||
operator =(a);
|
||||
return;
|
||||
} else if (a.len < b.len)
|
||||
// If a is shorter than b, the result is negative.
|
||||
throw "BigUnsigned::subtract: "
|
||||
"Negative result in unsigned calculation";
|
||||
// Some variables...
|
||||
bool borrowIn, borrowOut;
|
||||
Blk temp;
|
||||
Index i;
|
||||
// Set preliminary length and make room
|
||||
len = a.len;
|
||||
allocate(len);
|
||||
// For each block index that is present in both inputs...
|
||||
for (i = 0, borrowIn = false; i < b.len; i++) {
|
||||
temp = a.blk[i] - b.blk[i];
|
||||
// If a reverse rollover occurred,
|
||||
// the result is greater than the block from a.
|
||||
borrowOut = (temp > a.blk[i]);
|
||||
// Handle an incoming borrow
|
||||
if (borrowIn) {
|
||||
borrowOut |= (temp == 0);
|
||||
temp--;
|
||||
}
|
||||
blk[i] = temp; // Save the subtraction result
|
||||
borrowIn = borrowOut; // Pass the borrow along
|
||||
}
|
||||
// If there is a borrow left over, decrease blocks until
|
||||
// one does not reverse rollover.
|
||||
for (; i < a.len && borrowIn; i++) {
|
||||
borrowIn = (a.blk[i] == 0);
|
||||
blk[i] = a.blk[i] - 1;
|
||||
}
|
||||
/* If there's still a borrow, the result is negative.
|
||||
* Throw an exception, but zero out this object so as to leave it in a
|
||||
* predictable state. */
|
||||
if (borrowIn) {
|
||||
len = 0;
|
||||
throw "BigUnsigned::subtract: Negative result in unsigned calculation";
|
||||
} else
|
||||
// Copy over the rest of the blocks
|
||||
for (; i < a.len; i++)
|
||||
blk[i] = a.blk[i];
|
||||
// Zap leading zeros
|
||||
zapLeadingZeros();
|
||||
}
|
||||
|
||||
/*
|
||||
* About the multiplication and division algorithms:
|
||||
*
|
||||
* I searched unsucessfully for fast C++ built-in operations like the `b_0'
|
||||
* and `c_0' Knuth describes in Section 4.3.1 of ``The Art of Computer
|
||||
* Programming'' (replace `place' by `Blk'):
|
||||
*
|
||||
* ``b_0[:] multiplication of a one-place integer by another one-place
|
||||
* integer, giving a two-place answer;
|
||||
*
|
||||
* ``c_0[:] division of a two-place integer by a one-place integer,
|
||||
* provided that the quotient is a one-place integer, and yielding
|
||||
* also a one-place remainder.''
|
||||
*
|
||||
* I also missed his note that ``[b]y adjusting the word size, if
|
||||
* necessary, nearly all computers will have these three operations
|
||||
* available'', so I gave up on trying to use algorithms similar to his.
|
||||
* A future version of the library might include such algorithms; I
|
||||
* would welcome contributions from others for this.
|
||||
*
|
||||
* I eventually decided to use bit-shifting algorithms. To multiply `a'
|
||||
* and `b', we zero out the result. Then, for each `1' bit in `a', we
|
||||
* shift `b' left the appropriate amount and add it to the result.
|
||||
* Similarly, to divide `a' by `b', we shift `b' left varying amounts,
|
||||
* repeatedly trying to subtract it from `a'. When we succeed, we note
|
||||
* the fact by setting a bit in the quotient. While these algorithms
|
||||
* have the same O(n^2) time complexity as Knuth's, the ``constant factor''
|
||||
* is likely to be larger.
|
||||
*
|
||||
* Because I used these algorithms, which require single-block addition
|
||||
* and subtraction rather than single-block multiplication and division,
|
||||
* the innermost loops of all four routines are very similar. Study one
|
||||
* of them and all will become clear.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is a little inline function used by both the multiplication
|
||||
* routine and the division routine.
|
||||
*
|
||||
* `getShiftedBlock' returns the `x'th block of `num << y'.
|
||||
* `y' may be anything from 0 to N - 1, and `x' may be anything from
|
||||
* 0 to `num.len'.
|
||||
*
|
||||
* Two things contribute to this block:
|
||||
*
|
||||
* (1) The `N - y' low bits of `num.blk[x]', shifted `y' bits left.
|
||||
*
|
||||
* (2) The `y' high bits of `num.blk[x-1]', shifted `N - y' bits right.
|
||||
*
|
||||
* But we must be careful if `x == 0' or `x == num.len', in
|
||||
* which case we should use 0 instead of (2) or (1), respectively.
|
||||
*
|
||||
* If `y == 0', then (2) contributes 0, as it should. However,
|
||||
* in some computer environments, for a reason I cannot understand,
|
||||
* `a >> b' means `a >> (b % N)'. This means `num.blk[x-1] >> (N - y)'
|
||||
* will return `num.blk[x-1]' instead of the desired 0 when `y == 0';
|
||||
* the test `y == 0' handles this case specially.
|
||||
*/
|
||||
inline BigUnsigned::Blk getShiftedBlock(const BigUnsigned &num,
|
||||
BigUnsigned::Index x, unsigned int y) {
|
||||
BigUnsigned::Blk part1 = (x == 0 || y == 0) ? 0 : (num.blk[x - 1] >> (BigUnsigned::N - y));
|
||||
BigUnsigned::Blk part2 = (x == num.len) ? 0 : (num.blk[x] << y);
|
||||
return part1 | part2;
|
||||
}
|
||||
|
||||
void BigUnsigned::multiply(const BigUnsigned &a, const BigUnsigned &b) {
|
||||
DTRT_ALIASED(this == &a || this == &b, multiply(a, b));
|
||||
// If either a or b is zero, set to zero.
|
||||
if (a.len == 0 || b.len == 0) {
|
||||
len = 0;
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Overall method:
|
||||
*
|
||||
* Set this = 0.
|
||||
* For each 1-bit of `a' (say the `i2'th bit of block `i'):
|
||||
* Add `b << (i blocks and i2 bits)' to *this.
|
||||
*/
|
||||
// Variables for the calculation
|
||||
Index i, j, k;
|
||||
unsigned int i2;
|
||||
Blk temp;
|
||||
bool carryIn, carryOut;
|
||||
// Set preliminary length and make room
|
||||
len = a.len + b.len;
|
||||
allocate(len);
|
||||
// Zero out this object
|
||||
for (i = 0; i < len; i++)
|
||||
blk[i] = 0;
|
||||
// For each block of the first number...
|
||||
for (i = 0; i < a.len; i++) {
|
||||
// For each 1-bit of that block...
|
||||
for (i2 = 0; i2 < N; i2++) {
|
||||
if ((a.blk[i] & (Blk(1) << i2)) == 0)
|
||||
continue;
|
||||
/*
|
||||
* Add b to this, shifted left i blocks and i2 bits.
|
||||
* j is the index in b, and k = i + j is the index in this.
|
||||
*
|
||||
* `getShiftedBlock', a short inline function defined above,
|
||||
* is now used for the bit handling. It replaces the more
|
||||
* complex `bHigh' code, in which each run of the loop dealt
|
||||
* immediately with the low bits and saved the high bits to
|
||||
* be picked up next time. The last run of the loop used to
|
||||
* leave leftover high bits, which were handled separately.
|
||||
* Instead, this loop runs an additional time with j == b.len.
|
||||
* These changes were made on 2005.01.11.
|
||||
*/
|
||||
for (j = 0, k = i, carryIn = false; j <= b.len; j++, k++) {
|
||||
/*
|
||||
* The body of this loop is very similar to the body of the first loop
|
||||
* in `add', except that this loop does a `+=' instead of a `+'.
|
||||
*/
|
||||
temp = blk[k] + getShiftedBlock(b, j, i2);
|
||||
carryOut = (temp < blk[k]);
|
||||
if (carryIn) {
|
||||
temp++;
|
||||
carryOut |= (temp == 0);
|
||||
}
|
||||
blk[k] = temp;
|
||||
carryIn = carryOut;
|
||||
}
|
||||
// No more extra iteration to deal with `bHigh'.
|
||||
// Roll-over a carry as necessary.
|
||||
for (; carryIn; k++) {
|
||||
blk[k]++;
|
||||
carryIn = (blk[k] == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Zap possible leading zero
|
||||
if (blk[len - 1] == 0)
|
||||
len--;
|
||||
}
|
||||
|
||||
/*
|
||||
* DIVISION WITH REMAINDER
|
||||
* This monstrous function mods *this by the given divisor b while storing the
|
||||
* quotient in the given object q; at the end, *this contains the remainder.
|
||||
* The seemingly bizarre pattern of inputs and outputs was chosen so that the
|
||||
* function copies as little as possible (since it is implemented by repeated
|
||||
* subtraction of multiples of b from *this).
|
||||
*
|
||||
* "modWithQuotient" might be a better name for this function, but I would
|
||||
* rather not change the name now.
|
||||
*/
|
||||
void BigUnsigned::divideWithRemainder(const BigUnsigned &b, BigUnsigned &q) {
|
||||
/* Defending against aliased calls is more complex than usual because we
|
||||
* are writing to both *this and q.
|
||||
*
|
||||
* It would be silly to try to write quotient and remainder to the
|
||||
* same variable. Rule that out right away. */
|
||||
if (this == &q)
|
||||
throw "BigUnsigned::divideWithRemainder: Cannot write quotient and remainder into the same variable";
|
||||
/* Now *this and q are separate, so the only concern is that b might be
|
||||
* aliased to one of them. If so, use a temporary copy of b. */
|
||||
if (this == &b || &q == &b) {
|
||||
BigUnsigned tmpB(b);
|
||||
divideWithRemainder(tmpB, q);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Knuth's definition of mod (which this function uses) is somewhat
|
||||
* different from the C++ definition of % in case of division by 0.
|
||||
*
|
||||
* We let a / 0 == 0 (it doesn't matter much) and a % 0 == a, no
|
||||
* exceptions thrown. This allows us to preserve both Knuth's demand
|
||||
* that a mod 0 == a and the useful property that
|
||||
* (a / b) * b + (a % b) == a.
|
||||
*/
|
||||
if (b.len == 0) {
|
||||
q.len = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If *this.len < b.len, then *this < b, and we can be sure that b doesn't go into
|
||||
* *this at all. The quotient is 0 and *this is already the remainder (so leave it alone).
|
||||
*/
|
||||
if (len < b.len) {
|
||||
q.len = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// At this point we know (*this).len >= b.len > 0. (Whew!)
|
||||
|
||||
/*
|
||||
* Overall method:
|
||||
*
|
||||
* For each appropriate i and i2, decreasing:
|
||||
* Subtract (b << (i blocks and i2 bits)) from *this, storing the
|
||||
* result in subtractBuf.
|
||||
* If the subtraction succeeds with a nonnegative result:
|
||||
* Turn on bit i2 of block i of the quotient q.
|
||||
* Copy subtractBuf back into *this.
|
||||
* Otherwise bit i2 of block i remains off, and *this is unchanged.
|
||||
*
|
||||
* Eventually q will contain the entire quotient, and *this will
|
||||
* be left with the remainder.
|
||||
*
|
||||
* subtractBuf[x] corresponds to blk[x], not blk[x+i], since 2005.01.11.
|
||||
* But on a single iteration, we don't touch the i lowest blocks of blk
|
||||
* (and don't use those of subtractBuf) because these blocks are
|
||||
* unaffected by the subtraction: we are subtracting
|
||||
* (b << (i blocks and i2 bits)), which ends in at least `i' zero
|
||||
* blocks. */
|
||||
// Variables for the calculation
|
||||
Index i, j, k;
|
||||
unsigned int i2;
|
||||
Blk temp;
|
||||
bool borrowIn, borrowOut;
|
||||
|
||||
/*
|
||||
* Make sure we have an extra zero block just past the value.
|
||||
*
|
||||
* When we attempt a subtraction, we might shift `b' so
|
||||
* its first block begins a few bits left of the dividend,
|
||||
* and then we'll try to compare these extra bits with
|
||||
* a nonexistent block to the left of the dividend. The
|
||||
* extra zero block ensures sensible behavior; we need
|
||||
* an extra block in `subtractBuf' for exactly the same reason.
|
||||
*/
|
||||
Index origLen = len; // Save real length.
|
||||
/* To avoid an out-of-bounds access in case of reallocation, allocate
|
||||
* first and then increment the logical length. */
|
||||
allocateAndCopy(len + 1);
|
||||
len++;
|
||||
blk[origLen] = 0; // Zero the added block.
|
||||
|
||||
// subtractBuf holds part of the result of a subtraction; see above.
|
||||
Blk *subtractBuf = new Blk[len];
|
||||
|
||||
// Set preliminary length for quotient and make room
|
||||
q.len = origLen - b.len + 1;
|
||||
q.allocate(q.len);
|
||||
// Zero out the quotient
|
||||
for (i = 0; i < q.len; i++)
|
||||
q.blk[i] = 0;
|
||||
|
||||
// For each possible left-shift of b in blocks...
|
||||
i = q.len;
|
||||
while (i > 0) {
|
||||
i--;
|
||||
// For each possible left-shift of b in bits...
|
||||
// (Remember, N is the number of bits in a Blk.)
|
||||
q.blk[i] = 0;
|
||||
i2 = N;
|
||||
while (i2 > 0) {
|
||||
i2--;
|
||||
/*
|
||||
* Subtract b, shifted left i blocks and i2 bits, from *this,
|
||||
* and store the answer in subtractBuf. In the for loop, `k == i + j'.
|
||||
*
|
||||
* Compare this to the middle section of `multiply'. They
|
||||
* are in many ways analogous. See especially the discussion
|
||||
* of `getShiftedBlock'.
|
||||
*/
|
||||
for (j = 0, k = i, borrowIn = false; j <= b.len; j++, k++) {
|
||||
temp = blk[k] - getShiftedBlock(b, j, i2);
|
||||
borrowOut = (temp > blk[k]);
|
||||
if (borrowIn) {
|
||||
borrowOut |= (temp == 0);
|
||||
temp--;
|
||||
}
|
||||
// Since 2005.01.11, indices of `subtractBuf' directly match those of `blk', so use `k'.
|
||||
subtractBuf[k] = temp;
|
||||
borrowIn = borrowOut;
|
||||
}
|
||||
// No more extra iteration to deal with `bHigh'.
|
||||
// Roll-over a borrow as necessary.
|
||||
for (; k < origLen && borrowIn; k++) {
|
||||
borrowIn = (blk[k] == 0);
|
||||
subtractBuf[k] = blk[k] - 1;
|
||||
}
|
||||
/*
|
||||
* If the subtraction was performed successfully (!borrowIn),
|
||||
* set bit i2 in block i of the quotient.
|
||||
*
|
||||
* Then, copy the portion of subtractBuf filled by the subtraction
|
||||
* back to *this. This portion starts with block i and ends--
|
||||
* where? Not necessarily at block `i + b.len'! Well, we
|
||||
* increased k every time we saved a block into subtractBuf, so
|
||||
* the region of subtractBuf we copy is just [i, k).
|
||||
*/
|
||||
if (!borrowIn) {
|
||||
q.blk[i] |= (Blk(1) << i2);
|
||||
while (k > i) {
|
||||
k--;
|
||||
blk[k] = subtractBuf[k];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Zap possible leading zero in quotient
|
||||
if (q.blk[q.len - 1] == 0)
|
||||
q.len--;
|
||||
// Zap any/all leading zeros in remainder
|
||||
zapLeadingZeros();
|
||||
// Deallocate subtractBuf.
|
||||
// (Thanks to Brad Spencer for noticing my accidental omission of this!)
|
||||
delete [] subtractBuf;
|
||||
}
|
||||
|
||||
/* BITWISE OPERATORS
|
||||
* These are straightforward blockwise operations except that they differ in
|
||||
* the output length and the necessity of zapLeadingZeros. */
|
||||
|
||||
void BigUnsigned::bitAnd(const BigUnsigned &a, const BigUnsigned &b) {
|
||||
DTRT_ALIASED(this == &a || this == &b, bitAnd(a, b));
|
||||
// The bitwise & can't be longer than either operand.
|
||||
len = (a.len >= b.len) ? b.len : a.len;
|
||||
allocate(len);
|
||||
Index i;
|
||||
for (i = 0; i < len; i++)
|
||||
blk[i] = a.blk[i] & b.blk[i];
|
||||
zapLeadingZeros();
|
||||
}
|
||||
|
||||
void BigUnsigned::bitOr(const BigUnsigned &a, const BigUnsigned &b) {
|
||||
DTRT_ALIASED(this == &a || this == &b, bitOr(a, b));
|
||||
Index i;
|
||||
const BigUnsigned *a2, *b2;
|
||||
if (a.len >= b.len) {
|
||||
a2 = &a;
|
||||
b2 = &b;
|
||||
} else {
|
||||
a2 = &b;
|
||||
b2 = &a;
|
||||
}
|
||||
allocate(a2->len);
|
||||
for (i = 0; i < b2->len; i++)
|
||||
blk[i] = a2->blk[i] | b2->blk[i];
|
||||
for (; i < a2->len; i++)
|
||||
blk[i] = a2->blk[i];
|
||||
len = a2->len;
|
||||
// Doesn't need zapLeadingZeros.
|
||||
}
|
||||
|
||||
void BigUnsigned::bitXor(const BigUnsigned &a, const BigUnsigned &b) {
|
||||
DTRT_ALIASED(this == &a || this == &b, bitXor(a, b));
|
||||
Index i;
|
||||
const BigUnsigned *a2, *b2;
|
||||
if (a.len >= b.len) {
|
||||
a2 = &a;
|
||||
b2 = &b;
|
||||
} else {
|
||||
a2 = &b;
|
||||
b2 = &a;
|
||||
}
|
||||
allocate(a2->len);
|
||||
for (i = 0; i < b2->len; i++)
|
||||
blk[i] = a2->blk[i] ^ b2->blk[i];
|
||||
for (; i < a2->len; i++)
|
||||
blk[i] = a2->blk[i];
|
||||
len = a2->len;
|
||||
zapLeadingZeros();
|
||||
}
|
||||
|
||||
void BigUnsigned::bitShiftLeft(const BigUnsigned &a, int b) {
|
||||
DTRT_ALIASED(this == &a, bitShiftLeft(a, b));
|
||||
if (b < 0) {
|
||||
if (b << 1 == 0)
|
||||
throw "BigUnsigned::bitShiftLeft: "
|
||||
"Pathological shift amount not implemented";
|
||||
else {
|
||||
bitShiftRight(a, -b);
|
||||
return;
|
||||
}
|
||||
}
|
||||
Index shiftBlocks = b / N;
|
||||
unsigned int shiftBits = b % N;
|
||||
// + 1: room for high bits nudged left into another block
|
||||
len = a.len + shiftBlocks + 1;
|
||||
allocate(len);
|
||||
Index i, j;
|
||||
for (i = 0; i < shiftBlocks; i++)
|
||||
blk[i] = 0;
|
||||
for (j = 0, i = shiftBlocks; j <= a.len; j++, i++)
|
||||
blk[i] = getShiftedBlock(a, j, shiftBits);
|
||||
// Zap possible leading zero
|
||||
if (blk[len - 1] == 0)
|
||||
len--;
|
||||
}
|
||||
|
||||
void BigUnsigned::bitShiftRight(const BigUnsigned &a, int b) {
|
||||
DTRT_ALIASED(this == &a, bitShiftRight(a, b));
|
||||
if (b < 0) {
|
||||
if (b << 1 == 0)
|
||||
throw "BigUnsigned::bitShiftRight: "
|
||||
"Pathological shift amount not implemented";
|
||||
else {
|
||||
bitShiftLeft(a, -b);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// This calculation is wacky, but expressing the shift as a left bit shift
|
||||
// within each block lets us use getShiftedBlock.
|
||||
Index rightShiftBlocks = (b + N - 1) / N;
|
||||
unsigned int leftShiftBits = N * rightShiftBlocks - b;
|
||||
// Now (N * rightShiftBlocks - leftShiftBits) == b
|
||||
// and 0 <= leftShiftBits < N.
|
||||
if (rightShiftBlocks >= a.len + 1) {
|
||||
// All of a is guaranteed to be shifted off, even considering the left
|
||||
// bit shift.
|
||||
len = 0;
|
||||
return;
|
||||
}
|
||||
// Now we're allocating a positive amount.
|
||||
// + 1: room for high bits nudged left into another block
|
||||
len = a.len + 1 - rightShiftBlocks;
|
||||
allocate(len);
|
||||
Index i, j;
|
||||
for (j = rightShiftBlocks, i = 0; j <= a.len; j++, i++)
|
||||
blk[i] = getShiftedBlock(a, j, leftShiftBits);
|
||||
// Zap possible leading zero
|
||||
if (blk[len - 1] == 0)
|
||||
len--;
|
||||
}
|
||||
|
||||
// INCREMENT/DECREMENT OPERATORS
|
||||
|
||||
// Prefix increment
|
||||
void BigUnsigned::operator ++() {
|
||||
Index i;
|
||||
bool carry = true;
|
||||
for (i = 0; i < len && carry; i++) {
|
||||
blk[i]++;
|
||||
carry = (blk[i] == 0);
|
||||
}
|
||||
if (carry) {
|
||||
// Allocate and then increase length, as in divideWithRemainder
|
||||
allocateAndCopy(len + 1);
|
||||
len++;
|
||||
blk[i] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Postfix increment: same as prefix
|
||||
void BigUnsigned::operator ++(int) {
|
||||
operator ++();
|
||||
}
|
||||
|
||||
// Prefix decrement
|
||||
void BigUnsigned::operator --() {
|
||||
if (len == 0)
|
||||
throw "BigUnsigned::operator --(): Cannot decrement an unsigned zero";
|
||||
Index i;
|
||||
bool borrow = true;
|
||||
for (i = 0; borrow; i++) {
|
||||
borrow = (blk[i] == 0);
|
||||
blk[i]--;
|
||||
}
|
||||
// Zap possible leading zero (there can only be one)
|
||||
if (blk[len - 1] == 0)
|
||||
len--;
|
||||
}
|
||||
|
||||
// Postfix decrement: same as prefix
|
||||
void BigUnsigned::operator --(int) {
|
||||
operator --();
|
||||
}
|
|
@ -1,418 +0,0 @@
|
|||
#ifndef BIGUNSIGNED_H
|
||||
#define BIGUNSIGNED_H
|
||||
|
||||
#include "NumberlikeArray.hh"
|
||||
|
||||
/* A BigUnsigned object represents a nonnegative integer of size limited only by
|
||||
* available memory. BigUnsigneds support most mathematical operators and can
|
||||
* be converted to and from most primitive integer types.
|
||||
*
|
||||
* The number is stored as a NumberlikeArray of unsigned longs as if it were
|
||||
* written in base 256^sizeof(unsigned long). The least significant block is
|
||||
* first, and the length is such that the most significant block is nonzero. */
|
||||
class BigUnsigned : protected NumberlikeArray<unsigned long> {
|
||||
|
||||
public:
|
||||
// Enumeration for the result of a comparison.
|
||||
enum CmpRes { less = -1, equal = 0, greater = 1 };
|
||||
|
||||
// BigUnsigneds are built with a Blk type of unsigned long.
|
||||
typedef unsigned long Blk;
|
||||
|
||||
typedef NumberlikeArray<Blk>::Index Index;
|
||||
using NumberlikeArray<Blk>::N;
|
||||
|
||||
protected:
|
||||
// Creates a BigUnsigned with a capacity; for internal use.
|
||||
BigUnsigned(int, Index c) : NumberlikeArray<Blk>(0, c) {}
|
||||
|
||||
// Decreases len to eliminate any leading zero blocks.
|
||||
void zapLeadingZeros() {
|
||||
while (len > 0 && blk[len - 1] == 0)
|
||||
len--;
|
||||
}
|
||||
|
||||
public:
|
||||
// Constructs zero.
|
||||
BigUnsigned() : NumberlikeArray<Blk>() {}
|
||||
|
||||
// Copy constructor
|
||||
BigUnsigned(const BigUnsigned &x) : NumberlikeArray<Blk>(x) {}
|
||||
|
||||
// Assignment operator
|
||||
void operator=(const BigUnsigned &x) {
|
||||
NumberlikeArray<Blk>::operator =(x);
|
||||
}
|
||||
|
||||
// Constructor that copies from a given array of blocks.
|
||||
BigUnsigned(const Blk *b, Index blen) : NumberlikeArray<Blk>(b, blen) {
|
||||
// Eliminate any leading zeros we may have been passed.
|
||||
zapLeadingZeros();
|
||||
}
|
||||
|
||||
// Destructor. NumberlikeArray does the delete for us.
|
||||
~BigUnsigned() {}
|
||||
|
||||
// Constructors from primitive integer types
|
||||
BigUnsigned(unsigned long x);
|
||||
BigUnsigned( long x);
|
||||
BigUnsigned(unsigned int x);
|
||||
BigUnsigned( int x);
|
||||
BigUnsigned(unsigned short x);
|
||||
BigUnsigned( short x);
|
||||
protected:
|
||||
// Helpers
|
||||
template <class X> void initFromPrimitive (X x);
|
||||
template <class X> void initFromSignedPrimitive(X x);
|
||||
public:
|
||||
|
||||
/* Converters to primitive integer types
|
||||
* The implicit conversion operators caused trouble, so these are now
|
||||
* named. */
|
||||
unsigned long toUnsignedLong () const;
|
||||
long toLong () const;
|
||||
unsigned int toUnsignedInt () const;
|
||||
int toInt () const;
|
||||
unsigned short toUnsignedShort() const;
|
||||
short toShort () const;
|
||||
protected:
|
||||
// Helpers
|
||||
template <class X> X convertToSignedPrimitive() const;
|
||||
template <class X> X convertToPrimitive () const;
|
||||
public:
|
||||
|
||||
// BIT/BLOCK ACCESSORS
|
||||
|
||||
// Expose these from NumberlikeArray directly.
|
||||
using NumberlikeArray<Blk>::getCapacity;
|
||||
using NumberlikeArray<Blk>::getLength;
|
||||
|
||||
/* Returns the requested block, or 0 if it is beyond the length (as if
|
||||
* the number had 0s infinitely to the left). */
|
||||
Blk getBlock(Index i) const { return i >= len ? 0 : blk[i]; }
|
||||
/* Sets the requested block. The number grows or shrinks as necessary. */
|
||||
void setBlock(Index i, Blk newBlock);
|
||||
|
||||
// The number is zero if and only if the canonical length is zero.
|
||||
bool isZero() const { return NumberlikeArray<Blk>::isEmpty(); }
|
||||
|
||||
/* Returns the length of the number in bits, i.e., zero if the number
|
||||
* is zero and otherwise one more than the largest value of bi for
|
||||
* which getBit(bi) returns true. */
|
||||
Index bitLength() const;
|
||||
/* Get the state of bit bi, which has value 2^bi. Bits beyond the
|
||||
* number's length are considered to be 0. */
|
||||
bool getBit(Index bi) const {
|
||||
return (getBlock(bi / N) & (Blk(1) << (bi % N))) != 0;
|
||||
}
|
||||
/* Sets the state of bit bi to newBit. The number grows or shrinks as
|
||||
* necessary. */
|
||||
void setBit(Index bi, bool newBit);
|
||||
|
||||
// COMPARISONS
|
||||
|
||||
// Compares this to x like Perl's <=>
|
||||
CmpRes compareTo(const BigUnsigned &x) const;
|
||||
|
||||
// Ordinary comparison operators
|
||||
bool operator ==(const BigUnsigned &x) const {
|
||||
return NumberlikeArray<Blk>::operator ==(x);
|
||||
}
|
||||
bool operator !=(const BigUnsigned &x) const {
|
||||
return NumberlikeArray<Blk>::operator !=(x);
|
||||
}
|
||||
bool operator < (const BigUnsigned &x) const { return compareTo(x) == less ; }
|
||||
bool operator <=(const BigUnsigned &x) const { return compareTo(x) != greater; }
|
||||
bool operator >=(const BigUnsigned &x) const { return compareTo(x) != less ; }
|
||||
bool operator > (const BigUnsigned &x) const { return compareTo(x) == greater; }
|
||||
|
||||
/*
|
||||
* BigUnsigned and BigInteger both provide three kinds of operators.
|
||||
* Here ``big-integer'' refers to BigInteger or BigUnsigned.
|
||||
*
|
||||
* (1) Overloaded ``return-by-value'' operators:
|
||||
* +, -, *, /, %, unary -, &, |, ^, <<, >>.
|
||||
* Big-integer code using these operators looks identical to code using
|
||||
* the primitive integer types. These operators take one or two
|
||||
* big-integer inputs and return a big-integer result, which can then
|
||||
* be assigned to a BigInteger variable or used in an expression.
|
||||
* Example:
|
||||
* BigInteger a(1), b = 1;
|
||||
* BigInteger c = a + b;
|
||||
*
|
||||
* (2) Overloaded assignment operators:
|
||||
* +=, -=, *=, /=, %=, flipSign, &=, |=, ^=, <<=, >>=, ++, --.
|
||||
* Again, these are used on big integers just like on ints. They take
|
||||
* one writable big integer that both provides an operand and receives a
|
||||
* result. Most also take a second read-only operand.
|
||||
* Example:
|
||||
* BigInteger a(1), b(1);
|
||||
* a += b;
|
||||
*
|
||||
* (3) Copy-less operations: `add', `subtract', etc.
|
||||
* These named methods take operands as arguments and store the result
|
||||
* in the receiver (*this), avoiding unnecessary copies and allocations.
|
||||
* `divideWithRemainder' is special: it both takes the dividend from and
|
||||
* stores the remainder into the receiver, and it takes a separate
|
||||
* object in which to store the quotient. NOTE: If you are wondering
|
||||
* why these don't return a value, you probably mean to use the
|
||||
* overloaded return-by-value operators instead.
|
||||
*
|
||||
* Examples:
|
||||
* BigInteger a(43), b(7), c, d;
|
||||
*
|
||||
* c = a + b; // Now c == 50.
|
||||
* c.add(a, b); // Same effect but without the two copies.
|
||||
*
|
||||
* c.divideWithRemainder(b, d);
|
||||
* // 50 / 7; now d == 7 (quotient) and c == 1 (remainder).
|
||||
*
|
||||
* // ``Aliased'' calls now do the right thing using a temporary
|
||||
* // copy, but see note on `divideWithRemainder'.
|
||||
* a.add(a, b);
|
||||
*/
|
||||
|
||||
// COPY-LESS OPERATIONS
|
||||
|
||||
// These 8: Arguments are read-only operands, result is saved in *this.
|
||||
void add(const BigUnsigned &a, const BigUnsigned &b);
|
||||
void subtract(const BigUnsigned &a, const BigUnsigned &b);
|
||||
void multiply(const BigUnsigned &a, const BigUnsigned &b);
|
||||
void bitAnd(const BigUnsigned &a, const BigUnsigned &b);
|
||||
void bitOr(const BigUnsigned &a, const BigUnsigned &b);
|
||||
void bitXor(const BigUnsigned &a, const BigUnsigned &b);
|
||||
/* Negative shift amounts translate to opposite-direction shifts,
|
||||
* except for -2^(8*sizeof(int)-1) which is unimplemented. */
|
||||
void bitShiftLeft(const BigUnsigned &a, int b);
|
||||
void bitShiftRight(const BigUnsigned &a, int b);
|
||||
|
||||
/* `a.divideWithRemainder(b, q)' is like `q = a / b, a %= b'.
|
||||
* / and % use semantics similar to Knuth's, which differ from the
|
||||
* primitive integer semantics under division by zero. See the
|
||||
* implementation in BigUnsigned.cc for details.
|
||||
* `a.divideWithRemainder(b, a)' throws an exception: it doesn't make
|
||||
* sense to write quotient and remainder into the same variable. */
|
||||
void divideWithRemainder(const BigUnsigned &b, BigUnsigned &q);
|
||||
|
||||
/* `divide' and `modulo' are no longer offered. Use
|
||||
* `divideWithRemainder' instead. */
|
||||
|
||||
// OVERLOADED RETURN-BY-VALUE OPERATORS
|
||||
BigUnsigned operator +(const BigUnsigned &x) const;
|
||||
BigUnsigned operator -(const BigUnsigned &x) const;
|
||||
BigUnsigned operator *(const BigUnsigned &x) const;
|
||||
BigUnsigned operator /(const BigUnsigned &x) const;
|
||||
BigUnsigned operator %(const BigUnsigned &x) const;
|
||||
/* OK, maybe unary minus could succeed in one case, but it really
|
||||
* shouldn't be used, so it isn't provided. */
|
||||
BigUnsigned operator &(const BigUnsigned &x) const;
|
||||
BigUnsigned operator |(const BigUnsigned &x) const;
|
||||
BigUnsigned operator ^(const BigUnsigned &x) const;
|
||||
BigUnsigned operator <<(int b) const;
|
||||
BigUnsigned operator >>(int b) const;
|
||||
|
||||
// OVERLOADED ASSIGNMENT OPERATORS
|
||||
void operator +=(const BigUnsigned &x);
|
||||
void operator -=(const BigUnsigned &x);
|
||||
void operator *=(const BigUnsigned &x);
|
||||
void operator /=(const BigUnsigned &x);
|
||||
void operator %=(const BigUnsigned &x);
|
||||
void operator &=(const BigUnsigned &x);
|
||||
void operator |=(const BigUnsigned &x);
|
||||
void operator ^=(const BigUnsigned &x);
|
||||
void operator <<=(int b);
|
||||
void operator >>=(int b);
|
||||
|
||||
/* INCREMENT/DECREMENT OPERATORS
|
||||
* To discourage messy coding, these do not return *this, so prefix
|
||||
* and postfix behave the same. */
|
||||
void operator ++( );
|
||||
void operator ++(int);
|
||||
void operator --( );
|
||||
void operator --(int);
|
||||
|
||||
// Helper function that needs access to BigUnsigned internals
|
||||
friend Blk getShiftedBlock(const BigUnsigned &num, Index x,
|
||||
unsigned int y);
|
||||
|
||||
// See BigInteger.cc.
|
||||
template <class X>
|
||||
friend X convertBigUnsignedToPrimitiveAccess(const BigUnsigned &a);
|
||||
};
|
||||
|
||||
/* Implementing the return-by-value and assignment operators in terms of the
|
||||
* copy-less operations. The copy-less operations are responsible for making
|
||||
* any necessary temporary copies to work around aliasing. */
|
||||
|
||||
inline BigUnsigned BigUnsigned::operator +(const BigUnsigned &x) const {
|
||||
BigUnsigned ans;
|
||||
ans.add(*this, x);
|
||||
return ans;
|
||||
}
|
||||
inline BigUnsigned BigUnsigned::operator -(const BigUnsigned &x) const {
|
||||
BigUnsigned ans;
|
||||
ans.subtract(*this, x);
|
||||
return ans;
|
||||
}
|
||||
inline BigUnsigned BigUnsigned::operator *(const BigUnsigned &x) const {
|
||||
BigUnsigned ans;
|
||||
ans.multiply(*this, x);
|
||||
return ans;
|
||||
}
|
||||
inline BigUnsigned BigUnsigned::operator /(const BigUnsigned &x) const {
|
||||
if (x.isZero()) throw "BigUnsigned::operator /: division by zero";
|
||||
BigUnsigned q, r;
|
||||
r = *this;
|
||||
r.divideWithRemainder(x, q);
|
||||
return q;
|
||||
}
|
||||
inline BigUnsigned BigUnsigned::operator %(const BigUnsigned &x) const {
|
||||
if (x.isZero()) throw "BigUnsigned::operator %: division by zero";
|
||||
BigUnsigned q, r;
|
||||
r = *this;
|
||||
r.divideWithRemainder(x, q);
|
||||
return r;
|
||||
}
|
||||
inline BigUnsigned BigUnsigned::operator &(const BigUnsigned &x) const {
|
||||
BigUnsigned ans;
|
||||
ans.bitAnd(*this, x);
|
||||
return ans;
|
||||
}
|
||||
inline BigUnsigned BigUnsigned::operator |(const BigUnsigned &x) const {
|
||||
BigUnsigned ans;
|
||||
ans.bitOr(*this, x);
|
||||
return ans;
|
||||
}
|
||||
inline BigUnsigned BigUnsigned::operator ^(const BigUnsigned &x) const {
|
||||
BigUnsigned ans;
|
||||
ans.bitXor(*this, x);
|
||||
return ans;
|
||||
}
|
||||
inline BigUnsigned BigUnsigned::operator <<(int b) const {
|
||||
BigUnsigned ans;
|
||||
ans.bitShiftLeft(*this, b);
|
||||
return ans;
|
||||
}
|
||||
inline BigUnsigned BigUnsigned::operator >>(int b) const {
|
||||
BigUnsigned ans;
|
||||
ans.bitShiftRight(*this, b);
|
||||
return ans;
|
||||
}
|
||||
|
||||
inline void BigUnsigned::operator +=(const BigUnsigned &x) {
|
||||
add(*this, x);
|
||||
}
|
||||
inline void BigUnsigned::operator -=(const BigUnsigned &x) {
|
||||
subtract(*this, x);
|
||||
}
|
||||
inline void BigUnsigned::operator *=(const BigUnsigned &x) {
|
||||
multiply(*this, x);
|
||||
}
|
||||
inline void BigUnsigned::operator /=(const BigUnsigned &x) {
|
||||
if (x.isZero()) throw "BigUnsigned::operator /=: division by zero";
|
||||
/* The following technique is slightly faster than copying *this first
|
||||
* when x is large. */
|
||||
BigUnsigned q;
|
||||
divideWithRemainder(x, q);
|
||||
// *this contains the remainder, but we overwrite it with the quotient.
|
||||
*this = q;
|
||||
}
|
||||
inline void BigUnsigned::operator %=(const BigUnsigned &x) {
|
||||
if (x.isZero()) throw "BigUnsigned::operator %=: division by zero";
|
||||
BigUnsigned q;
|
||||
// Mods *this by x. Don't care about quotient left in q.
|
||||
divideWithRemainder(x, q);
|
||||
}
|
||||
inline void BigUnsigned::operator &=(const BigUnsigned &x) {
|
||||
bitAnd(*this, x);
|
||||
}
|
||||
inline void BigUnsigned::operator |=(const BigUnsigned &x) {
|
||||
bitOr(*this, x);
|
||||
}
|
||||
inline void BigUnsigned::operator ^=(const BigUnsigned &x) {
|
||||
bitXor(*this, x);
|
||||
}
|
||||
inline void BigUnsigned::operator <<=(int b) {
|
||||
bitShiftLeft(*this, b);
|
||||
}
|
||||
inline void BigUnsigned::operator >>=(int b) {
|
||||
bitShiftRight(*this, b);
|
||||
}
|
||||
|
||||
/* Templates for conversions of BigUnsigned to and from primitive integers.
|
||||
* BigInteger.cc needs to instantiate convertToPrimitive, and the uses in
|
||||
* BigUnsigned.cc didn't do the trick; I think g++ inlined convertToPrimitive
|
||||
* instead of generating linkable instantiations. So for consistency, I put
|
||||
* all the templates here. */
|
||||
|
||||
// CONSTRUCTION FROM PRIMITIVE INTEGERS
|
||||
|
||||
/* Initialize this BigUnsigned from the given primitive integer. The same
|
||||
* pattern works for all primitive integer types, so I put it into a template to
|
||||
* reduce code duplication. (Don't worry: this is protected and we instantiate
|
||||
* it only with primitive integer types.) Type X could be signed, but x is
|
||||
* known to be nonnegative. */
|
||||
template <class X>
|
||||
void BigUnsigned::initFromPrimitive(X x) {
|
||||
if (x == 0)
|
||||
; // NumberlikeArray already initialized us to zero.
|
||||
else {
|
||||
// Create a single block. blk is NULL; no need to delete it.
|
||||
cap = 1;
|
||||
blk = new Blk[1];
|
||||
len = 1;
|
||||
blk[0] = Blk(x);
|
||||
}
|
||||
}
|
||||
|
||||
/* Ditto, but first check that x is nonnegative. I could have put the check in
|
||||
* initFromPrimitive and let the compiler optimize it out for unsigned-type
|
||||
* instantiations, but I wanted to avoid the warning stupidly issued by g++ for
|
||||
* a condition that is constant in *any* instantiation, even if not in all. */
|
||||
template <class X>
|
||||
void BigUnsigned::initFromSignedPrimitive(X x) {
|
||||
if (x < 0)
|
||||
throw "BigUnsigned constructor: "
|
||||
"Cannot construct a BigUnsigned from a negative number";
|
||||
else
|
||||
initFromPrimitive(x);
|
||||
}
|
||||
|
||||
// CONVERSION TO PRIMITIVE INTEGERS
|
||||
|
||||
/* Template with the same idea as initFromPrimitive. This might be slightly
|
||||
* slower than the previous version with the masks, but it's much shorter and
|
||||
* clearer, which is the library's stated goal. */
|
||||
template <class X>
|
||||
X BigUnsigned::convertToPrimitive() const {
|
||||
if (len == 0)
|
||||
// The number is zero; return zero.
|
||||
return 0;
|
||||
else if (len == 1) {
|
||||
// The single block might fit in an X. Try the conversion.
|
||||
X x = X(blk[0]);
|
||||
// Make sure the result accurately represents the block.
|
||||
if (Blk(x) == blk[0])
|
||||
// Successful conversion.
|
||||
return x;
|
||||
// Otherwise fall through.
|
||||
}
|
||||
throw "BigUnsigned::to<Primitive>: "
|
||||
"Value is too big to fit in the requested type";
|
||||
}
|
||||
|
||||
/* Wrap the above in an x >= 0 test to make sure we got a nonnegative result,
|
||||
* not a negative one that happened to convert back into the correct nonnegative
|
||||
* one. (E.g., catch incorrect conversion of 2^31 to the long -2^31.) Again,
|
||||
* separated to avoid a g++ warning. */
|
||||
template <class X>
|
||||
X BigUnsigned::convertToSignedPrimitive() const {
|
||||
X x = convertToPrimitive<X>();
|
||||
if (x >= 0)
|
||||
return x;
|
||||
else
|
||||
throw "BigUnsigned::to(Primitive): "
|
||||
"Value is too big to fit in the requested type";
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,125 +0,0 @@
|
|||
#include "BigUnsignedInABase.hh"
|
||||
|
||||
BigUnsignedInABase::BigUnsignedInABase(const Digit *d, Index l, Base base)
|
||||
: NumberlikeArray<Digit>(d, l), base(base) {
|
||||
// Check the base
|
||||
if (base < 2)
|
||||
throw "BigUnsignedInABase::BigUnsignedInABase(const Digit *, Index, Base): The base must be at least 2";
|
||||
|
||||
// Validate the digits.
|
||||
for (Index i = 0; i < l; i++)
|
||||
if (blk[i] >= base)
|
||||
throw "BigUnsignedInABase::BigUnsignedInABase(const Digit *, Index, Base): A digit is too large for the specified base";
|
||||
|
||||
// Eliminate any leading zeros we may have been passed.
|
||||
zapLeadingZeros();
|
||||
}
|
||||
|
||||
namespace {
|
||||
unsigned int bitLen(unsigned int x) {
|
||||
unsigned int len = 0;
|
||||
while (x > 0) {
|
||||
x >>= 1;
|
||||
len++;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
unsigned int ceilingDiv(unsigned int a, unsigned int b) {
|
||||
return (a + b - 1) / b;
|
||||
}
|
||||
}
|
||||
|
||||
BigUnsignedInABase::BigUnsignedInABase(const BigUnsigned &x, Base base) {
|
||||
// Check the base
|
||||
if (base < 2)
|
||||
throw "BigUnsignedInABase(BigUnsigned, Base): The base must be at least 2";
|
||||
this->base = base;
|
||||
|
||||
// Get an upper bound on how much space we need
|
||||
int maxBitLenOfX = x.getLength() * BigUnsigned::N;
|
||||
int minBitsPerDigit = bitLen(base) - 1;
|
||||
int maxDigitLenOfX = ceilingDiv(maxBitLenOfX, minBitsPerDigit);
|
||||
len = maxDigitLenOfX; // Another change to comply with `staying in bounds'.
|
||||
allocate(len); // Get the space
|
||||
|
||||
BigUnsigned x2(x), buBase(base);
|
||||
Index digitNum = 0;
|
||||
|
||||
while (!x2.isZero()) {
|
||||
// Get last digit. This is like `lastDigit = x2 % buBase, x2 /= buBase'.
|
||||
BigUnsigned lastDigit(x2);
|
||||
lastDigit.divideWithRemainder(buBase, x2);
|
||||
// Save the digit.
|
||||
blk[digitNum] = lastDigit.toUnsignedShort();
|
||||
// Move on. We can't run out of room: we figured it out above.
|
||||
digitNum++;
|
||||
}
|
||||
|
||||
// Save the actual length.
|
||||
len = digitNum;
|
||||
}
|
||||
|
||||
BigUnsignedInABase::operator BigUnsigned() const {
|
||||
BigUnsigned ans(0), buBase(base), temp;
|
||||
Index digitNum = len;
|
||||
while (digitNum > 0) {
|
||||
digitNum--;
|
||||
temp.multiply(ans, buBase);
|
||||
ans.add(temp, BigUnsigned(blk[digitNum]));
|
||||
}
|
||||
return ans;
|
||||
}
|
||||
|
||||
BigUnsignedInABase::BigUnsignedInABase(const std::string &s, Base base) {
|
||||
// Check the base.
|
||||
if (base > 36)
|
||||
throw "BigUnsignedInABase(std::string, Base): The default string conversion routines use the symbol set 0-9, A-Z and therefore support only up to base 36. You tried a conversion with a base over 36; write your own string conversion routine.";
|
||||
// Save the base.
|
||||
// This pattern is seldom seen in C++, but the analogous ``this.'' is common in Java.
|
||||
this->base = base;
|
||||
|
||||
// `s.length()' is a `size_t', while `len' is a `NumberlikeArray::Index',
|
||||
// also known as an `unsigned int'. Some compilers warn without this cast.
|
||||
len = Index(s.length());
|
||||
allocate(len);
|
||||
|
||||
Index digitNum, symbolNumInString;
|
||||
for (digitNum = 0; digitNum < len; digitNum++) {
|
||||
symbolNumInString = len - 1 - digitNum;
|
||||
char theSymbol = s[symbolNumInString];
|
||||
if (theSymbol >= '0' && theSymbol <= '9')
|
||||
blk[digitNum] = theSymbol - '0';
|
||||
else if (theSymbol >= 'A' && theSymbol <= 'Z')
|
||||
blk[digitNum] = theSymbol - 'A' + 10;
|
||||
else if (theSymbol >= 'a' && theSymbol <= 'z')
|
||||
blk[digitNum] = theSymbol - 'a' + 10;
|
||||
else
|
||||
throw "BigUnsignedInABase(std::string, Base): Bad symbol in input. Only 0-9, A-Z, a-z are accepted.";
|
||||
|
||||
if (blk[digitNum] >= base)
|
||||
throw "BigUnsignedInABase::BigUnsignedInABase(const Digit *, Index, Base): A digit is too large for the specified base";
|
||||
}
|
||||
zapLeadingZeros();
|
||||
}
|
||||
|
||||
BigUnsignedInABase::operator std::string() const {
|
||||
if (base > 36)
|
||||
throw "BigUnsignedInABase ==> std::string: The default string conversion routines use the symbol set 0-9, A-Z and therefore support only up to base 36. You tried a conversion with a base over 36; write your own string conversion routine.";
|
||||
if (len == 0)
|
||||
return std::string("0");
|
||||
// Some compilers don't have push_back, so use a char * buffer instead.
|
||||
char *s = new char[len + 1];
|
||||
s[len] = '\0';
|
||||
Index digitNum, symbolNumInString;
|
||||
for (symbolNumInString = 0; symbolNumInString < len; symbolNumInString++) {
|
||||
digitNum = len - 1 - symbolNumInString;
|
||||
Digit theDigit = blk[digitNum];
|
||||
if (theDigit < 10)
|
||||
s[symbolNumInString] = char('0' + theDigit);
|
||||
else
|
||||
s[symbolNumInString] = char('A' + theDigit - 10);
|
||||
}
|
||||
std::string s2(s);
|
||||
delete [] s;
|
||||
return s2;
|
||||
}
|
|
@ -1,122 +0,0 @@
|
|||
#ifndef BIGUNSIGNEDINABASE_H
|
||||
#define BIGUNSIGNEDINABASE_H
|
||||
|
||||
#include "NumberlikeArray.hh"
|
||||
#include "BigUnsigned.hh"
|
||||
#include <string>
|
||||
|
||||
/*
|
||||
* A BigUnsignedInABase object represents a nonnegative integer of size limited
|
||||
* only by available memory, represented in a user-specified base that can fit
|
||||
* in an `unsigned short' (most can, and this saves memory).
|
||||
*
|
||||
* BigUnsignedInABase is intended as an intermediary class with little
|
||||
* functionality of its own. BigUnsignedInABase objects can be constructed
|
||||
* from, and converted to, BigUnsigneds (requiring multiplication, mods, etc.)
|
||||
* and `std::string's (by switching digit values for appropriate characters).
|
||||
*
|
||||
* BigUnsignedInABase is similar to BigUnsigned. Note the following:
|
||||
*
|
||||
* (1) They represent the number in exactly the same way, except that
|
||||
* BigUnsignedInABase uses ``digits'' (or Digit) where BigUnsigned uses
|
||||
* ``blocks'' (or Blk).
|
||||
*
|
||||
* (2) Both use the management features of NumberlikeArray. (In fact, my desire
|
||||
* to add a BigUnsignedInABase class without duplicating a lot of code led me to
|
||||
* introduce NumberlikeArray.)
|
||||
*
|
||||
* (3) The only arithmetic operation supported by BigUnsignedInABase is an
|
||||
* equality test. Use BigUnsigned for arithmetic.
|
||||
*/
|
||||
|
||||
class BigUnsignedInABase : protected NumberlikeArray<unsigned short> {
|
||||
|
||||
public:
|
||||
// The digits of a BigUnsignedInABase are unsigned shorts.
|
||||
typedef unsigned short Digit;
|
||||
// That's also the type of a base.
|
||||
typedef Digit Base;
|
||||
|
||||
protected:
|
||||
// The base in which this BigUnsignedInABase is expressed
|
||||
Base base;
|
||||
|
||||
// Creates a BigUnsignedInABase with a capacity; for internal use.
|
||||
BigUnsignedInABase(int, Index c) : NumberlikeArray<Digit>(0, c) {}
|
||||
|
||||
// Decreases len to eliminate any leading zero digits.
|
||||
void zapLeadingZeros() {
|
||||
while (len > 0 && blk[len - 1] == 0)
|
||||
len--;
|
||||
}
|
||||
|
||||
public:
|
||||
// Constructs zero in base 2.
|
||||
BigUnsignedInABase() : NumberlikeArray<Digit>(), base(2) {}
|
||||
|
||||
// Copy constructor
|
||||
BigUnsignedInABase(const BigUnsignedInABase &x) : NumberlikeArray<Digit>(x), base(x.base) {}
|
||||
|
||||
// Assignment operator
|
||||
void operator =(const BigUnsignedInABase &x) {
|
||||
NumberlikeArray<Digit>::operator =(x);
|
||||
base = x.base;
|
||||
}
|
||||
|
||||
// Constructor that copies from a given array of digits.
|
||||
BigUnsignedInABase(const Digit *d, Index l, Base base);
|
||||
|
||||
// Destructor. NumberlikeArray does the delete for us.
|
||||
~BigUnsignedInABase() {}
|
||||
|
||||
// LINKS TO BIGUNSIGNED
|
||||
BigUnsignedInABase(const BigUnsigned &x, Base base);
|
||||
operator BigUnsigned() const;
|
||||
|
||||
/* LINKS TO STRINGS
|
||||
*
|
||||
* These use the symbols ``0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'' to
|
||||
* represent digits of 0 through 35. When parsing strings, lowercase is
|
||||
* also accepted.
|
||||
*
|
||||
* All string representations are big-endian (big-place-value digits
|
||||
* first). (Computer scientists have adopted zero-based counting; why
|
||||
* can't they tolerate little-endian numbers?)
|
||||
*
|
||||
* No string representation has a ``base indicator'' like ``0x''.
|
||||
*
|
||||
* An exception is made for zero: it is converted to ``0'' and not the
|
||||
* empty string.
|
||||
*
|
||||
* If you want different conventions, write your own routines to go
|
||||
* between BigUnsignedInABase and strings. It's not hard.
|
||||
*/
|
||||
operator std::string() const;
|
||||
BigUnsignedInABase(const std::string &s, Base base);
|
||||
|
||||
public:
|
||||
|
||||
// ACCESSORS
|
||||
Base getBase() const { return base; }
|
||||
|
||||
// Expose these from NumberlikeArray directly.
|
||||
using NumberlikeArray<Digit>::getCapacity;
|
||||
using NumberlikeArray<Digit>::getLength;
|
||||
|
||||
/* Returns the requested digit, or 0 if it is beyond the length (as if
|
||||
* the number had 0s infinitely to the left). */
|
||||
Digit getDigit(Index i) const { return i >= len ? 0 : blk[i]; }
|
||||
|
||||
// The number is zero if and only if the canonical length is zero.
|
||||
bool isZero() const { return NumberlikeArray<Digit>::isEmpty(); }
|
||||
|
||||
/* Equality test. For the purposes of this test, two BigUnsignedInABase
|
||||
* values must have the same base to be equal. */
|
||||
bool operator ==(const BigUnsignedInABase &x) const {
|
||||
return base == x.base && NumberlikeArray<Digit>::operator ==(x);
|
||||
}
|
||||
bool operator !=(const BigUnsignedInABase &x) const { return !operator ==(x); }
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,146 +0,0 @@
|
|||
Change Log
|
||||
|
||||
These entries tell you what was added, fixed, or improved in each version as
|
||||
compared to the previous one. In case you haven't noticed, a version number
|
||||
roughly corresponds to the release date of that version in `YYYY.MM.DD[.N]'
|
||||
format, where `.N' goes `.2', `.3', etc. if there are multiple versions on the
|
||||
same day. The topmost version listed is the one you have.
|
||||
|
||||
2010.04.30
|
||||
----------
|
||||
- Strengthen the advice about build/IDE configuration in the README.
|
||||
|
||||
2009.05.03
|
||||
----------
|
||||
- BigUnsigned::{get,set}Bit: Change two remaining `1 <<' to `Blk(1) <<' to work
|
||||
on systems where sizeof(unsigned int) != sizeof(Blk). Bug reported by Brad
|
||||
Spencer.
|
||||
- dataToBigInteger: Change a `delete' to `delete []' to avoid leaking memory.
|
||||
Bug reported by Nicolás Carrasco.
|
||||
|
||||
2009.03.26
|
||||
----------
|
||||
- BigUnsignedInABase(std::string) Reject digits too big for the base.
|
||||
Bug reported by Niakam Kazemi.
|
||||
|
||||
2008.07.20
|
||||
----------
|
||||
Dennis Yew pointed out serious problems with ambiguities and unwanted
|
||||
conversions when mixing BigInteger/BigUnsigned and primitive integers. To fix
|
||||
these, I removed the implicit conversions from BigInteger/BigUnsigned to
|
||||
primitive integers and from BigInteger to BigUnsigned. Removing the
|
||||
BigInteger-to-BigUnsigned conversion required changing BigInteger to have a
|
||||
BigUnsigned field instead of inheriting from it; this was a complex task but
|
||||
ultimately gave a saner design. At the same time, I went through the entire
|
||||
codebase, making the formatting and comments prettier and reworking anything I
|
||||
thought was unclear. I also added a testsuite (currently for 32-bit systems
|
||||
only); it doesn't yet cover the entire library but should help to ensure that
|
||||
things work the way they should.
|
||||
|
||||
A number of changes from version 2007.07.07 break compatibility with existing
|
||||
code that uses the library, but updating that code should be pretty easy:
|
||||
- BigInteger can no longer be implicitly converted to BigUnsigned. Use
|
||||
getMagnitude() instead.
|
||||
- BigUnsigned and BigInteger can no longer be implicitly converted to primitive
|
||||
integers. Use the toInt() family of functions instead.
|
||||
- The easy* functions have been renamed to more mature names:
|
||||
bigUnsignedToString, bigIntegerToString, stringToBigUnsigned,
|
||||
stringToBigInteger, dataToBigInteger.
|
||||
- BigInteger no longer supports bitwise operations. Get the magnitude with
|
||||
getMagnitude() and operate on that instead.
|
||||
- The old {BigUnsigned,BigInteger}::{divide,modulo} copy-less options have been
|
||||
removed. Use divideWithRemainder instead.
|
||||
- Added a base argument to BigUnsignedInABase's digit-array constructor. I
|
||||
ope no one used that constructor in its broken state anyway.
|
||||
|
||||
Other notable changes:
|
||||
- Added BigUnsigned functions setBlock, bitLength, getBit, setBit.
|
||||
- The bit-shifting operations now support negative shift amounts, which shift in
|
||||
the other direction.
|
||||
- Added some big-integer algorithms in BigIntegerAlgorithms.hh: gcd,
|
||||
extendedEuclidean, modinv, modexp.
|
||||
|
||||
2007.07.07
|
||||
----------
|
||||
Update the "Running the sample program produces this output:" comment in
|
||||
sample.cc for the bitwise operators.
|
||||
|
||||
2007.06.14
|
||||
----------
|
||||
- Implement << and >> for BigUnsigned in response to email from Marco Schulze.
|
||||
- Fix name: DOTR_ALIASED -> DTRT_ALIASED.
|
||||
- Demonstrate all bitwise operators (&, |, ^, <<, >>) in sample.cc.
|
||||
|
||||
2007.02.16
|
||||
----------
|
||||
Boris Dessy pointed out that the library threw an exception on "a *= a", so I changed all the put-here operations to handle aliased calls correctly using a temporary copy instead of throwing exceptions.
|
||||
|
||||
2006.08.14
|
||||
----------
|
||||
In BigUnsigned::bitXor, change allocate(b2->len) to allocate(a2->len): we should allocate enough space for the longer number, not the shorter one! Thanks to Sriram Sankararaman for pointing this out.
|
||||
|
||||
2006.05.03
|
||||
----------
|
||||
I ran the sample program using valgrind and discovered a `delete s' that should be `delete [] s' and a `len++' before an `allocateAndCopy(len)' that should have been after an `allocateAndCopy(len + 1)'. I fixed both. Yay for valgrind!
|
||||
|
||||
2006.05.01
|
||||
----------
|
||||
I fixed incorrect results reported by Mohand Mezmaz and related memory corruption on platforms where Blk is bigger than int. I replaced (1 << x) with (Blk(1) << x) in two places in BigUnsigned.cc.
|
||||
|
||||
2006.04.24
|
||||
----------
|
||||
Two bug fixes: BigUnsigned "++x" no longer segfaults when x grows in length, and BigUnsigned == and != are now redeclared so as to be usable. I redid the Makefile: I removed the *.tag mechanism and hard-coded the library's header dependencies, I added comments, and I made the Makefile more useful for building one's own programs instead of just the sample.
|
||||
|
||||
2006.02.26
|
||||
----------
|
||||
A few tweaks in preparation for a group to distribute the library. The project Web site has moved; I updated the references. I fixed a typo and added a missing function in NumberlikeArray.hh. I'm using Eclipse now, so you get Eclipse project files.
|
||||
|
||||
2005.03.30
|
||||
----------
|
||||
Sam Larkin found a bug in `BigInteger::subtract'; I fixed it.
|
||||
|
||||
2005.01.18
|
||||
----------
|
||||
I fixed some problems with `easyDataToBI'. Due to some multiply declared variables, this function would not compile. However, it is a template function, so the compiler parses it and doesn't compile the parsed representation until something uses the function; this is how I missed the problems. I also removed debugging output from this function.
|
||||
|
||||
2005.01.17
|
||||
----------
|
||||
A fix to some out-of-bounds accesses reported by Milan Tomic (see the comment under `BigUnsigned::divideWithRemainder'). `BigUnsigned::multiply' and `BigUnsigned::divideWithRemainder' implementations neatened up a bit with the help of a function `getShiftedBlock'. I (finally!) introduced a constant `BigUnsigned::N', the number of bits in a `BigUnsigned::Blk', which varies depending on machine word size. In both code and comments, it replaces the much clunkier `8*sizeof(Blk)'. Numerous other small changes. There's a new conversion routine `easyDataToBI' that will convert almost any format of binary data to a `BigInteger'.
|
||||
|
||||
I have inserted a significant number of new comments. Most explain unobvious aspects of the code.
|
||||
|
||||
2005.01.06
|
||||
----------
|
||||
Some changes to the way zero-length arrays are handled by `NumberlikeArray', which fixed a memory leak reported by Milan Tomic.
|
||||
|
||||
2004.12.24.2
|
||||
------------
|
||||
I tied down a couple of loose ends involving division/modulo. I added an explanation of put-here vs. overloaded operators in the sample program; this has confused too many people. Miscellaneous other improvements.
|
||||
|
||||
I believe that, at this point, the Big Integer Library makes no assumptions about the word size of the machine it is using. `BigUnsigned::Blk' is always an `unsigned long', whatever that may be, and its size is computed with `sizeof' when necessary. However, just in case, I would be interested to have someone test the library on a non-32-bit machine to see if it works.
|
||||
|
||||
2004.12.24
|
||||
----------
|
||||
This is a _major_ upgrade to the library. Among the things that have changed:
|
||||
|
||||
I wrote the original version of the library, particularly the four ``classical algorithms'' in `BigUnsigned.cc', using array indexing. Then I rewrote it to use pointers because I thought that would be faster. But recently, I revisited the code in `BigUnsigned.cc' and found that I could not begin to understand what it was doing.
|
||||
|
||||
I have decided that the drawbacks of pointers, increased coding difficulty and reduced code readability, far outweigh their speed benefits. Plus, any modern optimizing compiler should produce fast code either way. Therefore, I rewrote the library to use array indexing again. (Thank goodness for regular-expression find-and-replace. It saved me a lot of time.)
|
||||
|
||||
The put-here operations `divide' and `modulo' of each of `BigUnsigned' and `BigInteger' have been supplanted by a single operation `divideWithRemainder'. Read the profuse comments for more information on its exact behavior.
|
||||
|
||||
There is a new class `BigUnsignedInABase' that is like `BigUnsigned' but uses a user-specified, small base instead of `256 ^ sizeof(unsigned long)'. Much of the code common to the two has been factored out into `NumberlikeArray'.
|
||||
|
||||
`BigUnsignedInABase' facilitates conversion between `BigUnsigned's and digit-by-digit string representations using `std::string'. Convenience routines to do this conversion are in `BigIntegerUtils.hh'. `iostream' compatibility has been improved.
|
||||
|
||||
I would like to thank Chris Morbitzer for the e-mail message that catalyzed this major upgrade. He wanted a way to convert a string to a BigInteger. One thing just led to another, roughly in reverse order from how they are listed here.
|
||||
|
||||
2004.1216
|
||||
---------
|
||||
Brad Spencer pointed out a memory leak in `BigUnsigned::divide'. It is fixed in the December 16, 2004 version.
|
||||
|
||||
2004.1205
|
||||
---------
|
||||
After months of inactivity, I fixed a bug in the `BigInteger' division routine; thanks to David Allen for reporting the bug. I also added simple routines for decimal output to `std::ostream's, and there is a demo that prints out powers of 3.
|
||||
|
||||
~~~~
|
|
@ -1,177 +0,0 @@
|
|||
#ifndef NUMBERLIKEARRAY_H
|
||||
#define NUMBERLIKEARRAY_H
|
||||
|
||||
// Make sure we have NULL.
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
/* A NumberlikeArray<Blk> object holds a heap-allocated array of Blk with a
|
||||
* length and a capacity and provides basic memory management features.
|
||||
* BigUnsigned and BigUnsignedInABase both subclass it.
|
||||
*
|
||||
* NumberlikeArray provides no information hiding. Subclasses should use
|
||||
* nonpublic inheritance and manually expose members as desired using
|
||||
* declarations like this:
|
||||
*
|
||||
* public:
|
||||
* NumberlikeArray< the-type-argument >::getLength;
|
||||
*/
|
||||
template <class Blk>
|
||||
class NumberlikeArray {
|
||||
public:
|
||||
|
||||
// Type for the index of a block in the array
|
||||
typedef unsigned int Index;
|
||||
// The number of bits in a block, defined below.
|
||||
static const unsigned int N;
|
||||
|
||||
// The current allocated capacity of this NumberlikeArray (in blocks)
|
||||
Index cap;
|
||||
// The actual length of the value stored in this NumberlikeArray (in blocks)
|
||||
Index len;
|
||||
// Heap-allocated array of the blocks (can be NULL if len == 0)
|
||||
Blk *blk;
|
||||
|
||||
// Constructs a ``zero'' NumberlikeArray with the given capacity.
|
||||
NumberlikeArray(Index c) : cap(c), len(0) {
|
||||
blk = (cap > 0) ? (new Blk[cap]) : NULL;
|
||||
}
|
||||
|
||||
/* Constructs a zero NumberlikeArray without allocating a backing array.
|
||||
* A subclass that doesn't know the needed capacity at initialization
|
||||
* time can use this constructor and then overwrite blk without first
|
||||
* deleting it. */
|
||||
NumberlikeArray() : cap(0), len(0) {
|
||||
blk = NULL;
|
||||
}
|
||||
|
||||
// Destructor. Note that `delete NULL' is a no-op.
|
||||
~NumberlikeArray() {
|
||||
delete [] blk;
|
||||
}
|
||||
|
||||
/* Ensures that the array has at least the requested capacity; may
|
||||
* destroy the contents. */
|
||||
void allocate(Index c);
|
||||
|
||||
/* Ensures that the array has at least the requested capacity; does not
|
||||
* destroy the contents. */
|
||||
void allocateAndCopy(Index c);
|
||||
|
||||
// Copy constructor
|
||||
NumberlikeArray(const NumberlikeArray<Blk> &x);
|
||||
|
||||
// Assignment operator
|
||||
void operator=(const NumberlikeArray<Blk> &x);
|
||||
|
||||
// Constructor that copies from a given array of blocks
|
||||
NumberlikeArray(const Blk *b, Index blen);
|
||||
|
||||
// ACCESSORS
|
||||
Index getCapacity() const { return cap; }
|
||||
Index getLength() const { return len; }
|
||||
Blk getBlock(Index i) const { return blk[i]; }
|
||||
bool isEmpty() const { return len == 0; }
|
||||
|
||||
/* Equality comparison: checks if both objects have the same length and
|
||||
* equal (==) array elements to that length. Subclasses may wish to
|
||||
* override. */
|
||||
bool operator ==(const NumberlikeArray<Blk> &x) const;
|
||||
|
||||
bool operator !=(const NumberlikeArray<Blk> &x) const {
|
||||
return !operator ==(x);
|
||||
}
|
||||
};
|
||||
|
||||
/* BEGIN TEMPLATE DEFINITIONS. They are present here so that source files that
|
||||
* include this header file can generate the necessary real definitions. */
|
||||
|
||||
template <class Blk>
|
||||
const unsigned int NumberlikeArray<Blk>::N = 8 * sizeof(Blk);
|
||||
|
||||
template <class Blk>
|
||||
void NumberlikeArray<Blk>::allocate(Index c) {
|
||||
// If the requested capacity is more than the current capacity...
|
||||
if (c > cap) {
|
||||
// Delete the old number array
|
||||
delete [] blk;
|
||||
// Allocate the new array
|
||||
cap = c;
|
||||
blk = new Blk[cap];
|
||||
}
|
||||
}
|
||||
|
||||
template <class Blk>
|
||||
void NumberlikeArray<Blk>::allocateAndCopy(Index c) {
|
||||
// If the requested capacity is more than the current capacity...
|
||||
if (c > cap) {
|
||||
Blk *oldBlk = blk;
|
||||
// Allocate the new number array
|
||||
cap = c;
|
||||
blk = new Blk[cap];
|
||||
// Copy number blocks
|
||||
Index i;
|
||||
for (i = 0; i < len; i++)
|
||||
blk[i] = oldBlk[i];
|
||||
// Delete the old array
|
||||
delete [] oldBlk;
|
||||
}
|
||||
}
|
||||
|
||||
template <class Blk>
|
||||
NumberlikeArray<Blk>::NumberlikeArray(const NumberlikeArray<Blk> &x)
|
||||
: len(x.len) {
|
||||
// Create array
|
||||
cap = len;
|
||||
blk = new Blk[cap];
|
||||
// Copy blocks
|
||||
Index i;
|
||||
for (i = 0; i < len; i++)
|
||||
blk[i] = x.blk[i];
|
||||
}
|
||||
|
||||
template <class Blk>
|
||||
void NumberlikeArray<Blk>::operator=(const NumberlikeArray<Blk> &x) {
|
||||
/* Calls like a = a have no effect; catch them before the aliasing
|
||||
* causes a problem */
|
||||
if (this == &x)
|
||||
return;
|
||||
// Copy length
|
||||
len = x.len;
|
||||
// Expand array if necessary
|
||||
allocate(len);
|
||||
// Copy number blocks
|
||||
Index i;
|
||||
for (i = 0; i < len; i++)
|
||||
blk[i] = x.blk[i];
|
||||
}
|
||||
|
||||
template <class Blk>
|
||||
NumberlikeArray<Blk>::NumberlikeArray(const Blk *b, Index blen)
|
||||
: cap(blen), len(blen) {
|
||||
// Create array
|
||||
blk = new Blk[cap];
|
||||
// Copy blocks
|
||||
Index i;
|
||||
for (i = 0; i < len; i++)
|
||||
blk[i] = b[i];
|
||||
}
|
||||
|
||||
template <class Blk>
|
||||
bool NumberlikeArray<Blk>::operator ==(const NumberlikeArray<Blk> &x) const {
|
||||
if (len != x.len)
|
||||
// Definitely unequal.
|
||||
return false;
|
||||
else {
|
||||
// Compare corresponding blocks one by one.
|
||||
Index i;
|
||||
for (i = 0; i < len; i++)
|
||||
if (blk[i] != x.blk[i])
|
||||
return false;
|
||||
// No blocks differed, so the objects are equal.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,71 +0,0 @@
|
|||
|
||||
C++ Big Integer Library
|
||||
(see ChangeLog for version)
|
||||
|
||||
http://mattmccutchen.net/bigint/
|
||||
|
||||
Written and maintained by Matt McCutchen <matt@mattmccutchen.net>
|
||||
|
||||
You can use this library in a C++ program to do arithmetic on integers of size
|
||||
limited only by your computer's memory. The library provides BigUnsigned and
|
||||
BigInteger classes that represent nonnegative integers and signed integers,
|
||||
respectively. Most of the C++ arithmetic operators are overloaded for these
|
||||
classes, so big-integer calculations are as easy as:
|
||||
|
||||
#include "BigIntegerLibrary.hh"
|
||||
|
||||
BigInteger a = 65536;
|
||||
cout << (a * a * a * a * a * a * a * a);
|
||||
|
||||
(prints 340282366920938463463374607431768211456)
|
||||
|
||||
The code in `sample.cc' demonstrates the most important features of the library.
|
||||
To get started quickly, read the code and explanations in that file and run it.
|
||||
If you want more detail or a feature not shown in `sample.cc', consult the
|
||||
consult the actual header and source files, which are thoroughly commented.
|
||||
|
||||
This library emphasizes ease of use and clarity of implementation over speed;
|
||||
some users will prefer GMP (http://swox.com/gmp/), which is faster. The code is
|
||||
intended to be reasonably portable across computers and modern C++ compilers; in
|
||||
particular, it uses whatever word size the computer provides (32-bit, 64-bit, or
|
||||
otherwise).
|
||||
|
||||
Compiling programs that use the library
|
||||
---------------------------------------
|
||||
The library consists of a folder full of C++ header files (`.hh') and source
|
||||
files (`.cc'). Your own programs should `#include' the necessary header files
|
||||
and link with the source files. A makefile that builds the sample program
|
||||
(`sample.cc') is included; you can adapt it to replace the sample with your own
|
||||
program.
|
||||
|
||||
Alternatively, you can use your own build system or IDE. In that case, you must
|
||||
put the library header files where the compiler will find them and arrange to
|
||||
have your program linked with the library source files; otherwise, you will get
|
||||
errors about missing header files or "undefined references". To learn how to do
|
||||
this, consult the documentation for the build system or IDE; don't bother asking
|
||||
me. Adding all the library files to your project will work in many IDEs but may
|
||||
not be the most desirable approach.
|
||||
|
||||
Resources
|
||||
---------
|
||||
The library's Web site (above) provides links to released versions, the current
|
||||
development version, and a mailing list for release announcements, questions,
|
||||
bug reports, and other discussion of the library. I would be delighted to hear
|
||||
from you if you like this library and/or find a good use for it.
|
||||
|
||||
Bugs and enhancements
|
||||
---------------------
|
||||
The library has been tested by me and others but is by no means bug-free. If
|
||||
you find a bug, please report it, whether it comes in the form of compiling
|
||||
trouble, a mathematically inaccurate result, or a memory-management blooper
|
||||
(since I use Java, these are altogether too common in my C++). I generally fix
|
||||
all reported bugs. You are also welcome to request enhancements, but I am
|
||||
unlikely to do substantial amounts of work on enhancements at this point.
|
||||
|
||||
Legal
|
||||
-----
|
||||
I, Matt McCutchen, the sole author of the original Big Integer Library, waive my
|
||||
copyright to it, placing it in the public domain. The library comes with
|
||||
absolutely no warranty.
|
||||
|
||||
~~~~
|
|
@ -1,8 +1,9 @@
|
|||
// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
|
||||
#ifndef __ZXING_COMMON_DETECTOR_MATH_H__
|
||||
#define __ZXING_COMMON_DETECTOR_MATH_H__
|
||||
/*
|
||||
* Copyright 2012 ZXing authors All rights reserved.
|
||||
* Array.cpp
|
||||
* zxing
|
||||
*
|
||||
* Created by Christian Brunschen on 07/05/2008.
|
||||
* Copyright 2008 Google UK. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -17,27 +18,5 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <cmath>
|
||||
#include <zxing/common/Array.h>
|
||||
|
||||
namespace zxing {
|
||||
namespace common {
|
||||
namespace detector {
|
||||
|
||||
class Math {
|
||||
private:
|
||||
Math();
|
||||
~Math();
|
||||
public:
|
||||
|
||||
// Java standard Math.round
|
||||
static inline int round(float a) {
|
||||
return (int)std::floor(a +0.5f);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -23,25 +23,27 @@
|
|||
|
||||
#include <vector>
|
||||
|
||||
#ifdef DEBUG_COUNTING
|
||||
#include <iostream>
|
||||
#include <typeinfo>
|
||||
#endif
|
||||
|
||||
#include <zxing/common/Counted.h>
|
||||
|
||||
|
||||
namespace zxing {
|
||||
|
||||
template<typename T> class Array : public Counted {
|
||||
protected:
|
||||
public:
|
||||
std::vector<T> values_;
|
||||
Array() {}
|
||||
Array(int n) :
|
||||
Array(size_t n) :
|
||||
Counted(), values_(n, T()) {
|
||||
}
|
||||
Array(T const* ts, int n) :
|
||||
Array(T *ts, size_t n) :
|
||||
Counted(), values_(ts, ts+n) {
|
||||
}
|
||||
Array(T const* ts, T const* te) :
|
||||
Counted(), values_(ts, te) {
|
||||
}
|
||||
Array(T v, int n) :
|
||||
Array(T v, size_t n) :
|
||||
Counted(), values_(n, v) {
|
||||
}
|
||||
Array(std::vector<T> &v) :
|
||||
|
@ -56,26 +58,35 @@ public:
|
|||
virtual ~Array() {
|
||||
}
|
||||
Array<T>& operator=(const Array<T> &other) {
|
||||
#ifdef DEBUG_COUNTING
|
||||
cout << "assigning values from Array " << &other << " to this Array " << this << ", ";
|
||||
#endif
|
||||
values_ = other.values_;
|
||||
#ifdef DEBUG_COUNTING
|
||||
cout << "new size = " << values_.size() << "\n";
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
Array<T>& operator=(const std::vector<T> &array) {
|
||||
#ifdef DEBUG_COUNTING
|
||||
cout << "assigning values from Array " << &array << " to this Array " << this << ", ";
|
||||
#endif
|
||||
values_ = array;
|
||||
#ifdef DEBUG_COUNTING
|
||||
cout << "new size = " << values_.size() << "\n";
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
T const& operator[](int i) const {
|
||||
T operator[](size_t i) const {
|
||||
return values_[i];
|
||||
}
|
||||
T& operator[](int i) {
|
||||
T& operator[](size_t i) {
|
||||
return values_[i];
|
||||
}
|
||||
int size() const {
|
||||
size_t size() const {
|
||||
return values_.size();
|
||||
}
|
||||
bool empty() const {
|
||||
return values_.size() == 0;
|
||||
}
|
||||
std::vector<T> const& values() const {
|
||||
std::vector<T> values() const {
|
||||
return values_;
|
||||
}
|
||||
std::vector<T>& values() {
|
||||
|
@ -89,46 +100,81 @@ public:
|
|||
Array<T> *array_;
|
||||
ArrayRef() :
|
||||
array_(0) {
|
||||
#ifdef DEBUG_COUNTING
|
||||
cout << "instantiating empty ArrayRef " << this << "\n";
|
||||
#endif
|
||||
}
|
||||
explicit ArrayRef(int n) :
|
||||
ArrayRef(size_t n) :
|
||||
array_(0) {
|
||||
#ifdef DEBUG_COUNTING
|
||||
cout << "instantiating ArrayRef " << this << "with size " << n << "\n";
|
||||
#endif
|
||||
reset(new Array<T> (n));
|
||||
}
|
||||
ArrayRef(T *ts, int n) :
|
||||
ArrayRef(T *ts, size_t n) :
|
||||
array_(0) {
|
||||
#ifdef DEBUG_COUNTING
|
||||
cout << "instantiating ArrayRef " << this << "with " << n << " elements at " << (void *)ts << "\n";
|
||||
#endif
|
||||
reset(new Array<T> (ts, n));
|
||||
}
|
||||
ArrayRef(Array<T> *a) :
|
||||
array_(0) {
|
||||
#ifdef DEBUG_COUNTING
|
||||
cout << "instantiating ArrayRef " << this << " from pointer:\n";
|
||||
#endif
|
||||
reset(a);
|
||||
}
|
||||
ArrayRef(const Array<T> &a) :
|
||||
array_(0) {
|
||||
#ifdef DEBUG_COUNTING
|
||||
cout << "instantiating ArrayRef " << this << " from reference to Array " << (void *)&a << ":\n";
|
||||
#endif
|
||||
reset(const_cast<Array<T> *>(&a));
|
||||
}
|
||||
ArrayRef(const ArrayRef &other) :
|
||||
Counted(), array_(0) {
|
||||
#ifdef DEBUG_COUNTING
|
||||
cout << "instantiating ArrayRef " << this << " from ArrayRef " << &other << ":\n";
|
||||
#endif
|
||||
reset(other.array_);
|
||||
}
|
||||
|
||||
template<class Y>
|
||||
ArrayRef(const ArrayRef<Y> &other) :
|
||||
array_(0) {
|
||||
reset(static_cast<const Array<T> *>(other.array_));
|
||||
#ifdef DEBUG_COUNTING
|
||||
cout << "instantiating ArrayRef " << this << " from ArrayRef " << &other << ":\n";
|
||||
#endif
|
||||
reset(static_cast<const Array<T> *>(other.array_));
|
||||
}
|
||||
|
||||
~ArrayRef() {
|
||||
#ifdef DEBUG_COUNTING
|
||||
cout << "destroying ArrayRef " << this << " with " << (array_ ? typeid(*array_).name() : "NULL") << " "
|
||||
<< array_ << "\n";
|
||||
#endif
|
||||
if (array_) {
|
||||
array_->release();
|
||||
}
|
||||
array_ = 0;
|
||||
}
|
||||
|
||||
T const& operator[](int i) const {
|
||||
T operator[](size_t i) const {
|
||||
return (*array_)[i];
|
||||
}
|
||||
|
||||
T& operator[](int i) {
|
||||
T& operator[](size_t i) {
|
||||
return (*array_)[i];
|
||||
}
|
||||
size_t size() const {
|
||||
return array_->size();
|
||||
}
|
||||
|
||||
void reset(Array<T> *a) {
|
||||
#ifdef DEBUG_COUNTING
|
||||
cout << "resetting ArrayRef " << this << " from " << (array_ ? typeid(*array_).name() : "NULL") << " "
|
||||
<< array_ << " to " << (a ? typeid(*a).name() : "NULL") << " " << a << "\n";
|
||||
#endif
|
||||
if (a) {
|
||||
a->retain();
|
||||
}
|
||||
|
@ -149,20 +195,12 @@ public:
|
|||
return *this;
|
||||
}
|
||||
|
||||
Array<T>& operator*() const {
|
||||
Array<T>& operator*() {
|
||||
return *array_;
|
||||
}
|
||||
|
||||
Array<T>* operator->() const {
|
||||
Array<T>* operator->() {
|
||||
return array_;
|
||||
}
|
||||
|
||||
operator bool () const {
|
||||
return array_ != 0;
|
||||
}
|
||||
bool operator ! () const {
|
||||
return array_ == 0;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace zxing
|
127
src/qzxing/zxing/common/BitArray.cpp
Normal file
127
src/qzxing/zxing/common/BitArray.cpp
Normal file
|
@ -0,0 +1,127 @@
|
|||
// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
|
||||
/*
|
||||
* Copyright 2010 ZXing authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <zxing/common/BitArray.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace zxing {
|
||||
|
||||
|
||||
size_t BitArray::wordsForBits(size_t bits) {
|
||||
int arraySize = (bits + bitsPerWord_ - 1) >> logBits_;
|
||||
return arraySize;
|
||||
}
|
||||
|
||||
BitArray::BitArray(size_t size) :
|
||||
size_(size), bits_(wordsForBits(size), (const unsigned int)0) {
|
||||
}
|
||||
|
||||
BitArray::~BitArray() {
|
||||
}
|
||||
|
||||
size_t BitArray::getSize() {
|
||||
return size_;
|
||||
}
|
||||
|
||||
void BitArray::setBulk(size_t i, unsigned int newBits) {
|
||||
bits_[i >> logBits_] = newBits;
|
||||
}
|
||||
|
||||
void BitArray::setRange(int start, int end) {
|
||||
if (end < start) {
|
||||
throw IllegalArgumentException("invalid call to BitArray::setRange");
|
||||
}
|
||||
if (end == start) {
|
||||
return;
|
||||
}
|
||||
end--; // will be easier to treat this as the last actually set bit -- inclusive
|
||||
int firstInt = start >> 5;
|
||||
int lastInt = end >> 5;
|
||||
for (int i = firstInt; i <= lastInt; i++) {
|
||||
int firstBit = i > firstInt ? 0 : start & 0x1F;
|
||||
int lastBit = i < lastInt ? 31 : end & 0x1F;
|
||||
int mask;
|
||||
if (firstBit == 0 && lastBit == 31) {
|
||||
mask = -1;
|
||||
} else {
|
||||
mask = 0;
|
||||
for (int j = firstBit; j <= lastBit; j++) {
|
||||
mask |= 1 << j;
|
||||
}
|
||||
}
|
||||
bits_[i] |= mask;
|
||||
}
|
||||
}
|
||||
|
||||
void BitArray::clear() {
|
||||
size_t max = bits_.size();
|
||||
for (size_t i = 0; i < max; i++) {
|
||||
bits_[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool BitArray::isRange(size_t start, size_t end, bool value) {
|
||||
if (end < start) {
|
||||
throw IllegalArgumentException("end must be after start");
|
||||
}
|
||||
if (end == start) {
|
||||
return true;
|
||||
}
|
||||
// treat the 'end' as inclusive, rather than exclusive
|
||||
end--;
|
||||
size_t firstWord = start >> logBits_;
|
||||
size_t lastWord = end >> logBits_;
|
||||
for (size_t i = firstWord; i <= lastWord; i++) {
|
||||
size_t firstBit = i > firstWord ? 0 : start & bitsMask_;
|
||||
size_t lastBit = i < lastWord ? bitsPerWord_ - 1: end & bitsMask_;
|
||||
unsigned int mask;
|
||||
if (firstBit == 0 && lastBit == bitsPerWord_ - 1) {
|
||||
mask = numeric_limits<unsigned int>::max();
|
||||
} else {
|
||||
mask = 0;
|
||||
for (size_t j = firstBit; j <= lastBit; j++) {
|
||||
mask |= 1 << j;
|
||||
}
|
||||
}
|
||||
if (value) {
|
||||
if ((bits_[i] & mask) != mask) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if ((bits_[i] & mask) != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
vector<unsigned int>& BitArray::getBitArray() {
|
||||
return bits_;
|
||||
}
|
||||
|
||||
void BitArray::reverse() {
|
||||
std::vector<unsigned int> newBits(bits_.size(),(const unsigned int) 0);
|
||||
for (size_t i = 0; i < size_; i++) {
|
||||
if (get(size_ - i - 1)) {
|
||||
newBits[i >> logBits_] |= 1<< (i & bitsMask_);
|
||||
}
|
||||
}
|
||||
bits_ = newBits;
|
||||
}
|
||||
}
|
|
@ -18,64 +18,53 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <zxing/ZXing.h>
|
||||
#include <zxing/common/Counted.h>
|
||||
#include <zxing/common/IllegalArgumentException.h>
|
||||
#include <zxing/common/Array.h>
|
||||
#include <vector>
|
||||
#include <limits>
|
||||
#include <iostream>
|
||||
|
||||
namespace zxing {
|
||||
|
||||
#define ZX_LOG_DIGITS(digits) \
|
||||
((digits == 8) ? 3 : \
|
||||
((digits == 16) ? 4 : \
|
||||
((digits == 32) ? 5 : \
|
||||
((digits == 64) ? 6 : \
|
||||
((digits == 128) ? 7 : \
|
||||
(-1))))))
|
||||
|
||||
class BitArray : public Counted {
|
||||
public:
|
||||
static const int bitsPerWord = std::numeric_limits<unsigned int>::digits;
|
||||
|
||||
private:
|
||||
int size;
|
||||
ArrayRef<int> bits;
|
||||
static const int logBits = ZX_LOG_DIGITS(bitsPerWord);
|
||||
static const int bitsMask = (1 << logBits) - 1;
|
||||
size_t size_;
|
||||
std::vector<unsigned int> bits_;
|
||||
static const unsigned int bitsPerWord_ =
|
||||
std::numeric_limits<unsigned int>::digits;
|
||||
static const unsigned int logBits_ = ZX_LOG_DIGITS(bitsPerWord_);
|
||||
static const unsigned int bitsMask_ = (1 << logBits_) - 1;
|
||||
static size_t wordsForBits(size_t bits);
|
||||
explicit BitArray();
|
||||
|
||||
public:
|
||||
BitArray(int size);
|
||||
BitArray(size_t size);
|
||||
~BitArray();
|
||||
int getSize() const;
|
||||
size_t getSize();
|
||||
|
||||
bool get(int i) const {
|
||||
return (bits[i >> logBits] & (1 << (i & bitsMask))) != 0;
|
||||
bool get(size_t i) {
|
||||
return (bits_[i >> logBits_] & (1 << (i & bitsMask_))) != 0;
|
||||
}
|
||||
|
||||
void set(int i) {
|
||||
bits[i >> logBits] |= 1 << (i & bitsMask);
|
||||
void set(size_t i) {
|
||||
bits_[i >> logBits_] |= 1 << (i & bitsMask_);
|
||||
}
|
||||
|
||||
int getNextSet(int from);
|
||||
int getNextUnset(int from);
|
||||
|
||||
void setBulk(int i, int newBits);
|
||||
void setBulk(size_t i, unsigned int newBits);
|
||||
void setRange(int start, int end);
|
||||
void clear();
|
||||
bool isRange(int start, int end, bool value);
|
||||
std::vector<int>& getBitArray();
|
||||
|
||||
bool isRange(size_t start, size_t end, bool value);
|
||||
std::vector<unsigned int>& getBitArray();
|
||||
void reverse();
|
||||
|
||||
class Reverse {
|
||||
private:
|
||||
Ref<BitArray> array;
|
||||
public:
|
||||
Reverse(Ref<BitArray> array);
|
||||
~Reverse();
|
||||
};
|
||||
|
||||
private:
|
||||
static int makeArraySize(int size);
|
||||
};
|
||||
|
||||
std::ostream& operator << (std::ostream&, BitArray const&);
|
||||
|
||||
}
|
||||
|
||||
#endif // __BIT_ARRAY_H__
|
157
src/qzxing/zxing/common/BitMatrix.cpp
Normal file
157
src/qzxing/zxing/common/BitMatrix.cpp
Normal file
|
@ -0,0 +1,157 @@
|
|||
// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
|
||||
/*
|
||||
* Copyright 2010 ZXing authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <zxing/common/BitMatrix.h>
|
||||
#include <zxing/common/IllegalArgumentException.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
using std::ostream;
|
||||
using std::ostringstream;
|
||||
|
||||
using zxing::BitMatrix;
|
||||
using zxing::BitArray;
|
||||
using zxing::Ref;
|
||||
|
||||
namespace {
|
||||
size_t wordsForSize(size_t width,
|
||||
size_t height,
|
||||
unsigned int bitsPerWord,
|
||||
unsigned int logBits) {
|
||||
size_t bits = width * height;
|
||||
int arraySize = (bits + bitsPerWord - 1) >> logBits;
|
||||
return arraySize;
|
||||
}
|
||||
}
|
||||
|
||||
BitMatrix::BitMatrix(size_t dimension) :
|
||||
width_(dimension), height_(dimension), words_(0), bits_(NULL) {
|
||||
words_ = wordsForSize(width_, height_, bitsPerWord, logBits);
|
||||
bits_ = new unsigned int[words_];
|
||||
clear();
|
||||
}
|
||||
|
||||
BitMatrix::BitMatrix(size_t width, size_t height) :
|
||||
width_(width), height_(height), words_(0), bits_(NULL) {
|
||||
words_ = wordsForSize(width_, height_, bitsPerWord, logBits);
|
||||
bits_ = new unsigned int[words_];
|
||||
clear();
|
||||
}
|
||||
|
||||
BitMatrix::~BitMatrix() {
|
||||
delete[] bits_;
|
||||
}
|
||||
|
||||
|
||||
void BitMatrix::flip(size_t x, size_t y) {
|
||||
size_t offset = x + width_ * y;
|
||||
bits_[offset >> logBits] ^= 1 << (offset & bitsMask);
|
||||
}
|
||||
|
||||
void BitMatrix::clear() {
|
||||
std::fill(bits_, bits_+words_, 0);
|
||||
}
|
||||
|
||||
void BitMatrix::setRegion(size_t left, size_t top, size_t width, size_t height) {
|
||||
if ((long)top < 0 || (long)left < 0) {
|
||||
throw IllegalArgumentException("topI and leftJ must be nonnegative");
|
||||
}
|
||||
if (height < 1 || width < 1) {
|
||||
throw IllegalArgumentException("height and width must be at least 1");
|
||||
}
|
||||
size_t right = left + width;
|
||||
size_t bottom = top + height;
|
||||
if (right > width_ || bottom > height_) {
|
||||
throw IllegalArgumentException("top + height and left + width must be <= matrix dimension");
|
||||
}
|
||||
for (size_t y = top; y < bottom; y++) {
|
||||
int yOffset = width_ * y;
|
||||
for (size_t x = left; x < right; x++) {
|
||||
size_t offset = x + yOffset;
|
||||
bits_[offset >> logBits] |= 1 << (offset & bitsMask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ref<BitArray> BitMatrix::getRow(int y, Ref<BitArray> row) {
|
||||
if (row.empty() || row->getSize() < width_) {
|
||||
row = new BitArray(width_);
|
||||
} else {
|
||||
row->clear();
|
||||
}
|
||||
size_t start = y * width_;
|
||||
size_t end = start + width_ - 1; // end is inclusive
|
||||
size_t firstWord = start >> logBits;
|
||||
size_t lastWord = end >> logBits;
|
||||
size_t bitOffset = start & bitsMask;
|
||||
for (size_t i = firstWord; i <= lastWord; i++) {
|
||||
size_t firstBit = i > firstWord ? 0 : start & bitsMask;
|
||||
size_t lastBit = i < lastWord ? bitsPerWord - 1 : end & bitsMask;
|
||||
unsigned int mask;
|
||||
if (firstBit == 0 && lastBit == logBits) {
|
||||
mask = std::numeric_limits<unsigned int>::max();
|
||||
} else {
|
||||
mask = 0;
|
||||
for (size_t j = firstBit; j <= lastBit; j++) {
|
||||
mask |= 1 << j;
|
||||
}
|
||||
}
|
||||
row->setBulk((i - firstWord) << logBits, (bits_[i] & mask) >> bitOffset);
|
||||
if (firstBit == 0 && bitOffset != 0) {
|
||||
unsigned int prevBulk = row->getBitArray()[i - firstWord - 1];
|
||||
prevBulk |= (bits_[i] & mask) << (bitsPerWord - bitOffset);
|
||||
row->setBulk((i - firstWord - 1) << logBits, prevBulk);
|
||||
}
|
||||
}
|
||||
return row;
|
||||
}
|
||||
|
||||
size_t BitMatrix::getWidth() const {
|
||||
return width_;
|
||||
}
|
||||
|
||||
size_t BitMatrix::getHeight() const {
|
||||
return height_;
|
||||
}
|
||||
|
||||
size_t BitMatrix::getDimension() const {
|
||||
return width_;
|
||||
}
|
||||
|
||||
unsigned int* BitMatrix::getBits() const {
|
||||
return bits_;
|
||||
}
|
||||
|
||||
namespace zxing {
|
||||
ostream& operator<<(ostream &out, const BitMatrix &bm) {
|
||||
for (size_t y = 0; y < bm.height_; y++) {
|
||||
for (size_t x = 0; x < bm.width_; x++) {
|
||||
out << (bm.get(x, y) ? "X " : " ");
|
||||
}
|
||||
out << "\n";
|
||||
}
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
const char* BitMatrix::description() {
|
||||
ostringstream out;
|
||||
out << *this;
|
||||
return out.str().c_str();
|
||||
}
|
|
@ -23,20 +23,16 @@
|
|||
|
||||
#include <zxing/common/Counted.h>
|
||||
#include <zxing/common/BitArray.h>
|
||||
#include <zxing/common/Array.h>
|
||||
#include <limits>
|
||||
|
||||
namespace zxing {
|
||||
|
||||
class BitMatrix : public Counted {
|
||||
public:
|
||||
static const int bitsPerWord = std::numeric_limits<unsigned int>::digits;
|
||||
|
||||
private:
|
||||
int width;
|
||||
int height;
|
||||
int rowSize;
|
||||
ArrayRef<int> bits;
|
||||
size_t width_;
|
||||
size_t height_;
|
||||
size_t words_;
|
||||
unsigned int* bits_;
|
||||
|
||||
#define ZX_LOG_DIGITS(digits) \
|
||||
((digits == 8) ? 3 : \
|
||||
|
@ -46,42 +42,42 @@ private:
|
|||
((digits == 128) ? 7 : \
|
||||
(-1))))))
|
||||
|
||||
static const int logBits = ZX_LOG_DIGITS(bitsPerWord);
|
||||
static const int bitsMask = (1 << logBits) - 1;
|
||||
static const unsigned int bitsPerWord =
|
||||
std::numeric_limits<unsigned int>::digits;
|
||||
static const unsigned int logBits = ZX_LOG_DIGITS(bitsPerWord);
|
||||
static const unsigned int bitsMask = (1 << logBits) - 1;
|
||||
|
||||
public:
|
||||
BitMatrix(int dimension);
|
||||
BitMatrix(int width, int height);
|
||||
BitMatrix(size_t dimension);
|
||||
BitMatrix(size_t width, size_t height);
|
||||
|
||||
~BitMatrix();
|
||||
|
||||
bool get(int x, int y) const {
|
||||
int offset = y * rowSize + (x >> logBits);
|
||||
return ((((unsigned)bits[offset]) >> (x & bitsMask)) & 1) != 0;
|
||||
bool get(size_t x, size_t y) const {
|
||||
size_t offset = x + width_ * y;
|
||||
return ((bits_[offset >> logBits] >> (offset & bitsMask)) & 0x01) != 0;
|
||||
}
|
||||
|
||||
void set(int x, int y) {
|
||||
int offset = y * rowSize + (x >> logBits);
|
||||
bits[offset] |= 1 << (x & bitsMask);
|
||||
void set(size_t x, size_t y) {
|
||||
size_t offset = x + width_ * y;
|
||||
bits_[offset >> logBits] |= 1 << (offset & bitsMask);
|
||||
}
|
||||
|
||||
void flip(int x, int y);
|
||||
void flip(size_t x, size_t y);
|
||||
void clear();
|
||||
void setRegion(int left, int top, int width, int height);
|
||||
void setRegion(size_t left, size_t top, size_t width, size_t height);
|
||||
Ref<BitArray> getRow(int y, Ref<BitArray> row);
|
||||
|
||||
int getWidth() const;
|
||||
int getHeight() const;
|
||||
size_t getDimension() const;
|
||||
size_t getWidth() const;
|
||||
size_t getHeight() const;
|
||||
|
||||
ArrayRef<int> getTopLeftOnBit() const;
|
||||
ArrayRef<int> getBottomRightOnBit() const;
|
||||
unsigned int* getBits() const;
|
||||
|
||||
friend std::ostream& operator<<(std::ostream &out, const BitMatrix &bm);
|
||||
const char *description();
|
||||
|
||||
private:
|
||||
inline void init(int, int);
|
||||
|
||||
BitMatrix(const BitMatrix&);
|
||||
BitMatrix& operator =(const BitMatrix&);
|
||||
};
|
|
@ -1,4 +1,3 @@
|
|||
// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
|
||||
/*
|
||||
* BitSource.cpp
|
||||
* zxing
|
||||
|
@ -20,16 +19,15 @@
|
|||
*/
|
||||
|
||||
#include <zxing/common/BitSource.h>
|
||||
#include <sstream>
|
||||
#include <zxing/common/IllegalArgumentException.h>
|
||||
|
||||
namespace zxing {
|
||||
|
||||
int BitSource::readBits(int numBits) {
|
||||
if (numBits < 0 || numBits > 32 || numBits > available()) {
|
||||
std::ostringstream oss;
|
||||
oss << numBits;
|
||||
throw IllegalArgumentException(oss.str().c_str());
|
||||
if (numBits < 0 || numBits > 32) {
|
||||
throw IllegalArgumentException("cannot read <1 or >32 bits");
|
||||
} else if (numBits > available()) {
|
||||
throw IllegalArgumentException("reading more bits than are available");
|
||||
}
|
||||
|
||||
int result = 0;
|
||||
|
@ -71,6 +69,6 @@ int BitSource::readBits(int numBits) {
|
|||
}
|
||||
|
||||
int BitSource::available() {
|
||||
return 8 * (bytes_->size() - byteOffset_) - bitOffset_;
|
||||
return 8 * (bytes_.size() - byteOffset_) - bitOffset_;
|
||||
}
|
||||
}
|
|
@ -33,7 +33,7 @@ namespace zxing {
|
|||
* @author christian.brunschen@gmail.com (Christian Brunschen)
|
||||
*/
|
||||
class BitSource : public Counted {
|
||||
typedef char byte;
|
||||
typedef unsigned char byte;
|
||||
private:
|
||||
ArrayRef<byte> bytes_;
|
||||
int byteOffset_;
|
||||
|
@ -47,10 +47,6 @@ public:
|
|||
bytes_(bytes), byteOffset_(0), bitOffset_(0) {
|
||||
}
|
||||
|
||||
int getBitOffset() {
|
||||
return bitOffset_;
|
||||
}
|
||||
|
||||
int getByteOffset() {
|
||||
return byteOffset_;
|
||||
}
|
|
@ -23,9 +23,12 @@
|
|||
#include <zxing/DecodeHints.h>
|
||||
|
||||
namespace zxing {
|
||||
namespace common {
|
||||
namespace common {
|
||||
class CharacterSetECI;
|
||||
}
|
||||
}
|
||||
|
||||
class CharacterSetECI {
|
||||
class zxing::common::CharacterSetECI {
|
||||
private:
|
||||
static std::map<int, CharacterSetECI*> VALUE_TO_ECI;
|
||||
static std::map<std::string, CharacterSetECI*> NAME_TO_ECI;
|
||||
|
@ -47,7 +50,4 @@ public:
|
|||
static CharacterSetECI* getCharacterSetECIByName(std::string const& name);
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,6 +1,9 @@
|
|||
// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
|
||||
/*
|
||||
* Copyright 2010 ZXing authors. All rights reserved.
|
||||
* Counted.cpp
|
||||
* zxing
|
||||
*
|
||||
* Created by Christian Brunschen on 07/05/2008.
|
||||
* Copyright 2008 Google UK. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -15,17 +18,15 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <zxing/common/BitArray.h>
|
||||
#include <zxing/common/Counted.h>
|
||||
|
||||
using zxing::BitArray;
|
||||
using std::ostream;
|
||||
namespace zxing {
|
||||
|
||||
ostream& zxing::operator << (ostream& os, BitArray const& ba) {
|
||||
for (int i = 0, size = ba.getSize(); i < size; i++) {
|
||||
if ((i & 0x07) == 0) {
|
||||
os << ' ';
|
||||
}
|
||||
os << (ba.get(i) ? 'X' : '.');
|
||||
}
|
||||
return os;
|
||||
using namespace std;
|
||||
|
||||
template<class T>
|
||||
ostream& operator<<(ostream &out, Ref<T>& ref) {
|
||||
out << "Ref(" << (ref.object_ ? (*ref.object_) : "NULL") << ")";
|
||||
return out;
|
||||
}
|
||||
}
|
|
@ -18,8 +18,14 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
//#define DEBUG_COUNTING
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#ifdef DEBUG_COUNTING
|
||||
#include <typeinfo>
|
||||
#endif
|
||||
|
||||
namespace zxing {
|
||||
|
||||
/* base class for reference-counted objects */
|
||||
|
@ -29,16 +35,43 @@ private:
|
|||
public:
|
||||
Counted() :
|
||||
count_(0) {
|
||||
#ifdef DEBUG_COUNTING
|
||||
cout << "instantiating " << typeid(*this).name() << " " << this <<
|
||||
" @ " << count_ << "\n";
|
||||
#endif
|
||||
}
|
||||
virtual ~Counted() {
|
||||
}
|
||||
Counted *retain() {
|
||||
#ifdef DEBUG_COUNTING
|
||||
cout << "retaining " << typeid(*this).name() << " " << this <<
|
||||
" @ " << count_;
|
||||
#endif
|
||||
count_++;
|
||||
#ifdef DEBUG_COUNTING
|
||||
cout << "->" << count_ << "\n";
|
||||
#endif
|
||||
return this;
|
||||
}
|
||||
void release() {
|
||||
#ifdef DEBUG_COUNTING
|
||||
cout << "releasing " << typeid(*this).name() << " " << this <<
|
||||
" @ " << count_;
|
||||
#endif
|
||||
if (count_ == 0 || count_ == 54321) {
|
||||
#ifdef DEBUG_COUNTING
|
||||
cout << "\nOverreleasing already-deleted object " << this << "!!!\n";
|
||||
#endif
|
||||
throw 4711;
|
||||
}
|
||||
count_--;
|
||||
#ifdef DEBUG_COUNTING
|
||||
cout << "->" << count_ << "\n";
|
||||
#endif
|
||||
if (count_ == 0) {
|
||||
#ifdef DEBUG_COUNTING
|
||||
cout << "deleting " << typeid(*this).name() << " " << this << "\n";
|
||||
#endif
|
||||
count_ = 0xDEADF001;
|
||||
delete this;
|
||||
}
|
||||
|
@ -58,26 +91,53 @@ public:
|
|||
T *object_;
|
||||
explicit Ref(T *o = 0) :
|
||||
object_(0) {
|
||||
#ifdef DEBUG_COUNTING
|
||||
cout << "instantiating Ref " << this << " from pointer" << o << "\n";
|
||||
#endif
|
||||
reset(o);
|
||||
}
|
||||
|
||||
explicit Ref(const T &o) :
|
||||
object_(0) {
|
||||
#ifdef DEBUG_COUNTING
|
||||
cout << "instantiating Ref " << this << " from reference\n";
|
||||
#endif
|
||||
reset(const_cast<T *>(&o));
|
||||
}
|
||||
|
||||
Ref(const Ref &other) :
|
||||
object_(0) {
|
||||
#ifdef DEBUG_COUNTING
|
||||
cout << "instantiating Ref " << this << " from Ref " << &other << "\n";
|
||||
#endif
|
||||
reset(other.object_);
|
||||
}
|
||||
|
||||
template<class Y>
|
||||
Ref(const Ref<Y> &other) :
|
||||
object_(0) {
|
||||
#ifdef DEBUG_COUNTING
|
||||
cout << "instantiating Ref " << this << " from reference\n";
|
||||
#endif
|
||||
reset(other.object_);
|
||||
}
|
||||
|
||||
~Ref() {
|
||||
#ifdef DEBUG_COUNTING
|
||||
cout << "destroying Ref " << this << " with " <<
|
||||
(object_ ? typeid(*object_).name() : "NULL") << " " << object_ << "\n";
|
||||
#endif
|
||||
if (object_) {
|
||||
object_->release();
|
||||
}
|
||||
}
|
||||
|
||||
void reset(T *o) {
|
||||
#ifdef DEBUG_COUNTING
|
||||
cout << "resetting Ref " << this << " from " <<
|
||||
(object_ ? typeid(*object_).name() : "NULL") << " " << object_ <<
|
||||
" to " << (o ? typeid(*o).name() : "NULL") << " " << o << "\n";
|
||||
#endif
|
||||
if (o) {
|
||||
o->retain();
|
||||
}
|
||||
|
@ -133,8 +193,10 @@ public:
|
|||
bool empty() const {
|
||||
return object_ == 0;
|
||||
}
|
||||
};
|
||||
|
||||
template<class Y>
|
||||
friend std::ostream& operator<<(std::ostream &out, Ref<Y>& ref);
|
||||
};
|
||||
}
|
||||
|
||||
#endif // __COUNTED_H__
|
|
@ -24,20 +24,20 @@
|
|||
using namespace std;
|
||||
using namespace zxing;
|
||||
|
||||
DecoderResult::DecoderResult(ArrayRef<char> rawBytes,
|
||||
DecoderResult::DecoderResult(ArrayRef<unsigned char> rawBytes,
|
||||
Ref<String> text,
|
||||
ArrayRef< ArrayRef<char> >& byteSegments,
|
||||
ArrayRef< ArrayRef<unsigned char> >& byteSegments,
|
||||
string const& ecLevel) :
|
||||
rawBytes_(rawBytes),
|
||||
text_(text),
|
||||
byteSegments_(byteSegments),
|
||||
ecLevel_(ecLevel) {}
|
||||
|
||||
DecoderResult::DecoderResult(ArrayRef<char> rawBytes,
|
||||
DecoderResult::DecoderResult(ArrayRef<unsigned char> rawBytes,
|
||||
Ref<String> text)
|
||||
: rawBytes_(rawBytes), text_(text) {}
|
||||
|
||||
ArrayRef<char> DecoderResult::getRawBytes() {
|
||||
ArrayRef<unsigned char> DecoderResult::getRawBytes() {
|
||||
return rawBytes_;
|
||||
}
|
||||
|
|
@ -29,20 +29,20 @@ namespace zxing {
|
|||
|
||||
class DecoderResult : public Counted {
|
||||
private:
|
||||
ArrayRef<char> rawBytes_;
|
||||
ArrayRef<unsigned char> rawBytes_;
|
||||
Ref<String> text_;
|
||||
ArrayRef< ArrayRef<char> > byteSegments_;
|
||||
ArrayRef< ArrayRef<unsigned char> > byteSegments_;
|
||||
std::string ecLevel_;
|
||||
|
||||
public:
|
||||
DecoderResult(ArrayRef<char> rawBytes,
|
||||
DecoderResult(ArrayRef<unsigned char> rawBytes,
|
||||
Ref<String> text,
|
||||
ArrayRef< ArrayRef<char> >& byteSegments,
|
||||
ArrayRef< ArrayRef<unsigned char> >& byteSegments,
|
||||
std::string const& ecLevel);
|
||||
|
||||
DecoderResult(ArrayRef<char> rawBytes, Ref<String> text);
|
||||
DecoderResult(ArrayRef<unsigned char> rawBytes, Ref<String> text);
|
||||
|
||||
ArrayRef<char> getRawBytes();
|
||||
ArrayRef<unsigned char> getRawBytes();
|
||||
Ref<String> getText();
|
||||
};
|
||||
|
|
@ -23,16 +23,15 @@
|
|||
|
||||
namespace zxing {
|
||||
|
||||
DetectorResult::DetectorResult(Ref<BitMatrix> bits,
|
||||
ArrayRef< Ref<ResultPoint> > points)
|
||||
: bits_(bits), points_(points) {
|
||||
DetectorResult::DetectorResult(Ref<BitMatrix> bits, std::vector<Ref<ResultPoint> > points) :
|
||||
bits_(bits), points_(points) {
|
||||
}
|
||||
|
||||
Ref<BitMatrix> DetectorResult::getBits() {
|
||||
return bits_;
|
||||
}
|
||||
|
||||
ArrayRef< Ref<ResultPoint> > DetectorResult::getPoints() {
|
||||
std::vector<Ref<ResultPoint> > DetectorResult::getPoints() {
|
||||
return points_;
|
||||
}
|
||||
|
|
@ -20,6 +20,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <vector>
|
||||
#include <zxing/common/Counted.h>
|
||||
#include <zxing/common/Array.h>
|
||||
#include <zxing/common/BitMatrix.h>
|
||||
|
@ -30,14 +31,13 @@ namespace zxing {
|
|||
class DetectorResult : public Counted {
|
||||
private:
|
||||
Ref<BitMatrix> bits_;
|
||||
ArrayRef< Ref<ResultPoint> > points_;
|
||||
std::vector<Ref<ResultPoint> > points_;
|
||||
|
||||
public:
|
||||
DetectorResult(Ref<BitMatrix> bits, ArrayRef< Ref<ResultPoint> > points);
|
||||
DetectorResult(Ref<BitMatrix> bits, std::vector<Ref<ResultPoint> > points);
|
||||
Ref<BitMatrix> getBits();
|
||||
ArrayRef< Ref<ResultPoint> > getPoints();
|
||||
std::vector<Ref<ResultPoint> > getPoints();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // __DETECTOR_RESULT_H__
|
191
src/qzxing/zxing/common/EdgeDetector.cpp
Normal file
191
src/qzxing/zxing/common/EdgeDetector.cpp
Normal file
|
@ -0,0 +1,191 @@
|
|||
/*
|
||||
* EdgeDetector.cpp
|
||||
* zxing
|
||||
*
|
||||
* Created by Ralf Kistner on 7/12/2009.
|
||||
* Copyright 2008 ZXing authors All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <zxing/common/EdgeDetector.h>
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace zxing {
|
||||
namespace EdgeDetector {
|
||||
|
||||
void findEdgePoints(std::vector<Point>& points, const BitMatrix& image, Point start, Point end, bool invert, int skip, float deviation) {
|
||||
float xdist = end.x - start.x;
|
||||
float ydist = end.y - start.y;
|
||||
float length = sqrt(xdist * xdist + ydist * ydist);
|
||||
|
||||
|
||||
int var;
|
||||
|
||||
if (abs(xdist) > abs(ydist)) {
|
||||
// Horizontal
|
||||
if (xdist < 0)
|
||||
skip = -skip;
|
||||
|
||||
var = int(abs(deviation * length / xdist));
|
||||
|
||||
float dy = ydist / xdist * skip;
|
||||
bool left = (skip < 0) ^ invert;
|
||||
int x = int(start.x);
|
||||
|
||||
int steps = int(xdist / skip);
|
||||
for (int i = 0; i < steps; i++) {
|
||||
x += skip;
|
||||
if (x < 0 || x >= (int)image.getWidth())
|
||||
continue; // In case we start off the edge
|
||||
int my = int(start.y + dy * i);
|
||||
int ey = min(my + var + 1, (int)image.getHeight() - 1);
|
||||
int sy = max(my - var, 0);
|
||||
for (int y = sy + 1; y < ey; y++) {
|
||||
if (left) {
|
||||
if (image.get(x, y) && !image.get(x, y + 1)) {
|
||||
points.push_back(Point(x, y + 0.5f));
|
||||
}
|
||||
} else {
|
||||
if (!image.get(x, y) && image.get(x, y + 1)) {
|
||||
points.push_back(Point(x, y + 0.5f));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Vertical
|
||||
if (ydist < 0)
|
||||
skip = -skip;
|
||||
|
||||
var = int(abs(deviation * length / ydist));
|
||||
|
||||
float dx = xdist / ydist * skip;
|
||||
bool down = (skip > 0) ^ invert;
|
||||
int y = int(start.y);
|
||||
|
||||
int steps = int(ydist / skip);
|
||||
for (int i = 0; i < steps; i++) {
|
||||
y += skip;
|
||||
if (y < 0 || y >= (int)image.getHeight())
|
||||
continue; // In case we start off the edge
|
||||
int mx = int(start.x + dx * i);
|
||||
int ex = min(mx + var + 1, (int)image.getWidth() - 1);
|
||||
int sx = max(mx - var, 0);
|
||||
for (int x = sx + 1; x < ex; x++) {
|
||||
if (down) {
|
||||
if (image.get(x, y) && !image.get(x + 1, y)) {
|
||||
points.push_back(Point(x + 0.5f, y));
|
||||
}
|
||||
|
||||
} else {
|
||||
if (!image.get(x, y) && image.get(x + 1, y)) {
|
||||
points.push_back(Point(x + 0.5f, y));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Line findLine(const BitMatrix& image, Line estimate, bool invert, int deviation, float threshold, int skip) {
|
||||
float t = threshold * threshold;
|
||||
|
||||
Point start = estimate.start;
|
||||
Point end = estimate.end;
|
||||
|
||||
vector<Point> edges;
|
||||
edges.clear();
|
||||
findEdgePoints(edges, image, start, end, invert, skip, deviation);
|
||||
|
||||
int n = edges.size();
|
||||
|
||||
float xdist = end.x - start.x;
|
||||
float ydist = end.y - start.y;
|
||||
|
||||
bool horizontal = abs(xdist) > abs(ydist);
|
||||
|
||||
float max = 0;
|
||||
Line bestLine(start, end); // prepopulate with the given line, in case we can't find any line for some reason
|
||||
|
||||
for (int i = -deviation; i < deviation; i++) {
|
||||
float x1, y1;
|
||||
if (horizontal) {
|
||||
y1 = start.y + i;
|
||||
x1 = start.x - i * ydist / xdist;
|
||||
} else {
|
||||
y1 = start.y - i * xdist / ydist;
|
||||
x1 = start.x + i;
|
||||
}
|
||||
|
||||
for (int j = -deviation; j < deviation; j++) {
|
||||
float x2, y2;
|
||||
if (horizontal) {
|
||||
y2 = end.y + j;
|
||||
x2 = end.x - j * ydist / xdist;
|
||||
} else {
|
||||
y2 = end.y - j * xdist / ydist;
|
||||
x2 = end.x + j;
|
||||
}
|
||||
|
||||
float dx = x1 - x2;
|
||||
float dy = y1 - y2;
|
||||
float length = sqrt(dx * dx + dy * dy);
|
||||
|
||||
float score = 0;
|
||||
|
||||
for(int k = 0; k < n; k++) {
|
||||
const Point& edge = edges[k];
|
||||
float dist = ((x1 - edge.x) * dy - (y1 - edge.y) * dx) / length;
|
||||
// Similar to least squares method
|
||||
float s = t - dist * dist;
|
||||
if (s > 0)
|
||||
score += s;
|
||||
}
|
||||
|
||||
if (score > max) {
|
||||
max = score;
|
||||
bestLine.start = Point(x1, y1);
|
||||
bestLine.end = Point(x2, y2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bestLine;
|
||||
}
|
||||
|
||||
Point intersection(Line a, Line b) {
|
||||
float dxa = a.start.x - a.end.x;
|
||||
float dxb = b.start.x - b.end.x;
|
||||
float dya = a.start.y - a.end.y;
|
||||
float dyb = b.start.y - b.end.y;
|
||||
|
||||
float p = a.start.x * a.end.y - a.start.y * a.end.x;
|
||||
float q = b.start.x * b.end.y - b.start.y * b.end.x;
|
||||
float denom = dxa * dyb - dya * dxb;
|
||||
if(denom == 0) // Lines don't intersect
|
||||
return Point(INFINITY, INFINITY);
|
||||
|
||||
float x = (p * dxb - dxa * q) / denom;
|
||||
float y = (p * dyb - dya * q) / denom;
|
||||
|
||||
return Point(x, y);
|
||||
}
|
||||
|
||||
} // namespace EdgeDetector
|
||||
} // namespace zxing
|
38
src/qzxing/zxing/common/EdgeDetector.h
Normal file
38
src/qzxing/zxing/common/EdgeDetector.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
#ifndef __EDGEDETECTOR_H__
|
||||
#define __EDGEDETECTOR_H__
|
||||
/*
|
||||
* EdgeDetector.h
|
||||
* zxing
|
||||
*
|
||||
* Copyright 2010 ZXing authors All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <vector>
|
||||
#include <zxing/common/BitMatrix.h>
|
||||
#include <zxing/common/Point.h>
|
||||
|
||||
namespace zxing {
|
||||
namespace EdgeDetector {
|
||||
|
||||
void findEdgePoints(std::vector<Point>& points, const BitMatrix& image, Point start, Point end, bool invert, int skip, float deviation);
|
||||
Line findLine(const BitMatrix& image, Line estimate, bool invert, int deviation, float threshold, int skip);
|
||||
|
||||
Point intersection(Line a, Line b);
|
||||
|
||||
}
|
||||
}
|
||||
#endif /* EDGEDETECTOR_H_ */
|
209
src/qzxing/zxing/common/GlobalHistogramBinarizer.cpp
Normal file
209
src/qzxing/zxing/common/GlobalHistogramBinarizer.cpp
Normal file
|
@ -0,0 +1,209 @@
|
|||
// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
|
||||
/*
|
||||
* GlobalHistogramBinarizer.cpp
|
||||
* zxing
|
||||
*
|
||||
* Copyright 2010 ZXing authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <zxing/common/GlobalHistogramBinarizer.h>
|
||||
#include <zxing/common/IllegalArgumentException.h>
|
||||
#include <zxing/common/Array.h>
|
||||
|
||||
namespace zxing {
|
||||
using namespace std;
|
||||
|
||||
const int LUMINANCE_BITS = 5;
|
||||
const int LUMINANCE_SHIFT = 8 - LUMINANCE_BITS;
|
||||
const int LUMINANCE_BUCKETS = 1 << LUMINANCE_BITS;
|
||||
|
||||
GlobalHistogramBinarizer::GlobalHistogramBinarizer(Ref<LuminanceSource> source) :
|
||||
Binarizer(source), cached_matrix_(NULL), cached_row_(NULL), cached_row_num_(-1) {
|
||||
|
||||
}
|
||||
|
||||
GlobalHistogramBinarizer::~GlobalHistogramBinarizer() {
|
||||
}
|
||||
|
||||
|
||||
Ref<BitArray> GlobalHistogramBinarizer::getBlackRow(int y, Ref<BitArray> row) {
|
||||
if (y == cached_row_num_) {
|
||||
if (cached_row_ != NULL) {
|
||||
return cached_row_;
|
||||
} else {
|
||||
throw IllegalArgumentException("Too little dynamic range in luminance");
|
||||
}
|
||||
}
|
||||
|
||||
vector<int> histogram(LUMINANCE_BUCKETS, 0);
|
||||
LuminanceSource& source = *getLuminanceSource();
|
||||
int width = source.getWidth();
|
||||
if (row == NULL || static_cast<int>(row->getSize()) < width) {
|
||||
row = new BitArray(width);
|
||||
} else {
|
||||
row->clear();
|
||||
}
|
||||
|
||||
//TODO(flyashi): cache this instead of allocating and deleting per row
|
||||
unsigned char* row_pixels = NULL;
|
||||
try {
|
||||
row_pixels = new unsigned char[width];
|
||||
row_pixels = source.getRow(y, row_pixels);
|
||||
for (int x = 0; x < width; x++) {
|
||||
histogram[row_pixels[x] >> LUMINANCE_SHIFT]++;
|
||||
}
|
||||
int blackPoint = estimate(histogram);
|
||||
|
||||
BitArray& array = *row;
|
||||
int left = row_pixels[0];
|
||||
int center = row_pixels[1];
|
||||
for (int x = 1; x < width - 1; x++) {
|
||||
int right = row_pixels[x + 1];
|
||||
// A simple -1 4 -1 box filter with a weight of 2.
|
||||
int luminance = ((center << 2) - left - right) >> 1;
|
||||
if (luminance < blackPoint) {
|
||||
array.set(x);
|
||||
}
|
||||
left = center;
|
||||
center = right;
|
||||
}
|
||||
|
||||
cached_row_ = row;
|
||||
cached_row_num_ = y;
|
||||
delete [] row_pixels;
|
||||
return row;
|
||||
} catch (IllegalArgumentException const& iae) {
|
||||
// Cache the fact that this row failed.
|
||||
cached_row_ = NULL;
|
||||
cached_row_num_ = y;
|
||||
delete [] row_pixels;
|
||||
throw iae;
|
||||
}
|
||||
}
|
||||
|
||||
Ref<BitMatrix> GlobalHistogramBinarizer::getBlackMatrix() {
|
||||
if (cached_matrix_ != NULL) {
|
||||
return cached_matrix_;
|
||||
}
|
||||
|
||||
// Faster than working with the reference
|
||||
LuminanceSource& source = *getLuminanceSource();
|
||||
int width = source.getWidth();
|
||||
int height = source.getHeight();
|
||||
vector<int> histogram(LUMINANCE_BUCKETS, 0);
|
||||
|
||||
// Quickly calculates the histogram by sampling four rows from the image.
|
||||
// This proved to be more robust on the blackbox tests than sampling a
|
||||
// diagonal as we used to do.
|
||||
ArrayRef<unsigned char> ref (width);
|
||||
unsigned char* row = &ref[0];
|
||||
for (int y = 1; y < 5; y++) {
|
||||
int rownum = height * y / 5;
|
||||
int right = (width << 2) / 5;
|
||||
row = source.getRow(rownum, row);
|
||||
for (int x = width / 5; x < right; x++) {
|
||||
histogram[row[x] >> LUMINANCE_SHIFT]++;
|
||||
}
|
||||
}
|
||||
|
||||
int blackPoint = estimate(histogram);
|
||||
|
||||
Ref<BitMatrix> matrix_ref(new BitMatrix(width, height));
|
||||
BitMatrix& matrix = *matrix_ref;
|
||||
for (int y = 0; y < height; y++) {
|
||||
row = source.getRow(y, row);
|
||||
for (int x = 0; x < width; x++) {
|
||||
if (row[x] < blackPoint)
|
||||
matrix.set(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
cached_matrix_ = matrix_ref;
|
||||
// delete [] row;
|
||||
return matrix_ref;
|
||||
}
|
||||
|
||||
int GlobalHistogramBinarizer::estimate(vector<int> &histogram) {
|
||||
int numBuckets = histogram.size();
|
||||
int maxBucketCount = 0;
|
||||
|
||||
// Find tallest peak in histogram
|
||||
int firstPeak = 0;
|
||||
int firstPeakSize = 0;
|
||||
for (int i = 0; i < numBuckets; i++) {
|
||||
if (histogram[i] > firstPeakSize) {
|
||||
firstPeak = i;
|
||||
firstPeakSize = histogram[i];
|
||||
}
|
||||
if (histogram[i] > maxBucketCount) {
|
||||
maxBucketCount = histogram[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Find second-tallest peak -- well, another peak that is tall and not
|
||||
// so close to the first one
|
||||
int secondPeak = 0;
|
||||
int secondPeakScore = 0;
|
||||
for (int i = 0; i < numBuckets; i++) {
|
||||
int distanceToBiggest = i - firstPeak;
|
||||
// Encourage more distant second peaks by multiplying by square of distance
|
||||
int score = histogram[i] * distanceToBiggest * distanceToBiggest;
|
||||
if (score > secondPeakScore) {
|
||||
secondPeak = i;
|
||||
secondPeakScore = score;
|
||||
}
|
||||
}
|
||||
|
||||
// Put firstPeak first
|
||||
if (firstPeak > secondPeak) {
|
||||
int temp = firstPeak;
|
||||
firstPeak = secondPeak;
|
||||
secondPeak = temp;
|
||||
}
|
||||
|
||||
// Kind of arbitrary; if the two peaks are very close, then we figure there is
|
||||
// so little dynamic range in the image, that discriminating black and white
|
||||
// is too error-prone.
|
||||
// Decoding the image/line is either pointless, or may in some cases lead to
|
||||
// a false positive for 1D formats, which are relatively lenient.
|
||||
// We arbitrarily say "close" is
|
||||
// "<= 1/16 of the total histogram buckets apart"
|
||||
if (secondPeak - firstPeak <= numBuckets >> 4) {
|
||||
throw IllegalArgumentException("Too little dynamic range in luminance");
|
||||
}
|
||||
|
||||
// Find a valley between them that is low and closer to the white peak
|
||||
int bestValley = secondPeak - 1;
|
||||
int bestValleyScore = -1;
|
||||
for (int i = secondPeak - 1; i > firstPeak; i--) {
|
||||
int fromFirst = i - firstPeak;
|
||||
// Favor a "valley" that is not too close to either peak -- especially not
|
||||
// the black peak -- and that has a low value of course
|
||||
int score = fromFirst * fromFirst * (secondPeak - i) *
|
||||
(maxBucketCount - histogram[i]);
|
||||
if (score > bestValleyScore) {
|
||||
bestValley = i;
|
||||
bestValleyScore = score;
|
||||
}
|
||||
}
|
||||
|
||||
return bestValley << LUMINANCE_SHIFT;
|
||||
}
|
||||
|
||||
Ref<Binarizer> GlobalHistogramBinarizer::createBinarizer(Ref<LuminanceSource> source) {
|
||||
return Ref<Binarizer> (new GlobalHistogramBinarizer(source));
|
||||
}
|
||||
|
||||
} // namespace zxing
|
|
@ -1,4 +1,3 @@
|
|||
// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
|
||||
#ifndef __GLOBALHISTOGRAMBINARIZER_H__
|
||||
#define __GLOBALHISTOGRAMBINARIZER_H__
|
||||
/*
|
||||
|
@ -20,28 +19,28 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <vector>
|
||||
#include <zxing/Binarizer.h>
|
||||
#include <zxing/common/BitArray.h>
|
||||
#include <zxing/common/BitMatrix.h>
|
||||
#include <zxing/common/Array.h>
|
||||
|
||||
namespace zxing {
|
||||
|
||||
class GlobalHistogramBinarizer : public Binarizer {
|
||||
private:
|
||||
ArrayRef<char> luminances;
|
||||
ArrayRef<int> buckets;
|
||||
public:
|
||||
GlobalHistogramBinarizer(Ref<LuminanceSource> source);
|
||||
virtual ~GlobalHistogramBinarizer();
|
||||
class GlobalHistogramBinarizer : public Binarizer {
|
||||
private:
|
||||
Ref<BitMatrix> cached_matrix_;
|
||||
Ref<BitArray> cached_row_;
|
||||
int cached_row_num_;
|
||||
|
||||
virtual Ref<BitArray> getBlackRow(int y, Ref<BitArray> row);
|
||||
virtual Ref<BitMatrix> getBlackMatrix();
|
||||
static int estimateBlackPoint(ArrayRef<int> const& buckets);
|
||||
Ref<Binarizer> createBinarizer(Ref<LuminanceSource> source);
|
||||
private:
|
||||
void initArrays(int luminanceSize);
|
||||
};
|
||||
public:
|
||||
GlobalHistogramBinarizer(Ref<LuminanceSource> source);
|
||||
virtual ~GlobalHistogramBinarizer();
|
||||
|
||||
virtual Ref<BitArray> getBlackRow(int y, Ref<BitArray> row);
|
||||
virtual Ref<BitMatrix> getBlackMatrix();
|
||||
static int estimate(std::vector<int> &histogram);
|
||||
Ref<Binarizer> createBinarizer(Ref<LuminanceSource> source);
|
||||
};
|
||||
|
||||
}
|
||||
|
70
src/qzxing/zxing/common/GreyscaleLuminanceSource.cpp
Normal file
70
src/qzxing/zxing/common/GreyscaleLuminanceSource.cpp
Normal file
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* GreyscaleLuminanceSource.cpp
|
||||
* zxing
|
||||
*
|
||||
* Copyright 2010 ZXing authors All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <zxing/common/GreyscaleLuminanceSource.h>
|
||||
#include <zxing/common/GreyscaleRotatedLuminanceSource.h>
|
||||
#include <zxing/common/IllegalArgumentException.h>
|
||||
|
||||
namespace zxing {
|
||||
|
||||
GreyscaleLuminanceSource::GreyscaleLuminanceSource(unsigned char* greyData, int dataWidth,
|
||||
int dataHeight, int left, int top, int width, int height) : greyData_(greyData),
|
||||
dataWidth_(dataWidth), dataHeight_(dataHeight), left_(left), top_(top), width_(width),
|
||||
height_(height) {
|
||||
|
||||
if (left + width > dataWidth || top + height > dataHeight || top < 0 || left < 0) {
|
||||
throw IllegalArgumentException("Crop rectangle does not fit within image data.");
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char* GreyscaleLuminanceSource::getRow(int y, unsigned char* row) {
|
||||
if (y < 0 || y >= this->getHeight()) {
|
||||
throw IllegalArgumentException("Requested row is outside the image.");
|
||||
}
|
||||
int width = getWidth();
|
||||
// TODO(flyashi): determine if row has enough size.
|
||||
if (row == NULL) {
|
||||
row = new unsigned char[width_];
|
||||
}
|
||||
int offset = (y + top_) * dataWidth_ + left_;
|
||||
memcpy(row, &greyData_[offset], width);
|
||||
return row;
|
||||
}
|
||||
|
||||
unsigned char* GreyscaleLuminanceSource::getMatrix() {
|
||||
int size = width_ * height_;
|
||||
unsigned char* result = new unsigned char[size];
|
||||
if (left_ == 0 && top_ == 0 && dataWidth_ == width_ && dataHeight_ == height_) {
|
||||
memcpy(result, greyData_, size);
|
||||
} else {
|
||||
for (int row = 0; row < height_; row++) {
|
||||
memcpy(result + row * width_, greyData_ + (top_ + row) * dataWidth_ + left_, width_);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Ref<LuminanceSource> GreyscaleLuminanceSource::rotateCounterClockwise() {
|
||||
// Intentionally flip the left, top, width, and height arguments as needed. dataWidth and
|
||||
// dataHeight are always kept unrotated.
|
||||
return Ref<LuminanceSource> (new GreyscaleRotatedLuminanceSource(greyData_, dataWidth_,
|
||||
dataHeight_, top_, left_, height_, width_));
|
||||
}
|
||||
|
||||
} /* namespace */
|
|
@ -1,4 +1,3 @@
|
|||
// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
|
||||
#ifndef __GREYSCALE_LUMINANCE_SOURCE__
|
||||
#define __GREYSCALE_LUMINANCE_SOURCE__
|
||||
/*
|
||||
|
@ -26,28 +25,38 @@ namespace zxing {
|
|||
|
||||
class GreyscaleLuminanceSource : public LuminanceSource {
|
||||
|
||||
private:
|
||||
typedef LuminanceSource Super;
|
||||
ArrayRef<char> greyData_;
|
||||
const int dataWidth_;
|
||||
const int dataHeight_;
|
||||
const int left_;
|
||||
const int top_;
|
||||
private:
|
||||
unsigned char* greyData_;
|
||||
int dataWidth_;
|
||||
int dataHeight_;
|
||||
int left_;
|
||||
int top_;
|
||||
int width_;
|
||||
int height_;
|
||||
|
||||
public:
|
||||
GreyscaleLuminanceSource(ArrayRef<char> greyData, int dataWidth, int dataHeight, int left,
|
||||
int top, int width, int height);
|
||||
public:
|
||||
GreyscaleLuminanceSource(unsigned char* greyData, int dataWidth, int dataHeight, int left,
|
||||
int top, int width, int height);
|
||||
|
||||
ArrayRef<char> getRow(int y, ArrayRef<char> row) const;
|
||||
ArrayRef<char> getMatrix() const;
|
||||
unsigned char* getRow(int y, unsigned char* row);
|
||||
unsigned char* getMatrix();
|
||||
|
||||
bool isRotateSupported() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
Ref<LuminanceSource> rotateCounterClockwise() const;
|
||||
int getWidth() const {
|
||||
return width_;
|
||||
}
|
||||
|
||||
int getHeight() const {
|
||||
return height_;
|
||||
}
|
||||
|
||||
Ref<LuminanceSource> rotateCounterClockwise();
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
} /* namespace */
|
||||
|
||||
#endif
|
65
src/qzxing/zxing/common/GreyscaleRotatedLuminanceSource.cpp
Normal file
65
src/qzxing/zxing/common/GreyscaleRotatedLuminanceSource.cpp
Normal file
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* GreyscaleRotatedLuminanceSource.cpp
|
||||
* zxing
|
||||
*
|
||||
* Copyright 2010 ZXing authors All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
#include <zxing/common/GreyscaleRotatedLuminanceSource.h>
|
||||
#include <zxing/common/IllegalArgumentException.h>
|
||||
|
||||
namespace zxing {
|
||||
|
||||
// Note that dataWidth and dataHeight are not reversed, as we need to be able to traverse the
|
||||
// greyData correctly, which does not get rotated.
|
||||
GreyscaleRotatedLuminanceSource::GreyscaleRotatedLuminanceSource(unsigned char* greyData,
|
||||
int dataWidth, int dataHeight, int left, int top, int width, int height) : greyData_(greyData),
|
||||
dataWidth_(dataWidth), dataHeight_(dataHeight), left_(left), top_(top), width_(width),
|
||||
height_(height) {
|
||||
|
||||
// Intentionally comparing to the opposite dimension since we're rotated.
|
||||
if (left + width > dataHeight || top + height > dataWidth) {
|
||||
throw IllegalArgumentException("Crop rectangle does not fit within image data.");
|
||||
}
|
||||
}
|
||||
|
||||
// The API asks for rows, but we're rotated, so we return columns.
|
||||
unsigned char* GreyscaleRotatedLuminanceSource::getRow(int y, unsigned char* row) {
|
||||
if (y < 0 || y >= getHeight()) {
|
||||
throw IllegalArgumentException("Requested row is outside the image.");
|
||||
}
|
||||
int width = getWidth();
|
||||
if (row == NULL) {
|
||||
row = new unsigned char[width];
|
||||
}
|
||||
int offset = (left_ * dataWidth_) + (dataWidth_ - (y + top_));
|
||||
for (int x = 0; x < width; x++) {
|
||||
row[x] = greyData_[offset];
|
||||
offset += dataWidth_;
|
||||
}
|
||||
return row;
|
||||
}
|
||||
|
||||
unsigned char* GreyscaleRotatedLuminanceSource::getMatrix() {
|
||||
unsigned char* result = new unsigned char[width_ * height_];
|
||||
// This depends on getRow() honoring its second parameter.
|
||||
for (int y = 0; y < height_; y++) {
|
||||
getRow(y, &result[y * width_]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace
|
|
@ -1,4 +1,3 @@
|
|||
// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
|
||||
#ifndef __GREYSCALE_ROTATED_LUMINANCE_SOURCE__
|
||||
#define __GREYSCALE_ROTATED_LUMINANCE_SOURCE__
|
||||
/*
|
||||
|
@ -27,20 +26,35 @@ namespace zxing {
|
|||
|
||||
class GreyscaleRotatedLuminanceSource : public LuminanceSource {
|
||||
private:
|
||||
typedef LuminanceSource Super;
|
||||
ArrayRef<char> greyData_;
|
||||
const int dataWidth_;
|
||||
const int left_;
|
||||
const int top_;
|
||||
unsigned char* greyData_;
|
||||
int dataWidth_;
|
||||
int dataHeight_;
|
||||
int left_;
|
||||
int top_;
|
||||
int width_;
|
||||
int height_;
|
||||
|
||||
public:
|
||||
GreyscaleRotatedLuminanceSource(ArrayRef<char> greyData, int dataWidth, int dataHeight,
|
||||
GreyscaleRotatedLuminanceSource(unsigned char* greyData, int dataWidth, int dataHeight,
|
||||
int left, int top, int width, int height);
|
||||
|
||||
ArrayRef<char> getRow(int y, ArrayRef<char> row) const;
|
||||
ArrayRef<char> getMatrix() const;
|
||||
unsigned char* getRow(int y, unsigned char* row);
|
||||
unsigned char* getMatrix();
|
||||
|
||||
bool isRotateSupported() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
int getWidth() const {
|
||||
return width_;
|
||||
}
|
||||
|
||||
int getHeight() const {
|
||||
return height_;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
} /* namespace */
|
||||
|
||||
#endif
|
|
@ -105,12 +105,12 @@ void GridSampler::checkAndNudgePoints(Ref<BitMatrix> image, vector<float> &point
|
|||
if (x == -1) {
|
||||
points[offset] = 0.0f;
|
||||
} else if (x == width) {
|
||||
points[offset] = float(width - 1);
|
||||
points[offset] = width - 1;
|
||||
}
|
||||
if (y == -1) {
|
||||
points[offset + 1] = 0.0f;
|
||||
} else if (y == height) {
|
||||
points[offset + 1] = float(height - 1);
|
||||
points[offset + 1] = height - 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -27,13 +27,13 @@ using namespace zxing;
|
|||
|
||||
namespace {
|
||||
const int BLOCK_SIZE_POWER = 3;
|
||||
const int BLOCK_SIZE = 1 << BLOCK_SIZE_POWER; // ...0100...00
|
||||
const int BLOCK_SIZE_MASK = BLOCK_SIZE - 1; // ...0011...11
|
||||
const int BLOCK_SIZE = 1 << BLOCK_SIZE_POWER;
|
||||
const int BLOCK_SIZE_MASK = BLOCK_SIZE - 1;
|
||||
const int MINIMUM_DIMENSION = BLOCK_SIZE * 5;
|
||||
}
|
||||
|
||||
HybridBinarizer::HybridBinarizer(Ref<LuminanceSource> source) :
|
||||
GlobalHistogramBinarizer(source), matrix_(NULL), cached_row_(NULL) {
|
||||
GlobalHistogramBinarizer(source), matrix_(NULL), cached_row_(NULL), cached_row_num_(-1) {
|
||||
}
|
||||
|
||||
HybridBinarizer::~HybridBinarizer() {
|
||||
|
@ -45,21 +45,20 @@ HybridBinarizer::createBinarizer(Ref<LuminanceSource> source) {
|
|||
return Ref<Binarizer> (new HybridBinarizer(source));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calculates the final BitMatrix once for all requests. This could be called once from the
|
||||
* constructor instead, but there are some advantages to doing it lazily, such as making
|
||||
* profiling easier, and not doing heavy lifting when callers don't expect it.
|
||||
*/
|
||||
Ref<BitMatrix> HybridBinarizer::getBlackMatrix() {
|
||||
// Calculates the final BitMatrix once for all requests. This could
|
||||
// be called once from the constructor instead, but there are some
|
||||
// advantages to doing it lazily, such as making profiling easier,
|
||||
// and not doing heavy lifting when callers don't expect it.
|
||||
if (matrix_) {
|
||||
return matrix_;
|
||||
}
|
||||
LuminanceSource& source = *getLuminanceSource();
|
||||
int width = source.getWidth();
|
||||
int height = source.getHeight();
|
||||
if (width >= MINIMUM_DIMENSION && height >= MINIMUM_DIMENSION) {
|
||||
ArrayRef<char> luminances = source.getMatrix();
|
||||
if (source.getWidth() >= MINIMUM_DIMENSION &&
|
||||
source.getHeight() >= MINIMUM_DIMENSION) {
|
||||
unsigned char* luminances = source.getMatrix();
|
||||
int width = source.getWidth();
|
||||
int height = source.getHeight();
|
||||
int subWidth = width >> BLOCK_SIZE_POWER;
|
||||
if ((width & BLOCK_SIZE_MASK) != 0) {
|
||||
subWidth++;
|
||||
|
@ -68,7 +67,7 @@ Ref<BitMatrix> HybridBinarizer::getBlackMatrix() {
|
|||
if ((height & BLOCK_SIZE_MASK) != 0) {
|
||||
subHeight++;
|
||||
}
|
||||
ArrayRef<int> blackPoints =
|
||||
int* blackPoints =
|
||||
calculateBlackPoints(luminances, subWidth, subHeight, width, height);
|
||||
|
||||
Ref<BitMatrix> newMatrix (new BitMatrix(width, height));
|
||||
|
@ -80,6 +79,13 @@ Ref<BitMatrix> HybridBinarizer::getBlackMatrix() {
|
|||
blackPoints,
|
||||
newMatrix);
|
||||
matrix_ = newMatrix;
|
||||
|
||||
// N.B.: these deletes are inadequate if anything between the new
|
||||
// and this point can throw. As of this writing, it doesn't look
|
||||
// like they do.
|
||||
|
||||
delete [] blackPoints;
|
||||
delete [] luminances;
|
||||
} else {
|
||||
// If the image is too small, fall back to the global histogram approach.
|
||||
matrix_ = GlobalHistogramBinarizer::getBlackMatrix();
|
||||
|
@ -87,34 +93,28 @@ Ref<BitMatrix> HybridBinarizer::getBlackMatrix() {
|
|||
return matrix_;
|
||||
}
|
||||
|
||||
namespace {
|
||||
inline int cap(int value, int min, int max) {
|
||||
return value < min ? min : value > max ? max : value;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
HybridBinarizer::calculateThresholdForBlock(ArrayRef<char> luminances,
|
||||
HybridBinarizer::calculateThresholdForBlock(unsigned char* luminances,
|
||||
int subWidth,
|
||||
int subHeight,
|
||||
int width,
|
||||
int height,
|
||||
ArrayRef<int> blackPoints,
|
||||
int blackPoints[],
|
||||
Ref<BitMatrix> const& matrix) {
|
||||
for (int y = 0; y < subHeight; y++) {
|
||||
int yoffset = y << BLOCK_SIZE_POWER;
|
||||
int maxYOffset = height - BLOCK_SIZE;
|
||||
if (yoffset > maxYOffset) {
|
||||
yoffset = maxYOffset;
|
||||
if (yoffset + BLOCK_SIZE >= height) {
|
||||
yoffset = height - BLOCK_SIZE;
|
||||
}
|
||||
for (int x = 0; x < subWidth; x++) {
|
||||
int xoffset = x << BLOCK_SIZE_POWER;
|
||||
int maxXOffset = width - BLOCK_SIZE;
|
||||
if (xoffset > maxXOffset) {
|
||||
xoffset = maxXOffset;
|
||||
if (xoffset + BLOCK_SIZE >= width) {
|
||||
xoffset = width - BLOCK_SIZE;
|
||||
}
|
||||
int left = cap(x, 2, subWidth - 3);
|
||||
int top = cap(y, 2, subHeight - 3);
|
||||
int left = (x > 1) ? x : 2;
|
||||
left = (left < subWidth - 2) ? left : subWidth - 3;
|
||||
int top = (y > 1) ? y : 2;
|
||||
top = (top < subHeight - 2) ? top : subHeight - 3;
|
||||
int sum = 0;
|
||||
for (int z = -2; z <= 2; z++) {
|
||||
int *blackRow = &blackPoints[(top + z) * subWidth];
|
||||
|
@ -125,17 +125,17 @@ HybridBinarizer::calculateThresholdForBlock(ArrayRef<char> luminances,
|
|||
sum += blackRow[left + 2];
|
||||
}
|
||||
int average = sum / 25;
|
||||
thresholdBlock(luminances, xoffset, yoffset, average, width, matrix);
|
||||
threshold8x8Block(luminances, xoffset, yoffset, average, width, matrix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HybridBinarizer::thresholdBlock(ArrayRef<char> luminances,
|
||||
int xoffset,
|
||||
int yoffset,
|
||||
int threshold,
|
||||
int stride,
|
||||
Ref<BitMatrix> const& matrix) {
|
||||
void HybridBinarizer::threshold8x8Block(unsigned char* luminances,
|
||||
int xoffset,
|
||||
int yoffset,
|
||||
int threshold,
|
||||
int stride,
|
||||
Ref<BitMatrix> const& matrix) {
|
||||
for (int y = 0, offset = yoffset * stride + xoffset;
|
||||
y < BLOCK_SIZE;
|
||||
y++, offset += stride) {
|
||||
|
@ -149,7 +149,7 @@ void HybridBinarizer::thresholdBlock(ArrayRef<char> luminances,
|
|||
}
|
||||
|
||||
namespace {
|
||||
inline int getBlackPointFromNeighbors(ArrayRef<int> blackPoints, int subWidth, int x, int y) {
|
||||
inline int getBlackPointFromNeighbors(int* blackPoints, int subWidth, int x, int y) {
|
||||
return (blackPoints[(y-1)*subWidth+x] +
|
||||
2*blackPoints[y*subWidth+x-1] +
|
||||
blackPoints[(y-1)*subWidth+x-1]) >> 2;
|
||||
|
@ -157,25 +157,20 @@ namespace {
|
|||
}
|
||||
|
||||
|
||||
ArrayRef<int> HybridBinarizer::calculateBlackPoints(ArrayRef<char> luminances,
|
||||
int subWidth,
|
||||
int subHeight,
|
||||
int width,
|
||||
int height) {
|
||||
int* HybridBinarizer::calculateBlackPoints(unsigned char* luminances, int subWidth, int subHeight,
|
||||
int width, int height) {
|
||||
const int minDynamicRange = 24;
|
||||
|
||||
ArrayRef<int> blackPoints (subHeight * subWidth);
|
||||
int *blackPoints = new int[subHeight * subWidth];
|
||||
for (int y = 0; y < subHeight; y++) {
|
||||
int yoffset = y << BLOCK_SIZE_POWER;
|
||||
int maxYOffset = height - BLOCK_SIZE;
|
||||
if (yoffset > maxYOffset) {
|
||||
yoffset = maxYOffset;
|
||||
if (yoffset + BLOCK_SIZE >= height) {
|
||||
yoffset = height - BLOCK_SIZE;
|
||||
}
|
||||
for (int x = 0; x < subWidth; x++) {
|
||||
int xoffset = x << BLOCK_SIZE_POWER;
|
||||
int maxXOffset = width - BLOCK_SIZE;
|
||||
if (xoffset > maxXOffset) {
|
||||
xoffset = maxXOffset;
|
||||
if (xoffset + BLOCK_SIZE >= width) {
|
||||
xoffset = width - BLOCK_SIZE;
|
||||
}
|
||||
int sum = 0;
|
||||
int min = 0xFF;
|
|
@ -32,6 +32,7 @@ namespace zxing {
|
|||
private:
|
||||
Ref<BitMatrix> matrix_;
|
||||
Ref<BitArray> cached_row_;
|
||||
int cached_row_num_;
|
||||
|
||||
public:
|
||||
HybridBinarizer(Ref<LuminanceSource> source);
|
||||
|
@ -42,24 +43,24 @@ namespace zxing {
|
|||
private:
|
||||
// We'll be using one-D arrays because C++ can't dynamically allocate 2D
|
||||
// arrays
|
||||
ArrayRef<int> calculateBlackPoints(ArrayRef<char> luminances,
|
||||
int subWidth,
|
||||
int subHeight,
|
||||
int width,
|
||||
int height);
|
||||
void calculateThresholdForBlock(ArrayRef<char> luminances,
|
||||
int* calculateBlackPoints(unsigned char* luminances,
|
||||
int subWidth,
|
||||
int subHeight,
|
||||
int width,
|
||||
int height);
|
||||
void calculateThresholdForBlock(unsigned char* luminances,
|
||||
int subWidth,
|
||||
int subHeight,
|
||||
int width,
|
||||
int height,
|
||||
ArrayRef<int> blackPoints,
|
||||
int blackPoints[],
|
||||
Ref<BitMatrix> const& matrix);
|
||||
void thresholdBlock(ArrayRef<char>luminances,
|
||||
int xoffset,
|
||||
int yoffset,
|
||||
int threshold,
|
||||
int stride,
|
||||
Ref<BitMatrix> const& matrix);
|
||||
void threshold8x8Block(unsigned char* luminances,
|
||||
int xoffset,
|
||||
int yoffset,
|
||||
int threshold,
|
||||
int stride,
|
||||
Ref<BitMatrix> const& matrix);
|
||||
};
|
||||
|
||||
}
|
|
@ -20,8 +20,12 @@
|
|||
|
||||
#include <zxing/common/IllegalArgumentException.h>
|
||||
|
||||
using zxing::IllegalArgumentException;
|
||||
namespace zxing {
|
||||
|
||||
IllegalArgumentException::IllegalArgumentException() : Exception() {}
|
||||
IllegalArgumentException::IllegalArgumentException(const char *msg) : Exception(msg) {}
|
||||
IllegalArgumentException::~IllegalArgumentException() throw() {}
|
||||
IllegalArgumentException::IllegalArgumentException(const char *msg) :
|
||||
Exception(msg) {
|
||||
}
|
||||
IllegalArgumentException::~IllegalArgumentException() throw() {
|
||||
|
||||
}
|
||||
}
|
|
@ -23,14 +23,11 @@
|
|||
#include <zxing/Exception.h>
|
||||
|
||||
namespace zxing {
|
||||
|
||||
class IllegalArgumentException : public Exception {
|
||||
class IllegalArgumentException : public zxing::Exception {
|
||||
public:
|
||||
IllegalArgumentException();
|
||||
IllegalArgumentException(const char *msg);
|
||||
~IllegalArgumentException() throw();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // __ILLEGAL_ARGUMENT_EXCEPTION_H__
|
|
@ -1,9 +1,8 @@
|
|||
// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
|
||||
/*
|
||||
* ResultIO.cpp
|
||||
* String.cpp
|
||||
* zxing
|
||||
*
|
||||
* Created by Christian Brunschen on 13/05/2008.
|
||||
* Created by Christian Brunschen on 20/05/2008.
|
||||
* Copyright 2008 ZXing authors All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -19,16 +18,21 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <zxing/Result.h>
|
||||
#include <zxing/common/Str.h>
|
||||
|
||||
using zxing::Result;
|
||||
using std::ostream;
|
||||
namespace zxing {
|
||||
using namespace std;
|
||||
|
||||
ostream& zxing::operator<<(ostream &out, Result& result) {
|
||||
if (result.text_ != 0) {
|
||||
out << result.text_->getText();
|
||||
} else {
|
||||
out << "[" << result.rawBytes_->size() << " bytes]";
|
||||
}
|
||||
String::String(const std::string &text) :
|
||||
text_(text) {
|
||||
}
|
||||
const std::string& String::getText() const {
|
||||
return text_;
|
||||
}
|
||||
|
||||
ostream &operator<<(ostream &out, const String &s) {
|
||||
out << s.text_;
|
||||
return out;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,4 +1,3 @@
|
|||
// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
|
||||
#ifndef __STR_H__
|
||||
#define __STR_H__
|
||||
|
||||
|
@ -27,23 +26,13 @@
|
|||
|
||||
namespace zxing {
|
||||
|
||||
class String;
|
||||
std::ostream& operator << (std::ostream& out, String const& s);
|
||||
|
||||
class String : public Counted {
|
||||
private:
|
||||
std::string text_;
|
||||
public:
|
||||
explicit String(const std::string &text);
|
||||
explicit String(int);
|
||||
char charAt(int) const;
|
||||
Ref<String> substring(int) const;
|
||||
const std::string& getText() const;
|
||||
int size() const;
|
||||
void append(std::string const& tail);
|
||||
void append(char c);
|
||||
int length() const;
|
||||
friend std::ostream& zxing::operator << (std::ostream& out, String const& s);
|
||||
String(const std::string &text);
|
||||
const std::string &getText() const;
|
||||
friend std::ostream &operator<<(std::ostream &out, const String &s);
|
||||
};
|
||||
|
||||
}
|
|
@ -35,7 +35,7 @@ char const* const StringUtils::ISO88591 = "ISO8859-1";
|
|||
const bool StringUtils::ASSUME_SHIFT_JIS = false;
|
||||
|
||||
string
|
||||
StringUtils::guessEncoding(char* bytes, int length,
|
||||
StringUtils::guessEncoding(unsigned char* bytes, int length,
|
||||
Hashtable const& hints) {
|
||||
Hashtable::const_iterator i = hints.find(DecodeHints::CHARACTER_SET);
|
||||
if (i != hints.end()) {
|
||||
|
@ -64,7 +64,7 @@ StringUtils::guessEncoding(char* bytes, int length,
|
|||
//int isoHighChars = 0;
|
||||
int isoHighOther = 0;
|
||||
|
||||
typedef char byte;
|
||||
typedef unsigned char byte;
|
||||
boolean utf8bom = length > 3 &&
|
||||
bytes[0] == (byte) 0xEF &&
|
||||
bytes[1] == (byte) 0xBB &&
|
|
@ -24,9 +24,12 @@
|
|||
#include <zxing/DecodeHints.h>
|
||||
|
||||
namespace zxing {
|
||||
namespace common {
|
||||
namespace common {
|
||||
class StringUtils;
|
||||
}
|
||||
}
|
||||
|
||||
class StringUtils {
|
||||
class zxing::common::StringUtils {
|
||||
private:
|
||||
static char const* const PLATFORM_DEFAULT_ENCODING;
|
||||
|
||||
|
@ -43,10 +46,7 @@ public:
|
|||
|
||||
typedef std::map<DecodeHintType, std::string> Hashtable;
|
||||
|
||||
static std::string guessEncoding(char* bytes, int length, Hashtable const& hints);
|
||||
static std::string guessEncoding(unsigned char* bytes, int length, Hashtable const& hints);
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue