--- /dev/null
+testout
+build
+report.html
+.sconsign.dblite
+
- Install Magick++ (libmagick++-dev on Ubuntu)
- Run "scons zxing"
+An simple example application is now also included, but no compilation instructions yet.
+
To clean:
- Run "scons -c all"
- Install astyle
- Run ./format
+To profile the code (very useful to optimize the code):
+ - Install valgrind
+ - "valgrind --tool=callgrind build/zxing - path/to/test/data/*.jpg > report.html"
+ - kcachegrind is a very nice tool to analize the output
zxing_include = ['core/src']\r
zxing_libs = env.Library('zxing', source=zxing_files, CPPPATH=zxing_include, **compile_options)\r
\r
-app_files = all_files('magick/src')\r
+app_files = ['magick/src/MagickBitmapSource.cpp', 'magick/src/main.cpp']\r
app_executable = env.Program('zxing', app_files, CPPPATH=magick_include + zxing_include, LIBS=magick_libs + zxing_libs, **compile_options)\r
\r
test_files = all_files('core/tests/src')\r
--- /dev/null
+/*
+ * 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>
+
+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
--- /dev/null
+/*
+ * EdgeDetector.h
+ * 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.
+ */
+
+#ifndef EDGEDETECTOR_H_
+#define EDGEDETECTOR_H_
+
+#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_ */
int top = (y > 0) ? y : 1;
top = (top < subHeight - 1) ? top : subHeight - 2;
int sum = 0;
- int type = 0;
+ int contrast = 0;
for (int z = -1; z <= 1; z++) {
// sum += averages[(top + z) * subWidth + left - 2];
sum += averages[(top + z) * subWidth + left - 1];
// sum += averages[(top + z) * subWidth + left + 2];
// type += types[(top + z) * subWidth + left - 2];
- type += types[(top + z) * subWidth + left - 1];
- type += types[(top + z) * subWidth + left];
- type += types[(top + z) * subWidth + left + 1];
+ contrast += types[(top + z) * subWidth + left - 1];
+ contrast += types[(top + z) * subWidth + left];
+ contrast += types[(top + z) * subWidth + left + 1];
// type += types[(top + z) * subWidth + left + 2];
}
int average = sum / 9;
- if (type > 3)
+ if (contrast > 2)
threshold8x8Block(luminances, x << 3, y << 3, average, stride, matrix);
// else if(average < global) // Black
// matrix.setRegion(x << 3, y << 3, 8, 8);
--- /dev/null
+/*
+ * Point.h
+ * 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.
+ */
+
+#ifndef ZXING_POINT_H_\r
+#define ZXING_POINT_H_\r
+
+namespace zxing {\r
+class PointI {
+public:
+ int x;
+ int y;
+};
+
+class Point {
+public:
+ Point(float x_, float y_) : x(x_), y(y_) {};
+
+ float x;
+ float y;
+};
+
+class Line {
+public:
+ Line(Point start_, Point end_) : start(start_), end(end_) {};
+
+ Point start;
+ Point end;
+};\r
+}\r
+#endif // POINT_H_\r
}
int stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2];
- if (5 * abs(stateCountTotal - originalStateCountTotal) >= originalStateCountTotal) {
+ if (5 * abs(stateCountTotal - originalStateCountTotal) >= 2 * originalStateCountTotal) {
return NAN;
}
}
}
if (alignmentPattern == 0) {
- throw zxing::ReaderException("Could not find alignment pattern");
+ // Try anyway
}
}
namespace qrcode {
class Detector : public Counted {
-private:
+protected:
Ref<BitMatrix> image_;
float allowanceFactor);
public:
- static Ref<PerspectiveTransform> createTransform(Ref<ResultPoint> topLeft, Ref<ResultPoint> topRight, Ref <
+ virtual Ref<PerspectiveTransform> createTransform(Ref<ResultPoint> topLeft, Ref<ResultPoint> topRight, Ref <
ResultPoint > bottomLeft, Ref<ResultPoint> alignmentPattern, int dimension);
Detector(Ref<BitMatrix> image);
return NAN;
}
- // If we found a finder-pattern-like section, but its size is more than 20% different than
+ // If we found a finder-pattern-like section, but its size is more than 40% different than
// the original, assume it's a false positive
int stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] + stateCount[4];
- if (5 * abs(stateCountTotal - originalStateCountTotal) >= originalStateCountTotal) {
+ if (5 * abs(stateCountTotal - originalStateCountTotal) >= 2 * originalStateCountTotal) {
return NAN;
}
--- /dev/null
+/*
+ * QREdgeDetector.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/qrcode/detector/QREdgeDetector.h>
+#include <zxing/common/EdgeDetector.h>
+
+using namespace std;
+
+namespace zxing {
+namespace qrcode {
+
+static const float patternEdgeThreshold = 2;
+static const int patternEdgeWidth = 3;
+static const float patternEdgeSearchRatio = 1.1;
+static const int patternEdgeSkip = 2;
+
+static const float accurateEdgeThreshold = 3.3;
+static const int accurateEdgeWidth = 7;
+static const int accurateEdgeSkip = 2;
+
+static Point guessLastPattern(Point topLeft, Point topRight, Point bottomLeft) {
+ return Point(topRight.x - topLeft.x + bottomLeft.x, topRight.y - topLeft.y + bottomLeft.y);
+}
+
+static Point rp(Ref<ResultPoint> rp) {
+ return Point(rp->getX(), rp->getY());
+}
+
+QREdgeDetector::QREdgeDetector(Ref<BitMatrix> image) : Detector(image) { }
+
+Ref<PerspectiveTransform> QREdgeDetector::createTransform(Ref<ResultPoint> topLeft, Ref<ResultPoint> topRight, Ref <
+ ResultPoint > bottomLeft, Ref<ResultPoint> alignmentPattern, int dimension) {
+
+ if(alignmentPattern == NULL) {
+ Point corner = findCorner(*image_.object_, rp(topLeft), rp(topRight), rp(bottomLeft), dimension);
+ return get1CornerTransform(rp(topLeft), rp(topRight), rp(bottomLeft), corner, dimension);
+ } else {
+ return Detector::createTransform(topLeft, topRight, bottomLeft, alignmentPattern, dimension);
+ }
+}
+
+
+
+
+Point QREdgeDetector::findCorner(const BitMatrix& image, Point topLeft, Point topRight, Point bottomLeft, int dimension) {
+ Point bottomRight = guessLastPattern(topLeft, topRight, bottomLeft);
+
+ Line bottomEst = findPatternEdge(image, bottomLeft, topLeft, bottomRight, false);
+ Line rightEst = findPatternEdge(image, topRight, topLeft, bottomRight, true);
+
+ //return EdgeDetector::intersection(bottomEst, rightEst);
+
+ Line bottom = EdgeDetector::findLine(image, bottomEst, false, accurateEdgeWidth, accurateEdgeThreshold, accurateEdgeSkip);
+ Line right = EdgeDetector::findLine(image, rightEst, true, accurateEdgeWidth, accurateEdgeThreshold, accurateEdgeSkip);
+
+
+ return EdgeDetector::intersection(bottom, right);
+}
+
+Line QREdgeDetector::findPatternEdge(const BitMatrix& image, Point pattern, Point opposite, Point direction, bool invert) {
+ Point start = endOfReverseBlackWhiteBlackRun(image, pattern, opposite);
+
+ float dx = pattern.x - start.x;
+ float dy = pattern.y - start.y;
+ float dist = sqrt(dx*dx + dy*dy);
+
+ float dirX = direction.x - pattern.x;
+ float dirY = direction.y - pattern.y;
+ float dirSize = sqrt(dirX*dirX + dirY*dirY);
+
+ float nx = dirX/dirSize;
+ float ny = dirY/dirSize;
+
+ float search = dist * patternEdgeSearchRatio;
+ Point a(start.x + nx*search, start.y + ny*search);
+ Point b(start.x - nx*search, start.y - ny*search);
+
+ return EdgeDetector::findLine(image, Line(a, b), invert, patternEdgeWidth, patternEdgeThreshold, patternEdgeSkip);
+}
+
+
+Ref<PerspectiveTransform> QREdgeDetector::get1CornerTransform(Point topLeft, Point topRight, Point bottomLeft, Point corner, int dimension) {
+ float dimMinusThree = (float) dimension - 3.5f;
+
+ Ref<PerspectiveTransform> transform(PerspectiveTransform::quadrilateralToQuadrilateral(3.5f, 3.5f, dimMinusThree, 3.5f, dimension,
+ dimension, 3.5f, dimMinusThree, topLeft.x, topLeft.y, topRight.x,
+ topRight.y, corner.x, corner.y, bottomLeft.x, bottomLeft.y));
+
+ return transform;
+}
+
+// Adapted from "sizeOfBlackWhiteBlackRun" in zxing::qrcode::Detector
+Point QREdgeDetector::endOfReverseBlackWhiteBlackRun(const BitMatrix& image, Point from, Point to) {
+ float fromX = from.x;
+ float fromY = from.y;
+ float toX = to.x;
+ float toY = to.y;
+
+ bool steep = abs(toY - fromY) > abs(toX - fromX);
+ if (steep) {
+ int temp = fromX;
+ fromX = fromY;
+ fromY = temp;
+ temp = toX;
+ toX = toY;
+ toY = temp;
+ }
+
+ int dx = abs(toX - fromX);
+ int dy = abs(toY - fromY);
+ int error = -dx >> 1;
+ int ystep = fromY < toY ? -1 : 1;
+ int xstep = fromX < toX ? -1 : 1;
+ int state = 0; // In black pixels, looking for white, first or second time
+
+ // In case there are no points, prepopulate to from
+ int realX = from.x;
+ int realY = from.y;
+ for (int x = fromX, y = fromY; x != toX; x += xstep) {
+ realX = steep ? y : x;
+ realY = steep ? x : y;
+
+ if(realX < 0 || realY < 0 || realX >= (int)image.getWidth() || realY >= (int)image.getHeight())
+ break;
+
+ if (state == 1) { // In white pixels, looking for black
+ if (image.get(realX, realY)) {
+ state++;
+ }
+ } else {
+ if (!image.get(realX, realY)) {
+ state++;
+ }
+ }
+
+ if (state == 3) { // Found black, white, black, and stumbled back onto white; done
+ return Point(realX, realY);
+ }
+ error += dy;
+ if (error > 0) {
+ y += ystep;
+ error -= dx;
+ }
+ }
+
+ // B-W-B run not found, return the last point visited.
+ return Point(realX, realY);
+}
+
+} // namespace qrcode
+} // namespace zxing
--- /dev/null
+/*
+ * QREdgeDetector.h
+ * 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.
+ */
+
+#ifndef QREDGEDETECTOR_H_\r
+#define QREDGEDETECTOR_H_\r
+
+#include <zxing/qrcode/detector/Detector.h>
+#include <zxing/common/Point.h>
+
+namespace zxing {
+namespace qrcode {
+
+class QREdgeDetector : public Detector {
+public:
+ QREdgeDetector(Ref<BitMatrix> image);
+
+ virtual Ref<PerspectiveTransform> createTransform(Ref<ResultPoint> topLeft, Ref<ResultPoint> topRight, Ref <
+ ResultPoint > bottomLeft, Ref<ResultPoint> alignmentPattern, int dimension);
+
+private:
+ Point findCorner(const BitMatrix& image, Point topLeft, Point topRight, Point bottomLeft, int dimension);
+ Line findPatternEdge(const BitMatrix& image, Point pattern, Point opposite, Point direction, bool invert);
+
+ Point endOfReverseBlackWhiteBlackRun(const BitMatrix& image, Point from, Point to);
+
+ Ref<PerspectiveTransform> get1CornerTransform(Point topLeft, Point topRight, Point bottomLeft, Point corner, int dimension);
+};
+
+}
+}\r
+#endif // QREDGEDETECTOR_H_\r
unsigned char MagickBitmapSource::getPixel(int x, int y) {
const PixelPacket* p = pixel_cache + y * width + x;
// We assume 16 bit values here
- return (unsigned char)((((int)p->red + (int)p->green + (int)p->blue) >> 8) / 3);
+
+ //return (unsigned char)((((int)p->red + (int)p->green + (int)p->blue) >> 8) / 3);
+
+ return (unsigned char)((306 * ((int)p->red >> 8) + 601 * ((int)p->green >> 8) + 117 * ((int)p->blue >> 8)) >> 10);
}
+
+/** This is a more efficient implementation. */
+unsigned char* MagickBitmapSource::copyMatrix() {
+ int width = getWidth();
+ int height = getHeight();
+ unsigned char* matrix = new unsigned char[width*height];
+ unsigned char* m = matrix;
+ const Magick::PixelPacket* p = pixel_cache;
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width; x++) {
+ *m = (unsigned char)((306 * ((int)p->red >> 8) + 601 * ((int)p->green >> 8) + 117 * ((int)p->blue >> 8)) >> 10);
+ m++;
+ p++;
+ }
+ }
+ return matrix;
+}
+
int getWidth();
int getHeight();
unsigned char getPixel(int x, int y);
+ unsigned char* copyMatrix();
};
#endif /* MAGICKMONOCHROMEBITMAPSOURCE_H_ */
--- /dev/null
+/*
+ * example.cpp
+ * zxing
+ *
+ * Created by Ralf Kistner on 16/10/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 <iostream>
+#include <fstream>
+#include <string>
+#include <Magick++.h>
+#include "MagickBitmapSource.h"
+#include <zxing/qrcode/QRCodeReader.h>
+#include <zxing/common/GlobalHistogramBinarizer.h>
+#include <zxing/common/LocalBlockBinarizer.h>
+#include <zxing/Exception.h>
+
+using namespace Magick;
+using namespace std;
+using namespace zxing;
+using namespace zxing::qrcode;
+
+
+void decode_image(Image& image, bool localized) {
+ try {
+ Ref<MagickBitmapSource> source(new MagickBitmapSource(image));
+
+ Ref<Binarizer> binarizer(NULL);
+ if (localized) {
+ binarizer = new LocalBlockBinarizer(source);
+ } else {
+ binarizer = new GlobalHistogramBinarizer(source);
+ }
+
+
+ Ref<BinaryBitmap> image(new BinaryBitmap(binarizer));
+ QRCodeReader reader;
+ Ref<Result> result(reader.decode(image));
+
+ cout << result->getText()->getText() << endl;
+ } catch (zxing::Exception& e) {
+ cerr << "Error: " << e.what() << endl;
+ }
+}
+
+
+int main(int argc, char** argv) {
+ if (argc < 2) {
+ cout << "Usage: " << argv[0] << "<filename1> [<filename2> ...]" << endl;
+ return 1;
+ }
+ for (int i = 1; i < argc; i++) {
+ string infilename = argv[i];
+ cout << "Processing: " << infilename << endl;
+ Image image;
+ try {
+ image.read(infilename);
+ } catch (...) {
+ cerr << "Unable to open image, ignoring" << endl;
+ continue;
+ }
+
+ bool local = true; // Use local thresholding
+
+ test_image(image, local);
+ }
+ return 0;
+}
+
+
#include <zxing/BinaryBitmap.h>
#include <zxing/qrcode/detector/Detector.h>
+#include <zxing/qrcode/detector/QREdgeDetector.h>
#include <zxing/qrcode/decoder/Decoder.h>
using namespace Magick;
Ref<Result> decode(string out_prefix, Ref<BinaryBitmap> image, string& cell_grid, string& cell_transformed) {
Decoder decoder;
- Detector detector(image->getBlackMatrix());
+ QREdgeDetector detector = QREdgeDetector(image->getBlackMatrix());
Ref<DetectorResult> detectorResult(detector.detect());
string cell_transformed;
string cell_result;
string cell_grid;
+ string result_color = "red";
int res = -1;
Ref<BitMatrix> matrix(NULL);
Ref<BinaryBitmap> binary(new BinaryBitmap(binarizer));
Ref<Result> result(decode(out_prefix, binary, cell_grid, cell_transformed));
- cell_result = "<font color=\"blue\"><b>" + result->getText()->getText() + "</b></font>";
+ cell_result = result->getText()->getText();
+ result_color = "green";
res = 0;
} catch (ReaderException e) {
cell_result = "zxing::ReaderException: " + string(e.what());
cout << "<td>" << cell_mono << "</td>" << endl;
cout << "<td>" << cell_grid << "</td>" << endl;
cout << "<td>" << cell_transformed << "</td>" << endl;
- cout << "<td>" << cell_result << "</td>" << endl;
+ cout << "<td bgcolor=\"" << result_color << "\">" << cell_result << "</td>" << endl;
return res;
}
int both = 0;
int neither = 0;
- cout << "<html><body><table>" << endl;
+ cout << "<html><body><table border=\"1\">" << endl;
for (int i = 2; i < argc; i++) {
string infilename = argv[i];
cerr << "Processing: " << infilename << endl;
cerr << "Unable to open image, ignoring" << endl;
continue;
}
- cout << "<tr><td colspan=\"3\">" << infilename << "</td></tr>" << endl;
+ cout << "<tr><td colspan=\"5\">" << infilename << "</td></tr>" << endl;
cout << "<tr>" << endl;
cout << "<td><img src=\"" << infilename << "\" /></td>" << endl;
int lresult = 1;
if (outfolder == string("-")) {
- gresult = test_image_global(image, "");
+ //gresult = test_image_global(image, "");
lresult = test_image_local(image, "");
} else {
replace(infilename.begin(), infilename.end(), '/', '_');
string prefix = string(outfolder) + string("/") + infilename;
- gresult = test_image_global(image, prefix + ".g");
+ //gresult = test_image_global(image, prefix + ".g");
lresult = test_image_local(image, prefix + ".l");
}