// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*- /* * Copyright 2010-2011 ZXing authors * * 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 #include #include #include "ImageReaderSource.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; using namespace zxing; using namespace zxing::multi; using namespace zxing::qrcode; namespace { bool more = false; bool test_mode = false; bool try_harder = false; bool search_multi = false; bool use_hybrid = false; bool use_global = false; bool verbose = false; } vector > decode(Ref image, DecodeHints hints) { Ref reader(new MultiFormatReader); return vector >(1, reader->decode(image, hints)); } vector > decode_multi(Ref image, DecodeHints hints) { MultiFormatReader delegate; GenericMultipleBarcodeReader reader(delegate); return reader.decodeMultiple(image, hints); } int read_image(Ref source, bool hybrid, string expected) { vector > results; string cell_result; int res = -1; try { Ref binarizer; if (hybrid) { binarizer = new HybridBinarizer(source); } else { binarizer = new GlobalHistogramBinarizer(source); } DecodeHints hints(DecodeHints::DEFAULT_HINT); hints.setTryHarder(try_harder); Ref binary(new BinaryBitmap(binarizer)); if (search_multi) { results = decode_multi(binary, hints); } else { results = decode(binary, hints); } res = 0; } catch (const ReaderException& e) { cell_result = "zxing::ReaderException: " + string(e.what()); res = -2; } catch (const zxing::IllegalArgumentException& e) { cell_result = "zxing::IllegalArgumentException: " + string(e.what()); res = -3; } catch (const zxing::Exception& e) { cell_result = "zxing::Exception: " + string(e.what()); res = -4; } catch (const std::exception& e) { cell_result = "std::exception: " + string(e.what()); res = -5; } if (test_mode && results.size() == 1) { std::string result = results[0]->getText()->getText(); if (expected.empty()) { cout << " Expected text or binary data for image missing." << endl << " Detected: " << result << endl; res = -6; } else { if (expected.compare(result) != 0) { cout << " Expected: " << expected << endl << " Detected: " << result << endl; cell_result = "data did not match"; res = -6; } } } if (res != 0 && (verbose || (use_global ^ use_hybrid))) { cout << (hybrid ? "Hybrid" : "Global") << " binarizer failed: " << cell_result << endl; } else if (!test_mode) { if (verbose) { cout << (hybrid ? "Hybrid" : "Global") << " binarizer succeeded: " << endl; } for (size_t i = 0; i < results.size(); i++) { if (more) { cout << " Format: " << BarcodeFormat::barcodeFormatNames[results[i]->getBarcodeFormat()] << endl; for (int j = 0; j < results[i]->getResultPoints()->size(); j++) { cout << " Point[" << j << "]: " << results[i]->getResultPoints()[j]->getX() << " " << results[i]->getResultPoints()[j]->getY() << endl; } } if (verbose) { cout << " "; } cout << results[i]->getText()->getText() << endl; } } return res; } string read_expected(string imagefilename) { string textfilename = imagefilename; string::size_type dotpos = textfilename.rfind("."); textfilename.replace(dotpos + 1, textfilename.length() - dotpos - 1, "txt"); ifstream textfile(textfilename.c_str(), ios::binary); textfilename.replace(dotpos + 1, textfilename.length() - dotpos - 1, "bin"); ifstream binfile(textfilename.c_str(), ios::binary); ifstream *file = 0; if (textfile.is_open()) { file = &textfile; } else if (binfile.is_open()) { file = &binfile; } else { return std::string(); } file->seekg(0, ios_base::end); size_t size = size_t(file->tellg()); file->seekg(0, ios_base::beg); if (size == 0) { return std::string(); } char* data = new char[size + 1]; file->read(data, size); data[size] = '\0'; string expected(data); delete[] data; return expected; } int main(int argc, char** argv) { if (argc <= 1) { cout << "Usage: " << argv[0] << " [OPTION]... ..." << endl << "Read barcodes from each IMAGE file." << endl << endl << "Options:" << endl << " (-h|--hybrid) use the hybrid binarizer (default)" << endl << " (-g|--global) use the global binarizer" << endl << " (-v|--verbose) chattier results printing" << endl << " --more display more information about the barcode" << endl << " --test-mode compare IMAGEs against text files" << endl << " --try-harder spend more time to try to find a barcode" << endl << " --search-multi search for more than one bar code" << endl << endl << "Example usage:" << endl << " zxing --test-mode *.jpg" << endl << endl; return 1; } int total = 0; int gonly = 0; int honly = 0; int both = 0; int neither = 0; for (int i = 1; i < argc; i++) { string filename = argv[i]; if (filename.compare("--verbose") == 0 || filename.compare("-v") == 0) { verbose = true; continue; } if (filename.compare("--hybrid") == 0 || filename.compare("-h") == 0) { use_hybrid = true; continue; } if (filename.compare("--global") == 0 || filename.compare("-g") == 0) { use_global = true; continue; } if (filename.compare("--more") == 0) { more = true; continue; } if (filename.compare("--test-mode") == 0) { test_mode = true; continue; } if (filename.compare("--try-harder") == 0) { try_harder = true; continue; } if (filename.compare("--search-multi") == 0){ search_multi = true; continue; } if (filename.length() > 3 && (filename.substr(filename.length() - 3, 3).compare("txt") == 0 || filename.substr(filename.length() - 3, 3).compare("bin") == 0)) { continue; } if (!use_global && !use_hybrid) { use_global = use_hybrid = true; } if (test_mode) { cerr << "Testing: " << filename << endl; } Ref source; try { source = ImageReaderSource::create(filename); } catch (const zxing::IllegalArgumentException &e) { cerr << e.what() << " (ignoring)" << endl; continue; } string expected = read_expected(filename); int gresult = 1; int hresult = 1; if (use_hybrid) { hresult = read_image(source, true, expected); } if (use_global && (verbose || hresult != 0)) { gresult = read_image(source, false, expected); if (!verbose && gresult != 0) { cout << "decoding failed" << endl; } } gresult = gresult == 0; hresult = hresult == 0; gonly += gresult && !hresult; honly += hresult && !gresult; both += gresult && hresult; neither += !gresult && !hresult; total = total + 1; } if (test_mode) { cout << endl << "Summary:" << endl << " " << total << " images tested total," << endl << " " << (honly + both) << " passed hybrid, " << (gonly + both) << " passed global, " << both << " pass both, " << endl << " " << honly << " passed only hybrid, " << gonly << " passed only global, " << neither << " pass neither." << endl; } return 0; }