用zxing 識別二維碼的main函式

pengfoo發表於2014-05-08
// -*- 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 <iostream>
#include <fstream>
#include <string>
#include "ImageReaderSource.h"
#include <zxing/common/Counted.h>
#include <zxing/Binarizer.h>
#include <zxing/MultiFormatReader.h>
#include <zxing/Result.h>
#include <zxing/ReaderException.h>
#include <zxing/common/GlobalHistogramBinarizer.h>
#include <zxing/common/HybridBinarizer.h>
#include <exception>
#include <zxing/Exception.h>
#include <zxing/common/IllegalArgumentException.h>
#include <zxing/BinaryBitmap.h>
#include <zxing/DecodeHints.h>

#include <zxing/qrcode/QRCodeReader.h>
#include <zxing/multi/qrcode/QRCodeMultiReader.h>
#include <zxing/multi/ByQuadrantReader.h>
#include <zxing/multi/MultipleBarcodeReader.h>
#include <zxing/multi/GenericMultipleBarcodeReader.h>

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<Ref<Result> > decode(Ref<BinaryBitmap> image, DecodeHints hints) {
  Ref<Reader> reader(new MultiFormatReader);
  return vector<Ref<Result> >(1, reader->decode(image, hints));
}

vector<Ref<Result> > decode_multi(Ref<BinaryBitmap> image, DecodeHints hints) {
  MultiFormatReader delegate;
  GenericMultipleBarcodeReader reader(delegate);
  return reader.decodeMultiple(image, hints);
}

int read_image(Ref<LuminanceSource> source, bool hybrid, string expected) {
  vector<Ref<Result> > results;
  string cell_result;
  int res = -1;

  try {
    Ref<Binarizer> binarizer;
    if (hybrid) {
      binarizer = new HybridBinarizer(source);
    } else {
      binarizer = new GlobalHistogramBinarizer(source);
    }
    DecodeHints hints(DecodeHints::DEFAULT_HINT);
    hints.setTryHarder(try_harder);
    Ref<BinaryBitmap> 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]... <IMAGE>..." << 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<LuminanceSource> 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;
}

相關文章