mirror of
https://github.com/status-im/qzxing.git
synced 2025-01-11 19:44:36 +00:00
Reimplemented CameraImageWrapper to internally use GreyscaleLuminanceSource.
Enhanced QZXing, in case of decode failure, it now reties with "tryHarder" added decode hint. These changes have the following increment on success rates when decoding (numbers generated by test application): CODE_128: was 44/48, is 47/48 EAN_8: was 7/8, is 8/8 EAN_13: was 101/157, is 119/157 ITF: was 18/27, is 22/27 QR_CODE: was 135/178, is 137/178 UPC_A: was 80/167, is 99/167 UPC_E: was 40/55, is 47/55
This commit is contained in:
parent
5de6bf853f
commit
41ebf93087
@ -10,11 +10,14 @@ CameraImageWrapper::CameraImageWrapper() : LuminanceSource(0,0), image(NULL)
|
||||
CameraImageWrapper::CameraImageWrapper(const QImage &sourceImage) : LuminanceSource(sourceImage.width(), sourceImage.height())
|
||||
{
|
||||
image = grayScaleImage( &sourceImage );
|
||||
delegate = Ref<GreyscaleLuminanceSource>(
|
||||
new GreyscaleLuminanceSource(getMatrixP(),image->width(), image->height(),0, 0, image->width(), image->height()));
|
||||
}
|
||||
|
||||
CameraImageWrapper::CameraImageWrapper(CameraImageWrapper& otherInstance) : LuminanceSource(otherInstance.getWidth(), otherInstance.getHeight())
|
||||
{
|
||||
image = new QImage(otherInstance.getOriginalImage());
|
||||
delegate = otherInstance.getDelegate();
|
||||
}
|
||||
|
||||
CameraImageWrapper::~CameraImageWrapper()
|
||||
@ -25,7 +28,7 @@ CameraImageWrapper::~CameraImageWrapper()
|
||||
|
||||
CameraImageWrapper *CameraImageWrapper::Factory(const QImage &sourceImage, int maxWidth, int maxHeight, bool smoothTransformation)
|
||||
{
|
||||
if((maxWidth != 1 || maxHeight != 1) && (sourceImage.width() > maxWidth || sourceImage.height() > maxHeight))
|
||||
if((maxWidth != 1 && sourceImage.width() > maxWidth) || (maxHeight != 1 && sourceImage.height() > maxHeight))
|
||||
{
|
||||
QImage image;
|
||||
image = sourceImage.scaled(
|
||||
@ -39,33 +42,6 @@ CameraImageWrapper *CameraImageWrapper::Factory(const QImage &sourceImage, int m
|
||||
return new CameraImageWrapper(sourceImage);
|
||||
}
|
||||
|
||||
int CameraImageWrapper::getWidth() const
|
||||
{
|
||||
return image->width();
|
||||
}
|
||||
|
||||
int CameraImageWrapper::getHeight() const
|
||||
{
|
||||
return image->height();
|
||||
}
|
||||
|
||||
unsigned char CameraImageWrapper::getPixel(int x, int y) const
|
||||
{
|
||||
return image->pixel(x,y);
|
||||
}
|
||||
|
||||
unsigned char* CameraImageWrapper::copyMatrix() const
|
||||
{
|
||||
unsigned char* newMatrix = (unsigned char*)malloc(image->width() * image->height() * sizeof(unsigned char));
|
||||
|
||||
int cnt = 0;
|
||||
for(int i=0; i<image->width(); i++)
|
||||
for(int j=0; j<image->height(); j++)
|
||||
newMatrix[cnt++] = getPixel(i,j);
|
||||
|
||||
return newMatrix;
|
||||
}
|
||||
|
||||
QImage* CameraImageWrapper::grayScaleImage(const QImage *origin)
|
||||
{
|
||||
QImage *tmp = new QImage(origin->width(), origin->height(), QImage::Format_Grayscale8);
|
||||
@ -89,6 +65,62 @@ QImage CameraImageWrapper::getOriginalImage()
|
||||
}
|
||||
|
||||
ArrayRef<char> CameraImageWrapper::getRow(int y, ArrayRef<char> row) const
|
||||
{
|
||||
if(delegate)
|
||||
return delegate->getRow(y, row);
|
||||
else
|
||||
return getRowP(y, row);
|
||||
}
|
||||
|
||||
ArrayRef<char> CameraImageWrapper::getMatrix() const
|
||||
{
|
||||
if(delegate)
|
||||
return delegate->getMatrix();
|
||||
else
|
||||
return getMatrixP();
|
||||
}
|
||||
|
||||
bool CameraImageWrapper::isCropSupported() const
|
||||
{
|
||||
if(delegate)
|
||||
return delegate->isCropSupported();
|
||||
else
|
||||
return LuminanceSource::isCropSupported();
|
||||
}
|
||||
|
||||
Ref<LuminanceSource> CameraImageWrapper::crop(int left, int top, int width, int height) const
|
||||
{
|
||||
if(delegate)
|
||||
return delegate->crop(left, top, width, height);
|
||||
else
|
||||
return LuminanceSource::crop(left, top, width, height);
|
||||
}
|
||||
|
||||
bool CameraImageWrapper::isRotateSupported() const
|
||||
{
|
||||
if(delegate)
|
||||
return delegate->isRotateSupported();
|
||||
else
|
||||
return LuminanceSource::isRotateSupported();
|
||||
}
|
||||
|
||||
Ref<LuminanceSource> CameraImageWrapper::invert() const
|
||||
{
|
||||
if(delegate)
|
||||
return delegate->invert();
|
||||
else
|
||||
return LuminanceSource::invert();
|
||||
}
|
||||
|
||||
Ref<LuminanceSource> CameraImageWrapper::rotateCounterClockwise() const
|
||||
{
|
||||
if(delegate)
|
||||
return delegate->rotateCounterClockwise();
|
||||
else
|
||||
return LuminanceSource::rotateCounterClockwise();
|
||||
}
|
||||
|
||||
ArrayRef<char> CameraImageWrapper::getRowP(int y, ArrayRef<char> row) const
|
||||
{
|
||||
int width = getWidth();
|
||||
|
||||
@ -96,12 +128,12 @@ ArrayRef<char> CameraImageWrapper::getRow(int y, ArrayRef<char> row) const
|
||||
row.reset(ArrayRef<char>(width));
|
||||
|
||||
for (int x = 0; x < width; x++)
|
||||
row[x] = getPixel(x,y);
|
||||
row[x] = image->pixel(x,y);
|
||||
|
||||
return row;
|
||||
}
|
||||
|
||||
ArrayRef<char> CameraImageWrapper::getMatrix() const
|
||||
ArrayRef<char> CameraImageWrapper::getMatrixP() const
|
||||
{
|
||||
int width = getWidth();
|
||||
int height = getHeight();
|
||||
@ -113,7 +145,7 @@ ArrayRef<char> CameraImageWrapper::getMatrix() const
|
||||
|
||||
for(int y=0; y<height; y++)
|
||||
{
|
||||
tmpRow = getRow(y, tmpRow);
|
||||
tmpRow = getRowP(y, tmpRow);
|
||||
#if __cplusplus > 199711L
|
||||
memcpy(m, tmpRow->values().data(), width);
|
||||
#else
|
||||
@ -125,6 +157,31 @@ ArrayRef<char> CameraImageWrapper::getMatrix() const
|
||||
return arr;
|
||||
}
|
||||
|
||||
//bool CameraImageWrapper::isCropSupported() const
|
||||
//{
|
||||
// return true;
|
||||
//}
|
||||
|
||||
//Ref<LuminanceSource> CameraImageWrapper::crop(int left, int top, int width, int height) const
|
||||
//{
|
||||
|
||||
//}
|
||||
|
||||
//bool CameraImageWrapper::isRotateSupported() const
|
||||
//{
|
||||
// return true;
|
||||
//}
|
||||
|
||||
//Ref<LuminanceSource> CameraImageWrapper::invert() const
|
||||
//{
|
||||
|
||||
//}
|
||||
|
||||
//Ref<LuminanceSource> CameraImageWrapper::rotateCounterClockwise() const
|
||||
//{
|
||||
|
||||
//}
|
||||
|
||||
QImage *CameraImageWrapper::sharpen(const QImage *origin)
|
||||
{
|
||||
QImage * newImage = new QImage(* origin);
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
#include <QImage>
|
||||
#include <QString>
|
||||
#include <zxing/zxing/LuminanceSource.h>
|
||||
#include <zxing/zxing/common/GreyscaleLuminanceSource.h>
|
||||
|
||||
using namespace zxing;
|
||||
|
||||
@ -17,23 +17,27 @@ public:
|
||||
|
||||
static CameraImageWrapper* Factory(const QImage& image, int maxWidth=-1, int maxHeight=-1, bool smoothTransformation=false);
|
||||
|
||||
int getWidth() const;
|
||||
int getHeight() const;
|
||||
|
||||
unsigned char getPixel(int x, int y) const;
|
||||
unsigned char* copyMatrix() const;
|
||||
|
||||
QImage* grayScaleImage(const QImage *origin);
|
||||
QImage getOriginalImage();
|
||||
Ref<GreyscaleLuminanceSource> getDelegate() { return delegate; }
|
||||
|
||||
// Callers take ownership of the returned memory and must call delete [] on it themselves.
|
||||
ArrayRef<char> getRow(int y, ArrayRef<char> row) const;
|
||||
ArrayRef<char> getMatrix() const;
|
||||
|
||||
bool isCropSupported() const;
|
||||
Ref<LuminanceSource> crop(int left, int top, int width, int height) const;
|
||||
bool isRotateSupported() const;
|
||||
Ref<LuminanceSource> invert() const;
|
||||
Ref<LuminanceSource> rotateCounterClockwise() const;
|
||||
|
||||
private:
|
||||
ArrayRef<char> getRowP(int y, ArrayRef<char> row) const;
|
||||
ArrayRef<char> getMatrixP() const;
|
||||
QImage* grayScaleImage(const QImage *origin);
|
||||
|
||||
QImage* sharpen(const QImage *origin);
|
||||
|
||||
QImage* image;
|
||||
Ref<GreyscaleLuminanceSource> delegate;
|
||||
};
|
||||
|
||||
#endif //CAMERAIMAGE_H
|
||||
|
@ -51,56 +51,56 @@ QZXing::QZXing(QZXing::DecoderFormat decodeHints, QObject *parent) : QObject(par
|
||||
QString QZXing::decoderFormatToString(int fmt)
|
||||
{
|
||||
switch (fmt) {
|
||||
case DecoderFormat_Aztec:
|
||||
return "AZTEC";
|
||||
case DecoderFormat_Aztec:
|
||||
return "AZTEC";
|
||||
|
||||
case DecoderFormat_CODABAR:
|
||||
return "CODABAR";
|
||||
case DecoderFormat_CODABAR:
|
||||
return "CODABAR";
|
||||
|
||||
case DecoderFormat_CODE_39:
|
||||
return "CODE_39";
|
||||
case DecoderFormat_CODE_39:
|
||||
return "CODE_39";
|
||||
|
||||
case DecoderFormat_CODE_93:
|
||||
return "CODE_93";
|
||||
case DecoderFormat_CODE_93:
|
||||
return "CODE_93";
|
||||
|
||||
case DecoderFormat_CODE_128:
|
||||
return "CODE_128";
|
||||
case DecoderFormat_CODE_128:
|
||||
return "CODE_128";
|
||||
|
||||
case DecoderFormat_DATA_MATRIX:
|
||||
return "DATA_MATRIX";
|
||||
case DecoderFormat_DATA_MATRIX:
|
||||
return "DATA_MATRIX";
|
||||
|
||||
case DecoderFormat_EAN_8:
|
||||
return "EAN_8";
|
||||
case DecoderFormat_EAN_8:
|
||||
return "EAN_8";
|
||||
|
||||
case DecoderFormat_EAN_13:
|
||||
return "EAN_13";
|
||||
case DecoderFormat_EAN_13:
|
||||
return "EAN_13";
|
||||
|
||||
case DecoderFormat_ITF:
|
||||
return "ITF";
|
||||
case DecoderFormat_ITF:
|
||||
return "ITF";
|
||||
|
||||
case DecoderFormat_MAXICODE:
|
||||
return "MAXICODE";
|
||||
case DecoderFormat_MAXICODE:
|
||||
return "MAXICODE";
|
||||
|
||||
case DecoderFormat_PDF_417:
|
||||
return "PDF_417";
|
||||
case DecoderFormat_PDF_417:
|
||||
return "PDF_417";
|
||||
|
||||
case DecoderFormat_QR_CODE:
|
||||
return "QR_CODE";
|
||||
case DecoderFormat_QR_CODE:
|
||||
return "QR_CODE";
|
||||
|
||||
case DecoderFormat_RSS_14:
|
||||
return "RSS_14";
|
||||
case DecoderFormat_RSS_14:
|
||||
return "RSS_14";
|
||||
|
||||
case DecoderFormat_RSS_EXPANDED:
|
||||
return "RSS_EXPANDED";
|
||||
case DecoderFormat_RSS_EXPANDED:
|
||||
return "RSS_EXPANDED";
|
||||
|
||||
case DecoderFormat_UPC_A:
|
||||
return "UPC_A";
|
||||
case DecoderFormat_UPC_A:
|
||||
return "UPC_A";
|
||||
|
||||
case DecoderFormat_UPC_E:
|
||||
return "UPC_E";
|
||||
case DecoderFormat_UPC_E:
|
||||
return "UPC_E";
|
||||
|
||||
case DecoderFormat_UPC_EAN_EXTENSION:
|
||||
return "UPC_EAN_EXTENSION";
|
||||
case DecoderFormat_UPC_EAN_EXTENSION:
|
||||
return "UPC_EAN_EXTENSION";
|
||||
} // switch
|
||||
return QString();
|
||||
}
|
||||
@ -190,12 +190,13 @@ QString QZXing::decodeImage(const QImage &image, int maxWidth, int maxHeight, bo
|
||||
}
|
||||
|
||||
CameraImageWrapper *ciw = NULL;
|
||||
try {
|
||||
if ((maxWidth > 0) || (maxHeight > 0))
|
||||
ciw = CameraImageWrapper::Factory(image, maxWidth, maxHeight, smoothTransformation);
|
||||
else
|
||||
ciw = CameraImageWrapper::Factory(image, 999, 999, true);
|
||||
|
||||
if ((maxWidth > 0) || (maxHeight > 0))
|
||||
ciw = CameraImageWrapper::Factory(image, maxWidth, maxHeight, smoothTransformation);
|
||||
else
|
||||
ciw = CameraImageWrapper::Factory(image, 999, 999, true);
|
||||
|
||||
try {
|
||||
Ref<LuminanceSource> imageRef(ciw);
|
||||
GlobalHistogramBinarizer *binz = new GlobalHistogramBinarizer(imageRef);
|
||||
|
||||
@ -204,7 +205,19 @@ QString QZXing::decodeImage(const QImage &image, int maxWidth, int maxHeight, bo
|
||||
|
||||
Ref<BinaryBitmap> ref(bb);
|
||||
|
||||
res = decoder->decode(ref, DecodeHints((int)enabledDecoders));
|
||||
DecodeHints hints((int)enabledDecoders);
|
||||
|
||||
bool hasSucceded = false;
|
||||
try {
|
||||
res = decoder->decode(ref, hints);
|
||||
hasSucceded = true;
|
||||
}catch(zxing::Exception &e){}
|
||||
|
||||
if(!hasSucceded)
|
||||
{
|
||||
hints.setTryHarder(true);
|
||||
res = decoder->decode(ref, hints);
|
||||
}
|
||||
|
||||
QString string = QString(res->getText()->getText().c_str());
|
||||
if (!string.isEmpty() && (string.length() > 0)) {
|
||||
@ -298,8 +311,8 @@ QImage QZXing::encodeData(const QString& data)
|
||||
for(int i=0; i<bytesRef->getWidth(); i++)
|
||||
for(int j=0; j<bytesRef->getHeight(); j++)
|
||||
image.setPixel(i, j, bytes[i][j] ?
|
||||
qRgb(0,0,0) :
|
||||
qRgb(255,255,255));
|
||||
qRgb(0,0,0) :
|
||||
qRgb(255,255,255));
|
||||
|
||||
image = image.scaled(240, 240);
|
||||
bool success = image.save("tmp.bmp","BMP");
|
||||
|
Loading…
x
Reference in New Issue
Block a user