C++ port: Hints infrastructure was added in r1499. This changeset implements reader...
[zxing.git] / cpp / magick / src / main.cpp
1 /*
2  *  main.cpp
3  *  zxing
4  *
5  *  Copyright 2010 ZXing authors All rights reserved.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19
20 #include <iostream>
21 #include <fstream>
22 #include <string>
23 #include <Magick++.h>
24 #include "MagickBitmapSource.h"
25 #include <zxing/common/Counted.h>
26 //#include <zxing/qrcode/QRCodeReader.h>
27 #include <zxing/Binarizer.h>
28 #include <zxing/MultiFormatReader.h>
29 #include <zxing/Result.h>
30 #include <zxing/ReaderException.h>
31 #include <zxing/common/GlobalHistogramBinarizer.h>
32 #include <zxing/common/HybridBinarizer.h>
33 #include <exception>
34 #include <zxing/Exception.h>
35 #include <zxing/common/IllegalArgumentException.h>
36 #include <zxing/BinaryBitmap.h>
37 #include <zxing/DecodeHints.h>
38
39 //#include <zxing/qrcode/detector/Detector.h>
40 //#include <zxing/qrcode/detector/QREdgeDetector.h>
41 //#include <zxing/qrcode/decoder/Decoder.h>
42
43 using namespace Magick;
44 using namespace std;
45 using namespace zxing;
46 //using namespace zxing::qrcode;
47
48 static bool raw_dump = false;
49 static bool show_format = false;
50 static bool tryHarder = false;
51 static bool show_filename = false;
52
53 static const int MAX_EXPECTED = 1024;
54
55 Ref<Result> decode(Ref<BinaryBitmap> image, DecodeHints hints) {
56   Ref<Reader> reader(new MultiFormatReader);
57   return Ref<Result> (new Result(*reader->decode(image, hints)));
58 }
59
60
61 int test_image(Image& image, bool hybrid, string expected = "") {
62
63   string cell_result;
64   int res = -1;
65
66   Ref<BitMatrix> matrix(NULL);
67   Ref<Binarizer> binarizer(NULL);
68   const char* result_format = "";
69
70   try {
71     Ref<MagickBitmapSource> source(new MagickBitmapSource(image));
72
73     if (hybrid) {
74       binarizer = new HybridBinarizer(source);
75     } else {
76       binarizer = new GlobalHistogramBinarizer(source);
77     }
78
79     DecodeHints hints(DecodeHints::DEFAULT_HINT);
80     hints.setTryHarder(tryHarder);
81     Ref<BinaryBitmap> binary(new BinaryBitmap(binarizer));
82     Ref<Result> result(decode(binary, hints));
83     cell_result = result->getText()->getText();
84     result_format = barcodeFormatNames[result->getBarcodeFormat()];
85     res = 0;
86   } catch (ReaderException e) {
87     cell_result = "zxing::ReaderException: " + string(e.what());
88     res = -2;
89   } catch (zxing::IllegalArgumentException& e) {
90     cell_result = "zxing::IllegalArgumentException: " + string(e.what());
91     res = -3;
92   } catch (zxing::Exception& e) {
93     cell_result = "zxing::Exception: " + string(e.what());
94     res = -4;
95   } catch (std::exception& e) {
96     cell_result = "std::exception: " + string(e.what());
97     res = -5;
98   }
99
100   if (cell_result.compare(expected)) {
101     res = -6;
102     if (!raw_dump) {
103         cout << (hybrid ? "Hybrid" : "Global") << " binarizer failed:\n";
104         if (expected.length() >= 0) {
105           cout << "  Expected: " << expected << "\n";
106         }
107         cout << "  Detected: " << cell_result << endl;
108     }
109   }
110
111
112   if (raw_dump && !hybrid) {/* don't print twice, and global is a bit better */
113     cout << cell_result;
114     if (show_format) {
115       cout << " " << result_format;
116     }
117     cout << endl;
118
119   }
120   return res;
121 }
122
123 int test_image_hybrid(Image& image, string expected = "") {
124   return test_image(image, true, expected);
125 }
126
127 int test_image_global(Image& image, string expected = "") {
128   return test_image(image, false, expected);
129 }
130
131 string get_expected(string imagefilename) {
132   string textfilename = imagefilename;
133   int dotpos = textfilename.rfind(".");
134   textfilename.replace(dotpos+1, textfilename.length() - dotpos - 1, "txt");
135   char data[MAX_EXPECTED];
136   FILE *fp = fopen(textfilename.data(), "rb");
137
138   if (!fp) {
139     // could not open file
140     return "";
141   }
142   // get file size
143   fseek(fp, 0, SEEK_END);
144   int toread = ftell(fp);
145   rewind(fp);
146   
147   if (toread > MAX_EXPECTED) {
148         cerr << "MAX_EXPECTED = " << MAX_EXPECTED << " but file '" << textfilename << "' has " << toread
149              << " bytes! Skipping..." << endl;
150     fclose(fp);
151     return "";
152   }
153   
154   int nread = fread(data, sizeof(char), toread, fp);
155   if (nread != toread) {
156     cerr << "Could not read entire contents of file '" << textfilename << "'! Skipping..." << endl;
157     fclose(fp);
158     return "";
159   }
160   fclose(fp);
161   data[nread] = '\0';
162   string expected(data);
163   return expected;
164 }
165
166 int main(int argc, char** argv) {
167   if (argc <= 1) {
168     cout << "Usage: " << argv[0] << " [--dump-raw] [--show-format] [--try-harder] [--show-filename] <filename1> [<filename2> ...]" << endl;
169     return 1;
170   }
171
172   int total = 0;
173   int gonly = 0;
174   int honly = 0;
175   int both = 0;
176   int neither = 0;
177
178   if (argc == 2) raw_dump = true;
179
180   for (int i = 1; i < argc; i++) {
181     string infilename = argv[i];
182     if (infilename.substr(infilename.length()-3,3).compare("txt") == 0) {
183       continue;
184     }
185     if (infilename.compare("--dump-raw") == 0) {
186       raw_dump = true;
187       continue;
188     }
189     if (infilename.compare("--show-format") == 0) {
190       show_format = true;
191       continue;
192     }
193     if (infilename.compare("--try-harder") == 0) {
194       tryHarder = true;
195       continue;
196     }
197     if (infilename.compare("--show-filename") == 0) {
198       show_filename = true;
199       continue;
200     }
201     if (!raw_dump)
202       cerr << "Processing: " << infilename << endl;
203     if (show_filename)
204       cout << infilename << " ";
205     Image image;
206     try {
207       image.read(infilename);
208     } catch (...) {
209       cerr << "Unable to open image, ignoring" << endl;
210       continue;
211     }
212
213     string expected;
214     expected = get_expected(infilename);
215
216     int gresult = 1;
217     int hresult = 1;
218
219     hresult = test_image_hybrid(image, expected);
220     gresult = test_image_global(image, expected);
221
222     gresult = gresult == 0;
223     hresult = hresult == 0;
224
225     gonly += gresult && !hresult;
226     honly += hresult && !gresult;
227     both += gresult && hresult;
228     neither += !gresult && !hresult;
229     total = total + 1;
230   }
231
232   if (!raw_dump)
233     cout << (honly+both)  << " passed hybrid, " << (gonly+both) << " passed global, "
234       << both << " pass both, " << neither << " pass neither, " << honly
235       << " passed only hybrid, " << gonly << " passed only global, of " << total
236       << " total." << endl;
237
238   return 0;
239 }
240
241