Added David Phillip Oster's fixes for compiling and getting the Barcodes app to scan for barcodes.

git-svn-id: https://zxing.googlecode.com/svn/trunk@1343 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
dmaclach 2010-05-07 17:10:06 +00:00
parent 0e7aedd046
commit 52e6d56a63
17 changed files with 1536 additions and 778 deletions

View file

@ -10,6 +10,7 @@ Brian Brown (Google)
Christian Brunschen (Google) Christian Brunschen (Google)
Daniel Switkin (Google) Daniel Switkin (Google)
Dave MacLachlan (Google) Dave MacLachlan (Google)
David Phillip Oster (Google)
David Albert (Bug Labs) David Albert (Bug Labs)
Diego Pierotto Diego Pierotto
Eric Kobrin (Velocitude) Eric Kobrin (Velocitude)

View file

@ -28,24 +28,24 @@
#include <zxing/common/Counted.h> #include <zxing/common/Counted.h>
namespace zxing { namespace zxing {
class Binarizer : public Counted { class Binarizer : public Counted {
private: private:
Ref<LuminanceSource> source_; Ref<LuminanceSource> source_;
Ref<BitMatrix> matrix_; Ref<BitArray> array_;
Ref<BitArray> array_; Ref<BitMatrix> matrix_;
public: public:
Binarizer(Ref<LuminanceSource> source); Binarizer(Ref<LuminanceSource> source);
virtual ~Binarizer(); virtual ~Binarizer();
virtual Ref<BitArray> estimateBlackRow(int y, Ref<BitArray> row)=0; virtual Ref<BitArray> estimateBlackRow(int y, Ref<BitArray> row)=0;
Ref<BitArray> getBlackRow(int y, Ref<BitArray> row); Ref<BitArray> getBlackRow(int y, Ref<BitArray> row);
virtual Ref<BitMatrix> estimateBlackMatrix() = 0; virtual Ref<BitMatrix> estimateBlackMatrix() = 0;
Ref<BitMatrix> getBlackMatrix(); Ref<BitMatrix> getBlackMatrix();
Ref<LuminanceSource> getSource(); Ref<LuminanceSource> getSource();
}; };
} }
#endif /* BINARIZER_H_ */ #endif /* BINARIZER_H_ */

View file

@ -24,154 +24,160 @@
#include <zxing/common/IllegalArgumentException.h> #include <zxing/common/IllegalArgumentException.h>
namespace zxing { namespace zxing {
using namespace std; using namespace std;
const int LUMINANCE_BITS = 5; const int LUMINANCE_BITS = 5;
const int LUMINANCE_SHIFT = 8 - LUMINANCE_BITS; const int LUMINANCE_SHIFT = 8 - LUMINANCE_BITS;
const int LUMINANCE_BUCKETS = 1 << LUMINANCE_BITS; const int LUMINANCE_BUCKETS = 1 << LUMINANCE_BITS;
GlobalHistogramBinarizer::GlobalHistogramBinarizer(Ref<LuminanceSource> source) : GlobalHistogramBinarizer::GlobalHistogramBinarizer(Ref<LuminanceSource> source) :
Binarizer(source) { Binarizer(source) {
}
GlobalHistogramBinarizer::~GlobalHistogramBinarizer() {
}
Ref<BitArray> GlobalHistogramBinarizer::estimateBlackRow(int y, Ref<BitArray> row){
vector<int> histogram(LUMINANCE_BUCKETS, 0);
LuminanceSource& source = *getSource();
int width = source.getWidth();
if (row == NULL || row->getSize() < width) {
row = new BitArray(width);
} else {
row->clear();
}
for (int x = 0; x < width; x++) {
unsigned char pixel = source.getPixel(x, y);
histogram[pixel >> LUMINANCE_SHIFT]++;
}
int blackPoint = estimate(histogram) << LUMINANCE_SHIFT;
Ref<BitArray> array_ref(new BitArray(width));
BitArray& array = *array_ref;
int left = source.getPixel(0, y);
int center = source.getPixel(1, y);
for (int x = 1; x < width - 1; x++) {
int right = source.getPixel(x+1, y);
// A simple -1 4 -1 box filter with a weight of 2.
int luminance = ((center << 2) - left - right) >> 1;
if (luminance < blackPoint) {
array.set(x);
}
left = center;
center = right;
}
return array_ref;
}
Ref<BitMatrix> GlobalHistogramBinarizer::estimateBlackMatrix() {
// Faster than working with the reference
LuminanceSource& source = *getSource();
int width = source.getWidth();
int height = source.getHeight();
vector<int> histogram(LUMINANCE_BUCKETS, 0);
// Quickly calculates the histogram by sampling four rows from the image. This proved to be
// more robust on the blackbox tests than sampling a diagonal as we used to do.
for (int y = 1; y < 5; y++) {
int row = height * y / 5;
int right = (width << 2) / 5;
int sdf;
for (int x = width / 5; x < right; x++) {
unsigned char pixel = source.getPixel(x, row);
histogram[pixel >> LUMINANCE_SHIFT]++;
sdf = histogram[pixel >> LUMINANCE_SHIFT];
}
}
int blackPoint = estimate(histogram) << LUMINANCE_SHIFT;
Ref<BitMatrix> matrix_ref(new BitMatrix(width, height));
BitMatrix& matrix = *matrix_ref;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
if (source.getPixel(x, y) <= blackPoint)
matrix.set(x, y);
}
}
return matrix_ref;
}
int GlobalHistogramBinarizer::estimate(vector<int> &histogram) {
int numBuckets = histogram.size();
int maxBucketCount = 0;
// Find tallest peak in histogram
int firstPeak = 0;
int firstPeakSize = 0;
for (int i = 0; i < numBuckets; i++) {
if (histogram[i] > firstPeakSize) {
firstPeak = i;
firstPeakSize = histogram[i];
}
if (histogram[i] > maxBucketCount) {
maxBucketCount = histogram[i];
}
}
// Find second-tallest peak -- well, another peak that is tall and not
// so close to the first one
int secondPeak = 0;
int secondPeakScore = 0;
for (int i = 0; i < numBuckets; i++) {
int distanceToBiggest = i - firstPeak;
// Encourage more distant second peaks by multiplying by square of distance
int score = histogram[i] * distanceToBiggest * distanceToBiggest;
if (score > secondPeakScore) {
secondPeak = i;
secondPeakScore = score;
}
}
// Put firstPeak first
if (firstPeak > secondPeak) {
int temp = firstPeak;
firstPeak = secondPeak;
secondPeak = temp;
}
// Kind of arbitrary; if the two peaks are very close, then we figure there is so little
// dynamic range in the image, that discriminating black and white is too error-prone.
// Decoding the image/line is either pointless, or may in some cases lead to a false positive
// for 1D formats, which are relatively lenient.
// We arbitrarily say "close" is "<= 1/16 of the total histogram buckets apart"
if (secondPeak - firstPeak <= numBuckets >> 4) {
throw IllegalArgumentException("Too little dynamic range in luminance");
}
// Find a valley between them that is low and closer to the white peak
int bestValley = secondPeak - 1;
int bestValleyScore = -1;
for (int i = secondPeak - 1; i > firstPeak; i--) {
int fromFirst = i - firstPeak;
// Favor a "valley" that is not too close to either peak -- especially not the black peak --
// and that has a low value of course
int score = fromFirst * fromFirst * (secondPeak - i) * (maxBucketCount - histogram[i]);
if (score > bestValleyScore) {
bestValley = i;
bestValleyScore = score;
}
}
return bestValley;
}
} }
GlobalHistogramBinarizer::~GlobalHistogramBinarizer() {
}
Ref<BitArray> GlobalHistogramBinarizer::estimateBlackRow(int y,
Ref<BitArray> row){
vector<int> histogram(LUMINANCE_BUCKETS, 0);
LuminanceSource& source = *getSource();
int width = source.getWidth();
if (row == NULL || static_cast<int>(row->getSize()) < width) {
row = new BitArray(width);
} else {
row->clear();
}
for (int x = 0; x < width; x++) {
unsigned char pixel = source.getPixel(x, y);
histogram[pixel >> LUMINANCE_SHIFT]++;
}
int blackPoint = estimate(histogram) << LUMINANCE_SHIFT;
Ref<BitArray> array_ref(new BitArray(width));
BitArray& array = *array_ref;
int left = source.getPixel(0, y);
int center = source.getPixel(1, y);
for (int x = 1; x < width - 1; x++) {
int right = source.getPixel(x+1, y);
// A simple -1 4 -1 box filter with a weight of 2.
int luminance = ((center << 2) - left - right) >> 1;
if (luminance < blackPoint) {
array.set(x);
}
left = center;
center = right;
}
return array_ref;
}
Ref<BitMatrix> GlobalHistogramBinarizer::estimateBlackMatrix() {
// Faster than working with the reference
LuminanceSource& source = *getSource();
int width = source.getWidth();
int height = source.getHeight();
vector<int> histogram(LUMINANCE_BUCKETS, 0);
// Quickly calculates the histogram by sampling four rows from the image.
// This proved to be more robust on the blackbox tests than sampling a
// diagonal as we used to do.
for (int y = 1; y < 5; y++) {
int row = height * y / 5;
int right = (width << 2) / 5;
int sdf;
for (int x = width / 5; x < right; x++) {
unsigned char pixel = source.getPixel(x, row);
histogram[pixel >> LUMINANCE_SHIFT]++;
sdf = histogram[pixel >> LUMINANCE_SHIFT];
}
}
int blackPoint = estimate(histogram) << LUMINANCE_SHIFT;
Ref<BitMatrix> matrix_ref(new BitMatrix(width, height));
BitMatrix& matrix = *matrix_ref;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
if (source.getPixel(x, y) <= blackPoint)
matrix.set(x, y);
}
}
return matrix_ref;
}
int GlobalHistogramBinarizer::estimate(vector<int> &histogram) {
int numBuckets = histogram.size();
int maxBucketCount = 0;
// Find tallest peak in histogram
int firstPeak = 0;
int firstPeakSize = 0;
for (int i = 0; i < numBuckets; i++) {
if (histogram[i] > firstPeakSize) {
firstPeak = i;
firstPeakSize = histogram[i];
}
if (histogram[i] > maxBucketCount) {
maxBucketCount = histogram[i];
}
}
// Find second-tallest peak -- well, another peak that is tall and not
// so close to the first one
int secondPeak = 0;
int secondPeakScore = 0;
for (int i = 0; i < numBuckets; i++) {
int distanceToBiggest = i - firstPeak;
// Encourage more distant second peaks by multiplying by square of distance
int score = histogram[i] * distanceToBiggest * distanceToBiggest;
if (score > secondPeakScore) {
secondPeak = i;
secondPeakScore = score;
}
}
// Put firstPeak first
if (firstPeak > secondPeak) {
int temp = firstPeak;
firstPeak = secondPeak;
secondPeak = temp;
}
// Kind of arbitrary; if the two peaks are very close, then we figure there is
// so little dynamic range in the image, that discriminating black and white
// is too error-prone.
// Decoding the image/line is either pointless, or may in some cases lead to
// a false positive for 1D formats, which are relatively lenient.
// We arbitrarily say "close" is
// "<= 1/16 of the total histogram buckets apart"
if (secondPeak - firstPeak <= numBuckets >> 4) {
throw IllegalArgumentException("Too little dynamic range in luminance");
}
// Find a valley between them that is low and closer to the white peak
int bestValley = secondPeak - 1;
int bestValleyScore = -1;
for (int i = secondPeak - 1; i > firstPeak; i--) {
int fromFirst = i - firstPeak;
// Favor a "valley" that is not too close to either peak -- especially not
// the black peak -- and that has a low value of course
int score = fromFirst * fromFirst * (secondPeak - i) *
(maxBucketCount - histogram[i]);
if (score > bestValleyScore) {
bestValley = i;
bestValleyScore = score;
}
}
return bestValley;
}
} // namespace zxing

View file

@ -28,8 +28,8 @@ PerspectiveTransform::PerspectiveTransform(float inA11, float inA21,
float inA22, float inA32, float inA22, float inA32,
float inA13, float inA23, float inA13, float inA23,
float inA33) : float inA33) :
a11(inA11), a21(inA21), a31(inA31), a12(inA12), a22(inA22), a32(inA32), a11(inA11), a12(inA12), a13(inA13), a21(inA21), a22(inA22), a23(inA23),
a13(inA13), a23(inA23), a33(inA33) {} a31(inA31), a32(inA32), a33(inA33) {}
Ref<PerspectiveTransform> PerspectiveTransform::quadrilateralToQuadrilateral(float x0, float y0, float x1, float y1, Ref<PerspectiveTransform> PerspectiveTransform::quadrilateralToQuadrilateral(float x0, float y0, float x1, float y1,
float x2, float y2, float x3, float y3, float x0p, float y0p, float x1p, float y1p, float x2p, float y2p, float x2, float y2, float x3, float y3, float x0p, float y0p, float x1p, float y1p, float x2p, float y2p,

View file

@ -28,13 +28,13 @@ int BitMatrixParser::copyBit(size_t x, size_t y, int versionBits) {
return bitMatrix_->get(x, y) ? (versionBits << 1) | 0x1 : versionBits << 1; return bitMatrix_->get(x, y) ? (versionBits << 1) | 0x1 : versionBits << 1;
} }
BitMatrixParser::BitMatrixParser(Ref<BitMatrix> bitMatrix) : parsedVersion_(NULL), BitMatrixParser::BitMatrixParser(Ref<BitMatrix> bitMatrix) : bitMatrix_(NULL),
bitMatrix_(NULL), parsedVersion_(NULL),
readBitMatrix_(NULL) { readBitMatrix_(NULL) {
size_t dimension = bitMatrix->getDimension(); size_t dimension = bitMatrix->getDimension();
if (dimension < 10 || dimension > 144 || (dimension & 0x01) != 0) if (dimension < 10 || dimension > 144 || (dimension & 0x01) != 0)
throw ReaderException("Dimension must be even, > 10 < 144"); throw ReaderException("Dimension must be even, > 10 < 144");
parsedVersion_ = readVersion(bitMatrix); parsedVersion_ = readVersion(bitMatrix);
bitMatrix_ = extractDataRegion(bitMatrix); bitMatrix_ = extractDataRegion(bitMatrix);
// TODO(bbrown): Make this work for rectangular symbols // TODO(bbrown): Make this work for rectangular symbols
@ -49,7 +49,7 @@ Ref<Version> BitMatrixParser::readVersion(Ref<BitMatrix> bitMatrix) {
// TODO(bbrown): make this work for rectangular dimensions as well. // TODO(bbrown): make this work for rectangular dimensions as well.
int numRows = bitMatrix->getDimension(); int numRows = bitMatrix->getDimension();
int numColumns = numRows; int numColumns = numRows;
Ref<Version> version = parsedVersion_->getVersionForDimensions(numRows, numColumns); Ref<Version> version = parsedVersion_->getVersionForDimensions(numRows, numColumns);
if (version != 0) { if (version != 0) {
return version; return version;
@ -66,12 +66,12 @@ ArrayRef<unsigned char> BitMatrixParser::readCodewords() {
// TODO(bbrown): Data Matrix can be rectangular, assuming square for now // TODO(bbrown): Data Matrix can be rectangular, assuming square for now
int numRows = bitMatrix_->getDimension(); int numRows = bitMatrix_->getDimension();
int numColumns = numRows; int numColumns = numRows;
bool corner1Read = false; bool corner1Read = false;
bool corner2Read = false; bool corner2Read = false;
bool corner3Read = false; bool corner3Read = false;
bool corner4Read = false; bool corner4Read = false;
// Read all of the codewords // Read all of the codewords
do { do {
// Check the four corner cases // Check the four corner cases
@ -106,7 +106,7 @@ ArrayRef<unsigned char> BitMatrixParser::readCodewords() {
} while ((row >= 0) && (column < numColumns)); } while ((row >= 0) && (column < numColumns));
row += 1; row += 1;
column +=3; column +=3;
// Sweep downward diagonally to the left // Sweep downward diagonally to the left
do { do {
if ((row >= 0) && (column < numColumns) && !readBitMatrix_->get(column, row)) { if ((row >= 0) && (column < numColumns) && !readBitMatrix_->get(column, row)) {
@ -125,7 +125,7 @@ ArrayRef<unsigned char> BitMatrixParser::readCodewords() {
} }
return result; return result;
} }
bool BitMatrixParser::readModule(int row, int column, int numRows, int numColumns) { bool BitMatrixParser::readModule(int row, int column, int numRows, int numColumns) {
// Adjust the row and column indices based on boundary wrapping // Adjust the row and column indices based on boundary wrapping
if (row < 0) { if (row < 0) {
@ -139,7 +139,7 @@ bool BitMatrixParser::readModule(int row, int column, int numRows, int numColumn
readBitMatrix_->set(column, row); readBitMatrix_->set(column, row);
return bitMatrix_->get(column, row); return bitMatrix_->get(column, row);
} }
int BitMatrixParser::readUtah(int row, int column, int numRows, int numColumns) { int BitMatrixParser::readUtah(int row, int column, int numRows, int numColumns) {
int currentByte = 0; int currentByte = 0;
if (readModule(row - 2, column - 2, numRows, numColumns)) { if (readModule(row - 2, column - 2, numRows, numColumns)) {
@ -175,7 +175,7 @@ int BitMatrixParser::readUtah(int row, int column, int numRows, int numColumns)
} }
return currentByte; return currentByte;
} }
int BitMatrixParser::readCorner1(int numRows, int numColumns) { int BitMatrixParser::readCorner1(int numRows, int numColumns) {
int currentByte = 0; int currentByte = 0;
if (readModule(numRows - 1, 0, numRows, numColumns)) { if (readModule(numRows - 1, 0, numRows, numColumns)) {
@ -211,7 +211,7 @@ int BitMatrixParser::readCorner1(int numRows, int numColumns) {
} }
return currentByte; return currentByte;
} }
int BitMatrixParser::readCorner2(int numRows, int numColumns) { int BitMatrixParser::readCorner2(int numRows, int numColumns) {
int currentByte = 0; int currentByte = 0;
if (readModule(numRows - 3, 0, numRows, numColumns)) { if (readModule(numRows - 3, 0, numRows, numColumns)) {
@ -247,7 +247,7 @@ int BitMatrixParser::readCorner2(int numRows, int numColumns) {
} }
return currentByte; return currentByte;
} }
int BitMatrixParser::readCorner3(int numRows, int numColumns) { int BitMatrixParser::readCorner3(int numRows, int numColumns) {
int currentByte = 0; int currentByte = 0;
if (readModule(numRows - 1, 0, numRows, numColumns)) { if (readModule(numRows - 1, 0, numRows, numColumns)) {
@ -283,7 +283,7 @@ int BitMatrixParser::readCorner3(int numRows, int numColumns) {
} }
return currentByte; return currentByte;
} }
int BitMatrixParser::readCorner4(int numRows, int numColumns) { int BitMatrixParser::readCorner4(int numRows, int numColumns) {
int currentByte = 0; int currentByte = 0;
if (readModule(numRows - 3, 0, numRows, numColumns)) { if (readModule(numRows - 3, 0, numRows, numColumns)) {
@ -319,25 +319,25 @@ int BitMatrixParser::readCorner4(int numRows, int numColumns) {
} }
return currentByte; return currentByte;
} }
Ref<BitMatrix> BitMatrixParser::extractDataRegion(Ref<BitMatrix> bitMatrix) { Ref<BitMatrix> BitMatrixParser::extractDataRegion(Ref<BitMatrix> bitMatrix) {
int symbolSizeRows = parsedVersion_->getSymbolSizeRows(); int symbolSizeRows = parsedVersion_->getSymbolSizeRows();
int symbolSizeColumns = parsedVersion_->getSymbolSizeColumns(); int symbolSizeColumns = parsedVersion_->getSymbolSizeColumns();
// TODO(bbrown): Make this work with rectangular codes // TODO(bbrown): Make this work with rectangular codes
if ((int)bitMatrix->getDimension() != symbolSizeRows) { if ((int)bitMatrix->getDimension() != symbolSizeRows) {
throw IllegalArgumentException("Dimension of bitMarix must match the version size"); throw IllegalArgumentException("Dimension of bitMarix must match the version size");
} }
int dataRegionSizeRows = parsedVersion_->getDataRegionSizeRows(); int dataRegionSizeRows = parsedVersion_->getDataRegionSizeRows();
int dataRegionSizeColumns = parsedVersion_->getDataRegionSizeColumns(); int dataRegionSizeColumns = parsedVersion_->getDataRegionSizeColumns();
int numDataRegionsRow = symbolSizeRows / dataRegionSizeRows; int numDataRegionsRow = symbolSizeRows / dataRegionSizeRows;
int numDataRegionsColumn = symbolSizeColumns / dataRegionSizeColumns; int numDataRegionsColumn = symbolSizeColumns / dataRegionSizeColumns;
int sizeDataRegionRow = numDataRegionsRow * dataRegionSizeRows; int sizeDataRegionRow = numDataRegionsRow * dataRegionSizeRows;
//int sizeDataRegionColumn = numDataRegionsColumn * dataRegionSizeColumns; //int sizeDataRegionColumn = numDataRegionsColumn * dataRegionSizeColumns;
// TODO(bbrown): Make this work with rectangular codes // TODO(bbrown): Make this work with rectangular codes
Ref<BitMatrix> bitMatrixWithoutAlignment(new BitMatrix(sizeDataRegionRow)); Ref<BitMatrix> bitMatrixWithoutAlignment(new BitMatrix(sizeDataRegionRow));
for (int dataRegionRow = 0; dataRegionRow < numDataRegionsRow; ++dataRegionRow) { for (int dataRegionRow = 0; dataRegionRow < numDataRegionsRow; ++dataRegionRow) {

View file

@ -33,8 +33,8 @@ namespace datamatrix {
class BitMatrixParser : public Counted { class BitMatrixParser : public Counted {
private: private:
Ref<BitMatrix> bitMatrix_; Ref<BitMatrix> bitMatrix_;
Ref<BitMatrix> readBitMatrix_;
Ref<Version> parsedVersion_; Ref<Version> parsedVersion_;
Ref<BitMatrix> readBitMatrix_;
int copyBit(size_t x, size_t y, int versionBits); int copyBit(size_t x, size_t y, int versionBits);

View file

@ -29,14 +29,14 @@ namespace datamatrix {
using namespace std; using namespace std;
ResultPointsAndTransitions::ResultPointsAndTransitions() : from_(), to_(), transitions_(0) { ResultPointsAndTransitions::ResultPointsAndTransitions() : to_(), from_(), transitions_(0) {
Ref<CornerPoint> ref(new CornerPoint(0,0)); Ref<CornerPoint> ref(new CornerPoint(0,0));
from_ = ref; from_ = ref;
to_ = ref; to_ = ref;
} }
ResultPointsAndTransitions::ResultPointsAndTransitions(Ref<CornerPoint> from, Ref<CornerPoint> to, int transitions) : ResultPointsAndTransitions::ResultPointsAndTransitions(Ref<CornerPoint> from, Ref<CornerPoint> to, int transitions) :
from_(from), to_(to), transitions_(transitions) { to_(to), from_(from), transitions_(transitions) {
} }
Ref<CornerPoint> ResultPointsAndTransitions::getFrom() { Ref<CornerPoint> ResultPointsAndTransitions::getFrom() {
@ -67,12 +67,12 @@ Ref<DetectorResult> Detector::detect() {
// Point A and D are across the diagonal from one another, // Point A and D are across the diagonal from one another,
// as are B and C. Figure out which are the solid black lines // as are B and C. Figure out which are the solid black lines
// by counting transitions // by counting transitions
std::vector<Ref<ResultPointsAndTransitions> > transitions(4); std::vector<Ref<ResultPointsAndTransitions> > transitions(4);
transitions[0].reset(transitionsBetween(pointA, pointB)); transitions[0].reset(transitionsBetween(pointA, pointB));
transitions[1].reset(transitionsBetween(pointA, pointC)); transitions[1].reset(transitionsBetween(pointA, pointC));
transitions[2].reset(transitionsBetween(pointB, pointD)); transitions[2].reset(transitionsBetween(pointB, pointD));
transitions[3].reset(transitionsBetween(pointC, pointD)); transitions[3].reset(transitionsBetween(pointC, pointD));
insertionSort(transitions); insertionSort(transitions);
// Sort by number of transitions. First two will be the two solid sides; last two // Sort by number of transitions. First two will be the two solid sides; last two
@ -85,42 +85,42 @@ Ref<DetectorResult> Detector::detect() {
Ref<CornerPoint> maybeTopLeft; Ref<CornerPoint> maybeTopLeft;
Ref<CornerPoint> bottomLeft; Ref<CornerPoint> bottomLeft;
Ref<CornerPoint> maybeBottomRight; Ref<CornerPoint> maybeBottomRight;
if (lSideOne->getFrom()->equals(lSideOne->getTo())) { if (lSideOne->getFrom()->equals(lSideOne->getTo())) {
bottomLeft = lSideOne->getFrom(); bottomLeft = lSideOne->getFrom();
maybeTopLeft = lSideTwo->getFrom(); maybeTopLeft = lSideTwo->getFrom();
maybeBottomRight = lSideTwo->getTo(); maybeBottomRight = lSideTwo->getTo();
} }
else if (lSideOne->getFrom()->equals(lSideTwo->getFrom())) { else if (lSideOne->getFrom()->equals(lSideTwo->getFrom())) {
bottomLeft = lSideOne->getFrom(); bottomLeft = lSideOne->getFrom();
maybeTopLeft = lSideOne->getTo(); maybeTopLeft = lSideOne->getTo();
maybeBottomRight = lSideTwo->getTo(); maybeBottomRight = lSideTwo->getTo();
} }
else if (lSideOne->getFrom()->equals(lSideTwo->getTo())) { else if (lSideOne->getFrom()->equals(lSideTwo->getTo())) {
bottomLeft = lSideOne->getFrom(); bottomLeft = lSideOne->getFrom();
maybeTopLeft = lSideOne->getTo(); maybeTopLeft = lSideOne->getTo();
maybeBottomRight = lSideTwo->getFrom(); maybeBottomRight = lSideTwo->getFrom();
} }
else if (lSideOne->getTo()->equals(lSideTwo->getFrom())) { else if (lSideOne->getTo()->equals(lSideTwo->getFrom())) {
bottomLeft = lSideOne->getTo(); bottomLeft = lSideOne->getTo();
maybeTopLeft = lSideOne->getFrom(); maybeTopLeft = lSideOne->getFrom();
maybeBottomRight = lSideTwo->getTo(); maybeBottomRight = lSideTwo->getTo();
} }
else if (lSideOne->getTo()->equals(lSideTwo->getTo())) { else if (lSideOne->getTo()->equals(lSideTwo->getTo())) {
bottomLeft = lSideOne->getTo(); bottomLeft = lSideOne->getTo();
maybeTopLeft = lSideOne->getFrom(); maybeTopLeft = lSideOne->getFrom();
maybeBottomRight = lSideTwo->getFrom(); maybeBottomRight = lSideTwo->getFrom();
} }
else { else {
bottomLeft = lSideTwo->getFrom(); bottomLeft = lSideTwo->getFrom();
maybeTopLeft = lSideOne->getTo(); maybeTopLeft = lSideOne->getTo();
maybeBottomRight = lSideOne->getFrom(); maybeBottomRight = lSideOne->getFrom();
} }
// Bottom left is correct but top left and bottom right might be switched // Bottom left is correct but top left and bottom right might be switched
std::vector<Ref<CornerPoint> > corners(3); std::vector<Ref<CornerPoint> > corners(3);
corners[0].reset(maybeTopLeft); corners[0].reset(maybeTopLeft);
corners[1].reset(bottomLeft); corners[1].reset(bottomLeft);
corners[2].reset(maybeBottomRight); corners[2].reset(maybeBottomRight);
// Use the dot product trick to sort them out // Use the dot product trick to sort them out
orderBestPatterns(corners); orderBestPatterns(corners);
@ -141,9 +141,9 @@ Ref<DetectorResult> Detector::detect() {
topRight = pointD; topRight = pointD;
} }
float topRightX = (bottomRight->getX() - bottomLeft->getX()) + topLeft->getX(); float topRightX = (bottomRight->getX() - bottomLeft->getX()) + topLeft->getX();
float topRightY = (bottomRight->getY() - bottomLeft->getY()) + topLeft->getY(); float topRightY = (bottomRight->getY() - bottomLeft->getY()) + topLeft->getY();
Ref<CornerPoint> topR(new CornerPoint(topRightX,topRightY)); Ref<CornerPoint> topR(new CornerPoint(topRightX,topRightY));
// Next determine the dimension by tracing along the top or right side and counting black/white // Next determine the dimension by tracing along the top or right side and counting black/white
// transitions. Since we start inside a black module, we should see a number of transitions // transitions. Since we start inside a black module, we should see a number of transitions
@ -153,7 +153,7 @@ Ref<DetectorResult> Detector::detect() {
// adjacent to the white module at the top right. Tracing to that corner from either the top left // adjacent to the white module at the top right. Tracing to that corner from either the top left
// or bottom right should work here. The number of transitions could be higher than it should be // or bottom right should work here. The number of transitions could be higher than it should be
// due to noise. So we try both and take the min. // due to noise. So we try both and take the min.
int dimension = min(transitionsBetween(topLeft, topRight)->getTransitions(), int dimension = min(transitionsBetween(topLeft, topRight)->getTransitions(),
transitionsBetween(bottomRight, topRight)->getTransitions()); transitionsBetween(bottomRight, topRight)->getTransitions());
if ((dimension & 0x01) == 1) { if ((dimension & 0x01) == 1) {
// it can't be odd, so, round... up? // it can't be odd, so, round... up?
@ -161,14 +161,14 @@ Ref<DetectorResult> Detector::detect() {
} }
dimension += 2; dimension += 2;
Ref<PerspectiveTransform> transform = createTransform(topLeft, topR, bottomLeft, bottomRight, dimension); Ref<PerspectiveTransform> transform = createTransform(topLeft, topR, bottomLeft, bottomRight, dimension);
Ref<BitMatrix> bits(sampleGrid(image_, dimension, transform)); Ref<BitMatrix> bits(sampleGrid(image_, dimension, transform));
std::vector<Ref<ResultPoint> > points(4); std::vector<Ref<ResultPoint> > points(4);
points[0].reset(pointA); points[0].reset(pointA);
points[1].reset(pointB); points[1].reset(pointB);
points[2].reset(pointC); points[2].reset(pointC);
points[3].reset(pointD); points[3].reset(pointD);
Ref<DetectorResult> detectorResult(new DetectorResult(bits, points, transform)); Ref<DetectorResult> detectorResult(new DetectorResult(bits, points, transform));
return detectorResult; return detectorResult;
} }
@ -210,7 +210,7 @@ Ref<ResultPointsAndTransitions> Detector::transitionsBetween(Ref<CornerPoint> fr
error -= dx; error -= dx;
} }
} }
Ref<ResultPointsAndTransitions> result(new ResultPointsAndTransitions(from, to, transitions)); Ref<ResultPointsAndTransitions> result(new ResultPointsAndTransitions(from, to, transitions));
return result; return result;
} }
@ -244,20 +244,20 @@ Ref<BitMatrix> Detector::sampleGrid(Ref<BitMatrix> image, int dimension, Ref<Per
void Detector::insertionSort(std::vector<Ref<ResultPointsAndTransitions> > &vector) { void Detector::insertionSort(std::vector<Ref<ResultPointsAndTransitions> > &vector) {
int max = vector.size(); int max = vector.size();
bool swapped = true; bool swapped = true;
Ref<ResultPointsAndTransitions> value; Ref<ResultPointsAndTransitions> value;
Ref<ResultPointsAndTransitions> valueB; Ref<ResultPointsAndTransitions> valueB;
do { do {
swapped = false; swapped = false;
for (int i = 1; i < max; i++) { for (int i = 1; i < max; i++) {
value = vector[i-1]; value = vector[i-1];
if (compare(value, (valueB = vector[i])) > 0) { if (compare(value, (valueB = vector[i])) > 0) {
swapped = true; swapped = true;
vector[i-1].reset(valueB); vector[i-1].reset(valueB);
vector[i].reset(value); vector[i].reset(value);
} }
} }
} while (swapped); } while (swapped);
} }
void Detector::orderBestPatterns(std::vector<Ref<CornerPoint> > &patterns) { void Detector::orderBestPatterns(std::vector<Ref<CornerPoint> > &patterns) {
// Find distances between pattern centers // Find distances between pattern centers
@ -293,7 +293,7 @@ void Detector::orderBestPatterns(std::vector<Ref<CornerPoint> > &patterns) {
patterns[0] = pointA; patterns[0] = pointA;
patterns[1] = pointB; patterns[1] = pointB;
patterns[2] = pointC; patterns[2] = pointC;
} }
float Detector::distance(float x1, float x2, float y1, float y2) { float Detector::distance(float x1, float x2, float y1, float y2) {

View file

@ -26,321 +26,333 @@
#include <limits.h> #include <limits.h>
namespace zxing { namespace zxing {
namespace oned { namespace oned {
static const char* ALPHABET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. *$/+%"; static const char* ALPHABET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. *$/+%";
/** /**
* These represent the encodings of characters, as patterns of wide and narrow bars. * These represent the encodings of characters, as patterns of wide and narrow
* The 9 least-significant bits of each int correspond to the pattern of wide and narrow, * bars.
* with 1s representing "wide" and 0s representing narrow. * The 9 least-significant bits of each int correspond to the pattern of wide
*/ * and narrow, with 1s representing "wide" and 0s representing narrow.
const int CHARACTER_ENCODINGS_LEN = 44; */
static int CHARACTER_ENCODINGS[CHARACTER_ENCODINGS_LEN] = { const int CHARACTER_ENCODINGS_LEN = 44;
0x034, 0x121, 0x061, 0x160, 0x031, 0x130, 0x070, 0x025, 0x124, 0x064, // 0-9 static int CHARACTER_ENCODINGS[CHARACTER_ENCODINGS_LEN] = {
0x109, 0x049, 0x148, 0x019, 0x118, 0x058, 0x00D, 0x10C, 0x04C, 0x01C, // A-J 0x034, 0x121, 0x061, 0x160, 0x031, 0x130, 0x070, 0x025, 0x124, 0x064, // 0-9
0x103, 0x043, 0x142, 0x013, 0x112, 0x052, 0x007, 0x106, 0x046, 0x016, // K-T 0x109, 0x049, 0x148, 0x019, 0x118, 0x058, 0x00D, 0x10C, 0x04C, 0x01C, // A-J
0x181, 0x0C1, 0x1C0, 0x091, 0x190, 0x0D0, 0x085, 0x184, 0x0C4, 0x094, // U-* 0x103, 0x043, 0x142, 0x013, 0x112, 0x052, 0x007, 0x106, 0x046, 0x016, // K-T
0x0A8, 0x0A2, 0x08A, 0x02A // $-% 0x181, 0x0C1, 0x1C0, 0x091, 0x190, 0x0D0, 0x085, 0x184, 0x0C4, 0x094, // U-*
}; 0x0A8, 0x0A2, 0x08A, 0x02A // $-%
};
static int ASTERISK_ENCODING = 0x094;
static const char* ALPHABET_STRING = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. *$/+%"; static int ASTERISK_ENCODING = 0x094;
static const char* ALPHABET_STRING =
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. *$/+%";
/**
* Creates a reader that assumes all encoded data is data, and does not treat the final
* character as a check digit. It will not decoded "extended Code 39" sequences. /**
*/ * Creates a reader that assumes all encoded data is data, and does not treat
Code39Reader::Code39Reader() : alphabet_string(ALPHABET_STRING), * the final character as a check digit. It will not decoded "extended
usingCheckDigit(false), * Code 39" sequences.
extendedMode(false) { */
} Code39Reader::Code39Reader() : alphabet_string(ALPHABET_STRING),
usingCheckDigit(false),
/** extendedMode(false) {
* Creates a reader that can be configured to check the last character as a check digit. }
* It will not decoded "extended Code 39" sequences.
* /**
* @param usingCheckDigit if true, treat the last data character as a check digit, not * Creates a reader that can be configured to check the last character as a
* data, and verify that the checksum passes. * check digit. It will not decoded "extended Code 39" sequences.
*/ *
Code39Reader::Code39Reader(bool usingCheckDigit_) : alphabet_string(ALPHABET_STRING), * @param usingCheckDigit if true, treat the last data character as a check
usingCheckDigit(usingCheckDigit_), * digit, not data, and verify that the checksum passes.
extendedMode(false) { */
} Code39Reader::Code39Reader(bool usingCheckDigit_) :
alphabet_string(ALPHABET_STRING),
usingCheckDigit(usingCheckDigit_),
extendedMode(false) {
}
Ref<Result> Code39Reader::decodeRow(int rowNumber, Ref<BitArray> row){
int* start = findAsteriskPattern(row);
int nextStart = start[1];
int end = row->getSize();
// Read off white space
while (nextStart < end && !row->get(nextStart)) {
nextStart++;
}
std::string tmpResultString;
int countersLen = 9;
int* counters = new int[countersLen];
for (int i=0; i<countersLen; i++) {
counters[i] = 0;
}
char decodedChar;
int lastStart;
do {
try {
recordPattern(row, nextStart, counters, countersLen);
} catch (ReaderException re) {
delete [] start;
throw re;
}
int pattern = toNarrowWidePattern(counters, countersLen);
if (pattern < 0) {
delete [] start;
throw ReaderException("pattern < 0");
}
decodedChar = patternToChar(pattern);
tmpResultString.append(1, decodedChar);
lastStart = nextStart;
for (int i = 0; i < countersLen; i++) {
nextStart += counters[i];
}
// Read off white space
while (nextStart < end && !row->get(nextStart)) {
nextStart++;
}
} while (decodedChar != '*');
tmpResultString.erase(tmpResultString.length()-1, 1);// remove asterisk
// Look for whitespace after pattern:
int lastPatternSize = 0;
for (int i = 0; i < countersLen; i++) {
lastPatternSize += counters[i];
}
// IS begin
delete [] counters;
// IS end
int whiteSpaceAfterEnd = nextStart - lastStart - lastPatternSize;
// If 50% of last pattern size, following last pattern, is not whitespace,
// fail (but if it's whitespace to the very end of the image, that's OK)
if (nextStart != end && whiteSpaceAfterEnd / 2 < lastPatternSize) {
delete [] start;
throw ReaderException("too short end white space");
}
if (usingCheckDigit) {
int max = tmpResultString.length() - 1;
unsigned int total = 0;
for (int i = 0; i < max; i++) {
total += alphabet_string.find_first_of(tmpResultString[i], 0);
}
if (total % 43 != alphabet_string.find_first_of(tmpResultString[max], 0)) {
throw ReaderException("");
}
tmpResultString.erase(max, 1);
}
Ref<String> resultString(new String(tmpResultString));
if (extendedMode) {
delete resultString;
resultString = decodeExtended(tmpResultString);
}
if (tmpResultString.length() == 0) {
delete [] start;
// Almost surely a false positive
throw ReaderException("");
}
float left = (float) (start[1] + start[0]) / 2.0f;
float right = (float) (nextStart + lastStart) / 2.0f;
std::vector< Ref<ResultPoint> > resultPoints(2);
Ref<OneDResultPoint> resultPoint1(
new OneDResultPoint(left, (float) rowNumber));
Ref<OneDResultPoint> resultPoint2(
new OneDResultPoint(right, (float) rowNumber));
resultPoints[0] = resultPoint1;
resultPoints[1] = resultPoint2;
ArrayRef<unsigned char> resultBytes(1);
delete [] start;
Ref<Result> res(new Result(
resultString, resultBytes, resultPoints, BarcodeFormat_CODE_39));
return res;
}
int* Code39Reader::findAsteriskPattern(Ref<BitArray> row){
int width = row->getSize();
int rowOffset = 0;
while (rowOffset < width) {
if (row->get(rowOffset)) {
break;
}
rowOffset++;
}
int counterPosition = 0;
int countersLen = 9;
int* counters = new int[countersLen];
for (int i=0; i<countersLen; i++) {
counters[i] = 0;
}
int patternStart = rowOffset;
bool isWhite = false;
int patternLength = countersLen;
for (int i = rowOffset; i < width; i++) {
bool pixel = row->get(i);
if (pixel ^ isWhite) {
counters[counterPosition]++;
} else {
if (counterPosition == patternLength - 1) {
if (toNarrowWidePattern(counters, countersLen) == ASTERISK_ENCODING) {
// Look for whitespace before start pattern, >= 50% of width of
// start pattern.
long double longPatternOffset =
fmaxl(0, patternStart - (i - patternStart) / 2);
if (row->isRange(longPatternOffset, patternStart, false)) {
int* resultValue = new int[2];
resultValue[0] = patternStart;
resultValue[1] = i;
return resultValue;
}
}
patternStart += counters[0] + counters[1];
for (int y = 2; y < patternLength; y++) {
counters[y - 2] = counters[y];
}
counters[patternLength - 2] = 0;
counters[patternLength - 1] = 0;
counterPosition--;
} else {
counterPosition++;
}
counters[counterPosition] = 1;
isWhite = !isWhite;
}
}
// IS begin
delete [] counters;
// IS end
throw ReaderException("");
}
// For efficiency, returns -1 on failure. Not throwing here saved as many as
// 700 exceptions per image when using some of our blackbox images.
int Code39Reader::toNarrowWidePattern(int counters[], int countersLen){
int numCounters = countersLen;
int maxNarrowCounter = 0;
int wideCounters;
do {
int minCounter = INT_MAX;
for (int i = 0; i < numCounters; i++) {
int counter = counters[i];
if (counter < minCounter && counter > maxNarrowCounter) {
minCounter = counter;
}
}
maxNarrowCounter = minCounter;
wideCounters = 0;
int totalWideCountersWidth = 0;
int pattern = 0;
for (int i = 0; i < numCounters; i++) {
int counter = counters[i];
if (counters[i] > maxNarrowCounter) {
pattern |= 1 << (numCounters - 1 - i);
wideCounters++;
totalWideCountersWidth += counter;
}
}
if (wideCounters == 3) {
// Found 3 wide counters, but are they close enough in width?
// We can perform a cheap, conservative check to see if any individual
// counter is more than 1.5 times the average:
for (int i = 0; i < numCounters && wideCounters > 0; i++) {
int counter = counters[i];
if (counters[i] > maxNarrowCounter) {
wideCounters--;
// totalWideCountersWidth = 3 * average, so this checks if
// counter >= 3/2 * average.
if ((counter << 1) >= totalWideCountersWidth) {
return -1;
}
}
}
return pattern;
}
} while (wideCounters > 3);
return -1;
}
char Code39Reader::patternToChar(int pattern){
for (int i = 0; i < CHARACTER_ENCODINGS_LEN; i++) {
if (CHARACTER_ENCODINGS[i] == pattern) {
return ALPHABET[i];
}
}
throw ReaderException("");
}
Ref<String> Code39Reader::decodeExtended(std::string encoded){
int length = encoded.length();
std::string tmpDecoded;
for (int i = 0; i < length; i++) {
char c = encoded[i];
if (c == '+' || c == '$' || c == '%' || c == '/') {
char next = encoded[i + 1];
char decodedChar = '\0';
switch (c) {
case '+':
// +A to +Z map to a to z
if (next >= 'A' && next <= 'Z') {
decodedChar = (char) (next + 32);
} else {
throw ReaderException("");
}
break;
case '$':
// $A to $Z map to control codes SH to SB
if (next >= 'A' && next <= 'Z') {
decodedChar = (char) (next - 64);
} else {
throw ReaderException("");
}
break;
case '%':
// %A to %E map to control codes ESC to US
if (next >= 'A' && next <= 'E') {
decodedChar = (char) (next - 38);
} else if (next >= 'F' && next <= 'W') {
decodedChar = (char) (next - 11);
} else {
throw ReaderException("");
}
break;
case '/':
// /A to /O map to ! to , and /Z maps to :
if (next >= 'A' && next <= 'O') {
decodedChar = (char) (next - 32);
} else if (next == 'Z') {
decodedChar = ':';
} else {
throw ReaderException("");
}
break;
}
tmpDecoded.append(1, decodedChar);
// bump up i again since we read two characters
i++;
} else {
tmpDecoded.append(1, c);
}
}
Ref<String> decoded(new String(tmpDecoded));
return decoded;
}
} // namespace oned
} // namespace zxing
Ref<Result> Code39Reader::decodeRow(int rowNumber, Ref<BitArray> row){
int* start = findAsteriskPattern(row);
int nextStart = start[1];
int end = row->getSize();
// Read off white space
while (nextStart < end && !row->get(nextStart)) {
nextStart++;
}
std::string tmpResultString;
int countersLen = 9;
int* counters = new int[countersLen];
for (int i=0; i<countersLen; i++) {
counters[i] = 0;
}
char decodedChar;
int lastStart;
do {
try {
recordPattern(row, nextStart, counters, countersLen);
} catch (ReaderException re) {
delete [] start;
throw re;
}
int pattern = toNarrowWidePattern(counters, countersLen);
if (pattern < 0) {
delete [] start;
throw ReaderException("pattern < 0");
}
decodedChar = patternToChar(pattern);
tmpResultString.append(1, decodedChar);
lastStart = nextStart;
for (int i = 0; i < countersLen; i++) {
nextStart += counters[i];
}
// Read off white space
while (nextStart < end && !row->get(nextStart)) {
nextStart++;
}
} while (decodedChar != '*');
tmpResultString.erase(tmpResultString.length()-1, 1);// remove asterisk
// Look for whitespace after pattern:
int lastPatternSize = 0;
for (int i = 0; i < countersLen; i++) {
lastPatternSize += counters[i];
}
// IS begin
delete [] counters;
// IS end
int whiteSpaceAfterEnd = nextStart - lastStart - lastPatternSize;
// If 50% of last pattern size, following last pattern, is not whitespace, fail
// (but if it's whitespace to the very end of the image, that's OK)
if (nextStart != end && whiteSpaceAfterEnd / 2 < lastPatternSize) {
delete [] start;
throw ReaderException("too short end white space");
}
if (usingCheckDigit) {
int max = tmpResultString.length() - 1;
int total = 0;
for (int i = 0; i < max; i++) {
total += alphabet_string.find_first_of(tmpResultString[i], 0);
}
if (total % 43 != alphabet_string.find_first_of(tmpResultString[max], 0)) {
throw ReaderException("");
}
tmpResultString.erase(max, 1);
}
Ref<String> resultString(new String(tmpResultString));
if (extendedMode) {
delete resultString;
resultString = decodeExtended(tmpResultString);
}
if (tmpResultString.length() == 0) {
delete [] start;
// Almost surely a false positive
throw ReaderException("");
}
float left = (float) (start[1] + start[0]) / 2.0f;
float right = (float) (nextStart + lastStart) / 2.0f;
std::vector< Ref<ResultPoint> > resultPoints(2);
Ref<OneDResultPoint> resultPoint1(new OneDResultPoint(left, (float) rowNumber));
Ref<OneDResultPoint> resultPoint2(new OneDResultPoint(right, (float) rowNumber));
resultPoints[0] = resultPoint1;
resultPoints[1] = resultPoint2;
ArrayRef<unsigned char> resultBytes(1);
delete [] start;
Ref<Result> res(new Result(resultString, resultBytes, resultPoints, BarcodeFormat_CODE_39));
return res;
}
int* Code39Reader::findAsteriskPattern(Ref<BitArray> row){
int width = row->getSize();
int rowOffset = 0;
while (rowOffset < width) {
if (row->get(rowOffset)) {
break;
}
rowOffset++;
}
int counterPosition = 0;
int countersLen = 9;
int* counters = new int[countersLen];
for (int i=0; i<countersLen; i++) {
counters[i] = 0;
}
int patternStart = rowOffset;
bool isWhite = false;
int patternLength = countersLen;
for (int i = rowOffset; i < width; i++) {
bool pixel = row->get(i);
if (pixel ^ isWhite) {
counters[counterPosition]++;
} else {
if (counterPosition == patternLength - 1) {
if (toNarrowWidePattern(counters, countersLen) == ASTERISK_ENCODING) {
// Look for whitespace before start pattern, >= 50% of width of start pattern
if (row->isRange(fmaxl(0, patternStart - (i - patternStart) / 2), patternStart, false)) {
int* resultValue = new int[2];
resultValue[0] = patternStart;
resultValue[1] = i;
return resultValue;
}
}
patternStart += counters[0] + counters[1];
for (int y = 2; y < patternLength; y++) {
counters[y - 2] = counters[y];
}
counters[patternLength - 2] = 0;
counters[patternLength - 1] = 0;
counterPosition--;
} else {
counterPosition++;
}
counters[counterPosition] = 1;
isWhite = !isWhite;
}
}
// IS begin
delete [] counters;
// IS end
throw ReaderException("");
}
// For efficiency, returns -1 on failure. Not throwing here saved as many as 700 exceptions
// per image when using some of our blackbox images.
int Code39Reader::toNarrowWidePattern(int counters[], int countersLen){
int numCounters = countersLen;
int maxNarrowCounter = 0;
int wideCounters;
do {
int minCounter = INT_MAX;
for (int i = 0; i < numCounters; i++) {
int counter = counters[i];
if (counter < minCounter && counter > maxNarrowCounter) {
minCounter = counter;
}
}
maxNarrowCounter = minCounter;
wideCounters = 0;
int totalWideCountersWidth = 0;
int pattern = 0;
for (int i = 0; i < numCounters; i++) {
int counter = counters[i];
if (counters[i] > maxNarrowCounter) {
pattern |= 1 << (numCounters - 1 - i);
wideCounters++;
totalWideCountersWidth += counter;
}
}
if (wideCounters == 3) {
// Found 3 wide counters, but are they close enough in width?
// We can perform a cheap, conservative check to see if any individual
// counter is more than 1.5 times the average:
for (int i = 0; i < numCounters && wideCounters > 0; i++) {
int counter = counters[i];
if (counters[i] > maxNarrowCounter) {
wideCounters--;
// totalWideCountersWidth = 3 * average, so this checks if counter >= 3/2 * average
if ((counter << 1) >= totalWideCountersWidth) {
return -1;
}
}
}
return pattern;
}
} while (wideCounters > 3);
return -1;
}
char Code39Reader::patternToChar(int pattern){
for (int i = 0; i < CHARACTER_ENCODINGS_LEN; i++) {
if (CHARACTER_ENCODINGS[i] == pattern) {
return ALPHABET[i];
}
}
throw ReaderException("");
}
Ref<String> Code39Reader::decodeExtended(std::string encoded){
int length = encoded.length();
std::string tmpDecoded;
for (int i = 0; i < length; i++) {
char c = encoded[i];
if (c == '+' || c == '$' || c == '%' || c == '/') {
char next = encoded[i + 1];
char decodedChar = '\0';
switch (c) {
case '+':
// +A to +Z map to a to z
if (next >= 'A' && next <= 'Z') {
decodedChar = (char) (next + 32);
} else {
throw ReaderException("");
}
break;
case '$':
// $A to $Z map to control codes SH to SB
if (next >= 'A' && next <= 'Z') {
decodedChar = (char) (next - 64);
} else {
throw ReaderException("");
}
break;
case '%':
// %A to %E map to control codes ESC to US
if (next >= 'A' && next <= 'E') {
decodedChar = (char) (next - 38);
} else if (next >= 'F' && next <= 'W') {
decodedChar = (char) (next - 11);
} else {
throw ReaderException("");
}
break;
case '/':
// /A to /O map to ! to , and /Z maps to :
if (next >= 'A' && next <= 'O') {
decodedChar = (char) (next - 32);
} else if (next == 'Z') {
decodedChar = ':';
} else {
throw ReaderException("");
}
break;
}
tmpDecoded.append(1, decodedChar);
// bump up i again since we read two characters
i++;
} else {
tmpDecoded.append(1, c);
}
}
Ref<String> decoded(new String(tmpDecoded));
return decoded;
}
}
}

View file

@ -36,17 +36,18 @@
IBOutlet UIBarItem *libraryBarItem; IBOutlet UIBarItem *libraryBarItem;
IBOutlet UIBarItem *archiveBarItem; IBOutlet UIBarItem *archiveBarItem;
IBOutlet UIBarItem *actionBarItem; IBOutlet UIBarItem *actionBarItem;
IBOutlet UIView *messageView; IBOutlet UIView *messageView;
IBOutlet UITextView *messageTextView; IBOutlet UITextView *messageTextView;
IBOutlet UIButton *messageHelpButton; IBOutlet UIButton *messageHelpButton;
IBOutlet ScannedImageView *imageView; IBOutlet ScannedImageView *imageView;
IBOutlet UIToolbar *toolbar; IBOutlet UIToolbar *toolbar;
UIImagePickerController *picker;
Decoder *decoder; Decoder *decoder;
ParsedResult *result; ParsedResult *result;
NSArray *actions; NSArray *actions;
NSMutableArray *resultPointViews; NSMutableArray *resultPointViews;
} }
@ -60,6 +61,7 @@
@property (nonatomic, retain) UITextView *messageTextView; @property (nonatomic, retain) UITextView *messageTextView;
@property (nonatomic, retain) UIButton *messageHelpButton; @property (nonatomic, retain) UIButton *messageHelpButton;
@property (nonatomic, retain) ScannedImageView *imageView; @property (nonatomic, retain) ScannedImageView *imageView;
@property (nonatomic, retain) UIImagePickerController *picker;
@property (nonatomic, retain) UIToolbar *toolbar; @property (nonatomic, retain) UIToolbar *toolbar;
@property (nonatomic, retain) Decoder *decoder; @property (nonatomic, retain) Decoder *decoder;
@ -86,8 +88,7 @@
/* UIImagePickerControllerDelegate methods */ /* UIImagePickerControllerDelegate methods */
- (void)imagePickerController:(UIImagePickerController *)picker - (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingImage:(UIImage *)image didFinishPickingMediaWithInfo:(NSDictionary *)info;
editingInfo:(NSDictionary *)editingInfo;
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker; - (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker;
/* UINavigationControllerDelegate methods */ /* UINavigationControllerDelegate methods */

View file

@ -32,6 +32,24 @@
#import "Scan.h" #import "Scan.h"
#import "TwoDDecoderResult.h" #import "TwoDDecoderResult.h"
// Michael Jurewitz, Dec 16, 2009 6:32 PM writes:
// https://devforums.apple.com/message/149553
// Notice Regarding UIGetScreenImage()
// After carefully considering the issue, Apple is now allowing applications to
// use the function UIGetScreenImage() to programmatically capture the current
// screen contents.
// Note that a future release of iPhone OS may provide a public API equivalent
// of this functionality. At such time, all applications using
// UIGetScreenImage() will be required to adopt the public API.
CGImageRef MyCGImageCopyScreenContents(void) {
extern CGImageRef UIGetScreenImage(void);
return UIGetScreenImage(); /* already retained */
}
@interface DecoderViewController()
- (void)takeScreenshot;
@end
@implementation DecoderViewController @implementation DecoderViewController
@synthesize cameraBarItem; @synthesize cameraBarItem;
@ -44,6 +62,7 @@
@synthesize messageTextView; @synthesize messageTextView;
@synthesize messageHelpButton; @synthesize messageHelpButton;
@synthesize imageView; @synthesize imageView;
@synthesize picker;
@synthesize toolbar; @synthesize toolbar;
@synthesize decoder; @synthesize decoder;
@ -53,17 +72,18 @@
@synthesize resultPointViews; @synthesize resultPointViews;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) { if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
// Initialization code // Initialization code
self.title = NSLocalizedString(@"DecoderViewController AppTitle", @"Barcode Scanner"); self.title =
NSLocalizedString(@"DecoderViewController AppTitle", @"Barcode Scanner");
Decoder *d = [[Decoder alloc] init]; Decoder *d = [[Decoder alloc] init];
self.decoder = d; self.decoder = d;
d.delegate = self; d.delegate = self;
[d release]; [d release];
resultPointViews = [[NSMutableArray alloc] init]; resultPointViews = [[NSMutableArray alloc] init];
} }
return self; return self;
} }
- (void) messageReady:(id)sender { - (void) messageReady:(id)sender {
@ -80,29 +100,31 @@
- (void) showHints:(id)sender { - (void) showHints:(id)sender {
NSLog(@"Showing Hints!"); NSLog(@"Showing Hints!");
MessageViewController *hintsController = MessageViewController *hintsController =
[[MessageViewController alloc] initWithMessageFilename:@"Hints" [[MessageViewController alloc] initWithMessageFilename:@"Hints"
target:self target:self
onSuccess:@selector(messageReady:) onSuccess:@selector(messageReady:)
onFailure:@selector(messageFailed:)]; onFailure:@selector(messageFailed:)];
hintsController.title = NSLocalizedString(@"DecoderViewController Hints MessageViewController title", @"Hints"); hintsController.title =
NSLocalizedString(@"DecoderViewController Hints MessageViewController title", @"Hints");
[hintsController view]; [hintsController view];
} }
- (void) showAbout:(id)sender { - (void) showAbout:(id)sender {
NSLog(@"Showing About!"); NSLog(@"Showing About!");
MessageViewController *aboutController = MessageViewController *aboutController =
[[MessageViewController alloc] initWithMessageFilename:@"About" [[MessageViewController alloc] initWithMessageFilename:@"About"
target:self target:self
onSuccess:@selector(messageReady:) onSuccess:@selector(messageReady:)
onFailure:@selector(messageFailed:)]; onFailure:@selector(messageFailed:)];
aboutController.title = NSLocalizedString(@"DecoderViewController About MessageViewController title", @"About"); aboutController.title =
NSLocalizedString(@"DecoderViewController About MessageViewController title", @"About");
[aboutController view]; [aboutController view];
} }
#define HELP_BUTTON_WIDTH (44.0) #define HELP_BUTTON_WIDTH (44.0)
#define HELP_BUTTON_HEIGHT (55.0) #define HELP_BUTTON_HEIGHT (55.0)
@ -114,23 +136,24 @@
self.result = nil; self.result = nil;
[self clearImageView]; [self clearImageView];
[self updateToolbar]; [self updateToolbar];
[self showMessage:NSLocalizedString(@"DecoderViewController take or choose picture", @"Please take or choose a picture containing a barcode") helpButton:YES]; [self showMessage:NSLocalizedString(@"DecoderViewController take or choose picture",
@"Please take or choose a picture containing a barcode") helpButton:YES];
} }
// Implement loadView if you want to create a view hierarchy programmatically // Implement loadView if you want to create a view hierarchy programmatically
- (void)loadView { - (void)loadView {
[super loadView]; [super loadView];
CGRect messageViewFrame = imageView.frame; CGRect messageViewFrame = imageView.frame;
UIView *mView = [[UIView alloc] initWithFrame:messageViewFrame]; UIView *mView = [[UIView alloc] initWithFrame:messageViewFrame];
mView.backgroundColor = [UIColor darkGrayColor]; mView.backgroundColor = [UIColor darkGrayColor];
mView.alpha = 0.9; mView.alpha = 0.9;
mView.autoresizingMask = UIViewAutoresizingFlexibleHeight | mView.autoresizingMask = UIViewAutoresizingFlexibleHeight |
UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleWidth |
UIViewAutoresizingFlexibleTopMargin; UIViewAutoresizingFlexibleTopMargin;
UITextView *mTextView = [[UITextView alloc] initWithFrame:messageViewFrame]; UITextView *mTextView = [[UITextView alloc] initWithFrame:messageViewFrame];
mTextView.autoresizingMask = UIViewAutoresizingFlexibleHeight | mTextView.autoresizingMask = UIViewAutoresizingFlexibleHeight |
UIViewAutoresizingFlexibleWidth; UIViewAutoresizingFlexibleWidth;
mTextView.editable = false; mTextView.editable = false;
mTextView.scrollEnabled = true; mTextView.scrollEnabled = true;
@ -143,31 +166,31 @@
UIButton *mHelpButton = [[UIButton buttonWithType:UIButtonTypeInfoLight] retain]; UIButton *mHelpButton = [[UIButton buttonWithType:UIButtonTypeInfoLight] retain];
mHelpButton.frame = CGRectMake(messageViewFrame.size.width - HELP_BUTTON_WIDTH, 0.0, HELP_BUTTON_WIDTH, HELP_BUTTON_HEIGHT); mHelpButton.frame = CGRectMake(messageViewFrame.size.width - HELP_BUTTON_WIDTH, 0.0, HELP_BUTTON_WIDTH, HELP_BUTTON_HEIGHT);
mHelpButton.backgroundColor = [UIColor clearColor]; mHelpButton.backgroundColor = [UIColor clearColor];
[mHelpButton setUserInteractionEnabled:YES]; [mHelpButton setUserInteractionEnabled:YES];
[mHelpButton addTarget:self action:@selector(showHints:) forControlEvents:UIControlEventTouchUpInside]; [mHelpButton addTarget:self action:@selector(showHints:) forControlEvents:UIControlEventTouchUpInside];
self.messageHelpButton = mHelpButton; self.messageHelpButton = mHelpButton;
[mHelpButton release]; [mHelpButton release];
self.messageTextView = mTextView; self.messageTextView = mTextView;
[mTextView release]; [mTextView release];
self.messageView = mView; self.messageView = mView;
[mView release]; [mView release];
[self.view addSubview:self.messageView]; [self.view addSubview:self.messageView];
// add the 'About' button at the top-right of the navigation bar // add the 'About' button at the top-right of the navigation bar
UIBarButtonItem *aboutButton = UIBarButtonItem *aboutButton =
[[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"DecoderViewController about button title", @"About") [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"DecoderViewController about button title", @"About")
style:UIBarButtonItemStyleBordered style:UIBarButtonItemStyleBordered
target:self target:self
action:@selector(showAbout:)]; action:@selector(showAbout:)];
self.navigationItem.rightBarButtonItem = aboutButton; self.navigationItem.rightBarButtonItem = aboutButton;
[aboutButton release]; [aboutButton release];
[self reset]; [self reset];
} }
@ -199,11 +222,42 @@
// Create the Image Picker // Create the Image Picker
if ([UIImagePickerController isSourceTypeAvailable:sourceType]) { if ([UIImagePickerController isSourceTypeAvailable:sourceType]) {
UIImagePickerController* picker = [[UIImagePickerController alloc] init]; UIImagePickerController* aPicker =
picker.sourceType = sourceType; [[[UIImagePickerController alloc] init] autorelease];
picker.delegate = self; aPicker.sourceType = sourceType;
picker.allowsImageEditing = YES; // [[NSUserDefaults standardUserDefaults] boolForKey:@"allowEditing"]; aPicker.delegate = self;
self.picker = aPicker;
// [[NSUserDefaults standardUserDefaults] boolForKey:@"allowEditing"];
BOOL isCamera = (sourceType == UIImagePickerControllerSourceTypeCamera);
picker.allowsEditing = !isCamera;
if (isCamera) {
picker.showsCameraControls = NO;
UIButton *cancelButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
NSString *cancelString =
NSLocalizedString(@"DecoderViewController cancel button title", @"");
CGFloat height = [UIFont systemFontSize];
CGSize size = [cancelString sizeWithFont:[UIFont systemFontOfSize:height]];
[cancelButton setTitle:cancelString forState:UIControlStateNormal];
CGRect appFrame = [[UIScreen mainScreen] bounds];
static const int kMargin = 10;
static const int kInternalXMargin = 10;
static const int kInternalYMargin = 10;
CGRect frame = CGRectMake(kMargin,
appFrame.size.height - (height + 2*kInternalYMargin + kMargin),
2*kInternalXMargin + size.width,
height + 2*kInternalYMargin);
[cancelButton setFrame:frame];
[cancelButton addTarget:self
action:@selector(cancel:)
forControlEvents:UIControlEventTouchUpInside];
picker.cameraOverlayView = cancelButton;
// The camera takes quite a while to start up. Hence the 2 second delay.
[self performSelector:@selector(takeScreenshot)
withObject:nil
afterDelay:2.0];
}
// Picker is displayed asynchronously. // Picker is displayed asynchronously.
[self presentModalViewController:picker animated:YES]; [self presentModalViewController:picker animated:YES];
} else { } else {
@ -214,7 +268,7 @@
- (IBAction)pickAndDecode:(id) sender { - (IBAction)pickAndDecode:(id) sender {
UIImagePickerControllerSourceType sourceType; UIImagePickerControllerSourceType sourceType;
int i = [sender tag]; int i = [sender tag];
switch (i) { switch (i) {
case 0: sourceType = UIImagePickerControllerSourceTypeCamera; break; case 0: sourceType = UIImagePickerControllerSourceTypeCamera; break;
case 1: sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum; break; case 1: sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum; break;
@ -246,17 +300,18 @@
[savedPhotosBarItem release]; [savedPhotosBarItem release];
[archiveBarItem release]; [archiveBarItem release];
[toolbar release]; [toolbar release];
[actions dealloc]; [picker release];
[resultPointViews dealloc]; [actions release];
[resultPointViews release];
[super dealloc];
[super dealloc];
} }
- (void)showMessage:(NSString *)message helpButton:(BOOL)showHelpButton { - (void)showMessage:(NSString *)message helpButton:(BOOL)showHelpButton {
#ifdef DEBUG #ifdef DEBUG
NSLog(@"Showing message '%@' %@ help Button", message, showHelpButton ? @"with" : @"without"); NSLog(@"Showing message '%@' %@ help Button", message, showHelpButton ? @"with" : @"without");
#endif #endif
CGSize imageMaxSize = imageView.bounds.size; CGSize imageMaxSize = imageView.bounds.size;
if (showHelpButton) { if (showHelpButton) {
imageMaxSize.width -= messageHelpButton.frame.size.width; imageMaxSize.width -= messageHelpButton.frame.size.width;
@ -279,15 +334,15 @@
if (showHelpButton) { if (showHelpButton) {
CGRect textViewFrame; CGRect textViewFrame;
CGRect helpButtonFrame; CGRect helpButtonFrame;
CGRectDivide(messageViewBounds, &helpButtonFrame, &textViewFrame, HELP_BUTTON_WIDTH, CGRectMaxXEdge); CGRectDivide(messageViewBounds, &helpButtonFrame, &textViewFrame, HELP_BUTTON_WIDTH, CGRectMaxXEdge);
[self.messageTextView setFrame:textViewFrame]; [self.messageTextView setFrame:textViewFrame];
[messageHelpButton setFrame:helpButtonFrame]; [messageHelpButton setFrame:helpButtonFrame];
messageHelpButton.alpha = 1.0; messageHelpButton.alpha = 1.0;
messageHelpButton.enabled = YES; messageHelpButton.enabled = YES;
messageHelpButton.autoresizingMask = messageHelpButton.autoresizingMask =
UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleLeftMargin |
UIViewAutoresizingFlexibleTopMargin; UIViewAutoresizingFlexibleTopMargin;
[messageView addSubview:messageHelpButton]; [messageView addSubview:messageHelpButton];
} else { } else {
@ -308,8 +363,8 @@
helpButton:NO]; helpButton:NO];
} }
- (void)decoder:(Decoder *)decoder - (void)decoder:(Decoder *)decoder
decodingImage:(UIImage *)image decodingImage:(UIImage *)image
usingSubset:(UIImage *)subset usingSubset:(UIImage *)subset
progress:(NSString *)message { progress:(NSString *)message {
[self clearImageView]; [self clearImageView];
@ -325,9 +380,9 @@
NSLog(@"result has %d actions", actions ? 0 : actions.count); NSLog(@"result has %d actions", actions ? 0 : actions.count);
#endif #endif
[self updateToolbar]; [self updateToolbar];
} }
- (void)presentResultPoints:(NSArray *)resultPoints - (void)presentResultPoints:(NSArray *)resultPoints
forImage:(UIImage *)image forImage:(UIImage *)image
usingSubset:(UIImage *)subset { usingSubset:(UIImage *)subset {
// simply add the points to the image view // simply add the points to the image view
@ -338,25 +393,32 @@
} }
- (void)decoder:(Decoder *)decoder didDecodeImage:(UIImage *)image usingSubset:(UIImage *)subset withResult:(TwoDDecoderResult *)twoDResult { - (void)decoder:(Decoder *)decoder didDecodeImage:(UIImage *)image usingSubset:(UIImage *)subset withResult:(TwoDDecoderResult *)twoDResult {
self.picker = nil;
[self presentResultForString:twoDResult.text]; [self presentResultForString:twoDResult.text];
[self presentResultPoints:twoDResult.points forImage:image usingSubset:subset]; [self presentResultPoints:twoDResult.points forImage:image usingSubset:subset];
// save the scan to the shared database // save the scan to the shared database
[[Database sharedDatabase] addScanWithText:twoDResult.text]; [[Database sharedDatabase] addScanWithText:twoDResult.text];
[self performResultAction:self]; [self performResultAction:self];
} }
- (void)decoder:(Decoder *)decoder failedToDecodeImage:(UIImage *)image usingSubset:(UIImage *)subset reason:(NSString *)reason { - (void)decoder:(Decoder *)decoder failedToDecodeImage:(UIImage *)image usingSubset:(UIImage *)subset reason:(NSString *)reason {
[self showMessage:reason helpButton:YES]; if (self.picker && UIImagePickerControllerSourceTypeCamera == self.picker.sourceType) {
[self updateToolbar]; // If we are using the camera, and the user hasn't manually cancelled,
// take another snapshot and try to decode it.
[self takeScreenshot];
} else {
[self showMessage:reason helpButton:YES];
[self updateToolbar];
}
} }
- (void)willAnimateFirstHalfOfRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { - (void)willAnimateFirstHalfOfRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
[super willAnimateFirstHalfOfRotationToInterfaceOrientation:toInterfaceOrientation duration:duration]; [super willAnimateFirstHalfOfRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
if (imageView.image) { if (imageView.image) {
/* /*
CGRect viewBounds = imageView.bounds; CGRect viewBounds = imageView.bounds;
@ -366,11 +428,11 @@
float xOffset = (viewBounds.size.width - scale * imageSize.width) / 2.0; float xOffset = (viewBounds.size.width - scale * imageSize.width) / 2.0;
float yOffset = (viewBounds.size.height - scale * imageSize.height) / 2.0; float yOffset = (viewBounds.size.height - scale * imageSize.height) / 2.0;
*/ */
for (UIView *view in resultPointViews) { for (UIView *view in resultPointViews) {
view.alpha = 0.0; view.alpha = 0.0;
} }
} }
} }
- (void)willAnimateSecondHalfOfRotationFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation duration:(NSTimeInterval)duration { - (void)willAnimateSecondHalfOfRotationFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation duration:(NSTimeInterval)duration {
@ -385,80 +447,105 @@
float xOffset = (viewBounds.size.width - scale * imageSize.width) / 2.0; float xOffset = (viewBounds.size.width - scale * imageSize.width) / 2.0;
float yOffset = (viewBounds.size.height - scale * imageSize.height) / 2.0; float yOffset = (viewBounds.size.height - scale * imageSize.height) / 2.0;
*/ */
for (UIView *view in resultPointViews) { for (UIView *view in resultPointViews) {
view.alpha = 1.0; view.alpha = 1.0;
} }
} }
}
- (void)cancel:(id)sender {
self.picker = nil;
}
- (void)takeScreenshot {
if (picker) {
CGImageRef cgScreen = MyCGImageCopyScreenContents();
if (cgScreen) {
CGRect croppedFrame = CGRectMake(0, 0, CGImageGetWidth(cgScreen),
CGImageGetHeight(cgScreen) - (10+toolbar.bounds.size.height));
CGImageRef cgCropped = CGImageCreateWithImageInRect(cgScreen, croppedFrame);
if (cgCropped) {
UIImage *screenshot = [UIImage imageWithCGImage:cgCropped];
CGImageRelease(cgCropped);
[self.decoder decodeImage:screenshot];
}
CGImageRelease(cgScreen);
}
}
} }
// UIImagePickerControllerDelegate methods // UIImagePickerControllerDelegate methods
- (void)imagePickerController:(UIImagePickerController *)picker - (void)imagePickerController:(UIImagePickerController *)aPicker
didFinishPickingImage:(UIImage *)image didFinishPickingMediaWithInfo:(NSDictionary *)info {
editingInfo:(NSDictionary *)editingInfo UIImage *imageToDecode =
{ [info objectForKey:UIImagePickerControllerEditedImage];
UIImage *imageToDecode = image; if (!imageToDecode) {
CGSize size = [image size]; imageToDecode = [info objectForKey:UIImagePickerControllerOriginalImage];
CGRect cropRect = CGRectMake(0.0, 0.0, size.width, size.height); }
CGSize size = [imageToDecode size];
CGRect cropRect = CGRectMake(0.0, 0.0, size.width, size.height);
#ifdef DEBUG #ifdef DEBUG
NSLog(@"picked image size = (%f, %f)", size.width, size.height); NSLog(@"picked image size = (%f, %f)", size.width, size.height);
#endif #endif
NSString *systemVersion = [[UIDevice currentDevice] systemVersion]; NSString *systemVersion = [[UIDevice currentDevice] systemVersion];
if (editingInfo) { NSValue *cropRectValue = [info objectForKey:UIImagePickerControllerCropRect];
UIImage *originalImage = [editingInfo objectForKey:UIImagePickerControllerOriginalImage]; if (cropRectValue) {
UIImage *originalImage = [info objectForKey:UIImagePickerControllerOriginalImage];
if (originalImage) { if (originalImage) {
#ifdef DEBUG #ifdef DEBUG
NSLog(@"original image size = (%f, %f)", originalImage.size.width, originalImage.size.height); NSLog(@"original image size = (%f, %f)", originalImage.size.width, originalImage.size.height);
#endif #endif
NSValue *cropRectValue = [editingInfo objectForKey:UIImagePickerControllerCropRect]; cropRect = [cropRectValue CGRectValue];
if (cropRectValue) {
cropRect = [cropRectValue CGRectValue];
#ifdef DEBUG #ifdef DEBUG
NSLog(@"crop rect = (%f, %f) x (%f, %f)", CGRectGetMinX(cropRect), CGRectGetMinY(cropRect), CGRectGetWidth(cropRect), CGRectGetHeight(cropRect)); NSLog(@"crop rect = (%f, %f) x (%f, %f)", CGRectGetMinX(cropRect), CGRectGetMinY(cropRect), CGRectGetWidth(cropRect), CGRectGetHeight(cropRect));
#endif #endif
if (([picker sourceType] == UIImagePickerControllerSourceTypeSavedPhotosAlbum) && if (([picker sourceType] == UIImagePickerControllerSourceTypeSavedPhotosAlbum) &&
[@"2.1" isEqualToString:systemVersion]) { [@"2.1" isEqualToString:systemVersion]) {
// adjust crop rect to work around bug in iPhone OS 2.1 when selecting from the photo roll // adjust crop rect to work around bug in iPhone OS 2.1 when selecting from the photo roll
cropRect.origin.x *= 2.5; cropRect.origin.x *= 2.5;
cropRect.origin.y *= 2.5; cropRect.origin.y *= 2.5;
cropRect.size.width *= 2.5; cropRect.size.width *= 2.5;
cropRect.size.height *= 2.5; cropRect.size.height *= 2.5;
#ifdef DEBUG #ifdef DEBUG
NSLog(@"2.1-adjusted crop rect = (%f, %f) x (%f, %f)", CGRectGetMinX(cropRect), CGRectGetMinY(cropRect), CGRectGetWidth(cropRect), CGRectGetHeight(cropRect)); NSLog(@"2.1-adjusted crop rect = (%f, %f) x (%f, %f)", CGRectGetMinX(cropRect), CGRectGetMinY(cropRect), CGRectGetWidth(cropRect), CGRectGetHeight(cropRect));
#endif #endif
}
imageToDecode = originalImage;
} }
imageToDecode = originalImage;
} }
} }
[[picker parentViewController] dismissModalViewControllerAnimated:YES];
[imageToDecode retain]; [imageToDecode retain];
[picker release]; self.picker = nil;
[self.decoder decodeImage:imageToDecode cropRect:cropRect]; [self.decoder decodeImage:imageToDecode cropRect:cropRect];
[imageToDecode release]; [imageToDecode release];
[self updateToolbar];
} }
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{ - (void)imagePickerControllerDidCancel:(UIImagePickerController *)aPicker {
[picker dismissModalViewControllerAnimated:YES]; self.picker = nil;
[picker release];
[self updateToolbar];
} }
- (void)navigationController:(UINavigationController *)navigationController - (void)setPicker:(UIImagePickerController *)aPicker {
didShowViewController:(UIViewController *)viewController if (picker != aPicker) {
[picker dismissModalViewControllerAnimated:YES];
picker = [aPicker retain];
[self updateToolbar];
}
}
- (void)navigationController:(UINavigationController *)navigationController
didShowViewController:(UIViewController *)viewController
animated:(BOOL)animated { animated:(BOOL)animated {
// no-op // no-op
} }
- (void)navigationController:(UINavigationController *)navigationController - (void)navigationController:(UINavigationController *)navigationController
willShowViewController:(UIViewController *)viewController willShowViewController:(UIViewController *)viewController
animated:(BOOL)animated { animated:(BOOL)animated {
// no-op // no-op
} }
@ -477,36 +564,36 @@
NSLog(@"no result to perform an action on!"); NSLog(@"no result to perform an action on!");
return; return;
} }
if (self.actions == nil || self.actions.count == 0) { if (self.actions == nil || self.actions.count == 0) {
NSLog(@"result has no actions to perform!"); NSLog(@"result has no actions to perform!");
return; return;
} }
if (self.actions.count == 1) { if (self.actions.count == 1) {
ResultAction *action = [self.actions lastObject]; ResultAction *action = [self.actions lastObject];
#ifdef DEBUG #ifdef DEBUG
NSLog(@"Result has the single action, (%@) '%@', performing it", NSLog(@"Result has the single action, (%@) '%@', performing it",
NSStringFromClass([action class]), [action title]); NSStringFromClass([action class]), [action title]);
#endif #endif
[self performSelector:@selector(confirmAndPerformAction:) [self performSelector:@selector(confirmAndPerformAction:)
withObject:action withObject:action
afterDelay:0.0]; afterDelay:0.0];
} else { } else {
#ifdef DEBUG #ifdef DEBUG
NSLog(@"Result has multiple actions, popping up an action sheet"); NSLog(@"Result has multiple actions, popping up an action sheet");
#endif #endif
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithFrame:self.view.bounds]; UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithFrame:self.view.bounds];
for (ResultAction *action in self.actions) { for (ResultAction *action in self.actions) {
[actionSheet addButtonWithTitle:[action title]]; [actionSheet addButtonWithTitle:[action title]];
} }
int cancelIndex = [actionSheet addButtonWithTitle:NSLocalizedString(@"DecoderViewController cancel button title", @"Cancel")]; int cancelIndex = [actionSheet addButtonWithTitle:NSLocalizedString(@"DecoderViewController cancel button title", @"Cancel")];
actionSheet.cancelButtonIndex = cancelIndex; actionSheet.cancelButtonIndex = cancelIndex;
actionSheet.delegate = self; actionSheet.delegate = self;
[actionSheet showFromToolbar:self.toolbar]; [actionSheet showFromToolbar:self.toolbar];
} }
} }
@ -515,8 +602,8 @@
if (buttonIndex < self.actions.count) { if (buttonIndex < self.actions.count) {
int actionIndex = buttonIndex; int actionIndex = buttonIndex;
ResultAction *action = [self.actions objectAtIndex:actionIndex]; ResultAction *action = [self.actions objectAtIndex:actionIndex];
[self performSelector:@selector(performAction:) [self performSelector:@selector(performAction:)
withObject:action withObject:action
afterDelay:0.0]; afterDelay:0.0];
} }
} }

View file

@ -65,8 +65,8 @@ static NSString *_timeString(NSDate *date) {
@synthesize timeView; @synthesize timeView;
- (id)initWithFrame:(CGRect)frame reuseIdentifier:(NSString *)reuseIdentifier { - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
if ((self = [super initWithFrame:frame reuseIdentifier:reuseIdentifier])) { if ((self = [super initWithStyle:style reuseIdentifier:reuseIdentifier])) {
imageView = [[UIImageView alloc] initWithFrame:CGRectZero]; imageView = [[UIImageView alloc] initWithFrame:CGRectZero];
imageView.contentMode = UIViewContentModeCenter; imageView.contentMode = UIViewContentModeCenter;
[self.contentView addSubview:imageView]; [self.contentView addSubview:imageView];
@ -88,8 +88,8 @@ static NSString *_timeString(NSDate *date) {
timeView.textAlignment = UITextAlignmentRight; timeView.textAlignment = UITextAlignmentRight;
timeView.textColor = [UIColor grayColor]; timeView.textColor = [UIColor grayColor];
[self.contentView addSubview:timeView]; [self.contentView addSubview:timeView];
} }
return self; return self;
} }
- (CGRect) _imageViewFrame { - (CGRect) _imageViewFrame {
@ -168,7 +168,7 @@ static NSString *_timeString(NSDate *date) {
[timeView release]; [timeView release];
[scan release]; [scan release];
[result release]; [result release];
[super dealloc]; [super dealloc];
} }

View file

@ -10,8 +10,8 @@
<p style="font-weight: bold;"> <p style="font-weight: bold;">
<img style="width: 128px; height: 128px;" alt="ZXing Project Logo" src="../ZxingLarge.png"></p> <img style="width: 128px; height: 128px;" alt="ZXing Project Logo" src="../ZxingLarge.png"></p>
<h2>Strichcodes</h2> <h2>Strichcodes</h2>
<p>Version 1.0</p> <p>Version 1.1</p>
<p>&copy; 2008 The <a href="http://code.google.com/p/zxing/">ZXing</a> <p>&copy; 2008-2010 The <a href="http://code.google.com/p/zxing/">ZXing</a>
Authors<br> Authors<br>
</p> </p>
<p> <p>

View file

@ -1,11 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="7.02"> <archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="7.10">
<data> <data>
<int key="IBDocument.SystemTarget">512</int> <int key="IBDocument.SystemTarget">768</int>
<string key="IBDocument.SystemVersion">9E17</string> <string key="IBDocument.SystemVersion">10D573</string>
<string key="IBDocument.InterfaceBuilderVersion">670</string> <string key="IBDocument.InterfaceBuilderVersion">762</string>
<string key="IBDocument.AppKitVersion">949.33</string> <string key="IBDocument.AppKitVersion">1038.29</string>
<string key="IBDocument.HIToolboxVersion">352.00</string> <string key="IBDocument.HIToolboxVersion">460.00</string>
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
<string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="NS.object.0">87</string>
</object>
<object class="NSMutableArray" key="IBDocument.EditedObjectIDs"> <object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
</object> </object>
@ -13,13 +17,24 @@
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string> <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
</object> </object>
<object class="NSMutableDictionary" key="IBDocument.Metadata">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSArray" key="dict.sortedKeys" id="0">
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
</object>
<object class="NSMutableArray" key="IBDocument.RootObjects" id="1000"> <object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
<object class="IBProxyObject" id="372490531"> <object class="IBProxyObject" id="372490531">
<string key="IBProxiedObjectIdentifier">IBFilesOwner</string> <string key="IBProxiedObjectIdentifier">IBFilesOwner</string>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
</object> </object>
<object class="IBProxyObject" id="711762367"> <object class="IBProxyObject" id="711762367">
<string key="IBProxiedObjectIdentifier">IBFirstResponder</string> <string key="IBProxiedObjectIdentifier">IBFirstResponder</string>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
</object> </object>
<object class="IBUIWebView" id="221386056"> <object class="IBUIWebView" id="221386056">
<nil key="NSNextResponder"/> <nil key="NSNextResponder"/>
@ -31,6 +46,7 @@
</object> </object>
<bool key="IBUIClipsSubviews">YES</bool> <bool key="IBUIClipsSubviews">YES</bool>
<bool key="IBUIMultipleTouchEnabled">YES</bool> <bool key="IBUIMultipleTouchEnabled">YES</bool>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
<bool key="IBUIScalesPageToFit">YES</bool> <bool key="IBUIScalesPageToFit">YES</bool>
</object> </object>
</object> </object>
@ -51,33 +67,31 @@
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
<object class="IBObjectRecord"> <object class="IBObjectRecord">
<int key="objectID">0</int> <int key="objectID">0</int>
<object class="NSArray" key="object" id="360949347"> <reference key="object" ref="0"/>
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
<reference key="children" ref="1000"/> <reference key="children" ref="1000"/>
<nil key="parent"/> <nil key="parent"/>
</object> </object>
<object class="IBObjectRecord"> <object class="IBObjectRecord">
<int key="objectID">-1</int> <int key="objectID">-1</int>
<reference key="object" ref="372490531"/> <reference key="object" ref="372490531"/>
<reference key="parent" ref="360949347"/> <reference key="parent" ref="0"/>
<string type="base64-UTF8" key="objectName">RmlsZSdzIE93bmVyA</string> <string key="objectName">File's Owner</string>
</object> </object>
<object class="IBObjectRecord"> <object class="IBObjectRecord">
<int key="objectID">-2</int> <int key="objectID">-2</int>
<reference key="object" ref="711762367"/> <reference key="object" ref="711762367"/>
<reference key="parent" ref="360949347"/> <reference key="parent" ref="0"/>
</object> </object>
<object class="IBObjectRecord"> <object class="IBObjectRecord">
<int key="objectID">4</int> <int key="objectID">4</int>
<reference key="object" ref="221386056"/> <reference key="object" ref="221386056"/>
<reference key="parent" ref="360949347"/> <reference key="parent" ref="0"/>
</object> </object>
</object> </object>
</object> </object>
<object class="NSMutableDictionary" key="flattenedProperties"> <object class="NSMutableDictionary" key="flattenedProperties">
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSMutableArray" key="dict.sortedKeys"> <object class="NSArray" key="dict.sortedKeys">
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
<string>-1.CustomClassName</string> <string>-1.CustomClassName</string>
<string>-2.CustomClassName</string> <string>-2.CustomClassName</string>
@ -85,16 +99,14 @@
</object> </object>
<object class="NSMutableArray" key="dict.values"> <object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
<string>HintsViewController</string> <string>MessageViewController</string>
<string>UIResponder</string> <string>UIResponder</string>
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string> <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
</object> </object>
</object> </object>
<object class="NSMutableDictionary" key="unlocalizedProperties"> <object class="NSMutableDictionary" key="unlocalizedProperties">
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSArray" key="dict.sortedKeys"> <reference key="dict.sortedKeys" ref="0"/>
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
<object class="NSMutableArray" key="dict.values"> <object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
</object> </object>
@ -102,9 +114,7 @@
<nil key="activeLocalization"/> <nil key="activeLocalization"/>
<object class="NSMutableDictionary" key="localizations"> <object class="NSMutableDictionary" key="localizations">
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSArray" key="dict.sortedKeys"> <reference key="dict.sortedKeys" ref="0"/>
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
<object class="NSMutableArray" key="dict.values"> <object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
</object> </object>
@ -116,17 +126,224 @@
<object class="NSMutableArray" key="referencedPartialClassDescriptions"> <object class="NSMutableArray" key="referencedPartialClassDescriptions">
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
<object class="IBPartialClassDescription"> <object class="IBPartialClassDescription">
<string key="className">HintsViewController</string> <string key="className">MessageViewController</string>
<string key="superclassName">UIViewController</string> <string key="superclassName">UIViewController</string>
<object class="NSMutableDictionary" key="outlets">
<string key="NS.key.0">callbackTarget</string>
<string key="NS.object.0">id</string>
</object>
<object class="IBClassDescriptionSource" key="sourceIdentifier"> <object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string> <string key="majorKey">IBProjectSource</string>
<string key="minorKey">Classes/HintsViewController.h</string> <string key="minorKey">Classes/MessageViewController.h</string>
</object>
</object>
</object>
<object class="NSMutableArray" key="referencedPartialClassDescriptionsV3.2+">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSError.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSFileManager.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSKeyValueCoding.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSKeyValueObserving.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSKeyedArchiver.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSNetServices.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSObject.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSPort.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSRunLoop.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSStream.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSThread.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSURL.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSURLConnection.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSXMLParser.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">UIKit.framework/Headers/UIAccessibility.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">UIKit.framework/Headers/UINibLoading.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier" id="28199712">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">UIKit.framework/Headers/UIResponder.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">UIResponder</string>
<string key="superclassName">NSObject</string>
<reference key="sourceIdentifier" ref="28199712"/>
</object>
<object class="IBPartialClassDescription">
<string key="className">UISearchBar</string>
<string key="superclassName">UIView</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">UIKit.framework/Headers/UISearchBar.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">UISearchDisplayController</string>
<string key="superclassName">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">UIKit.framework/Headers/UISearchDisplayController.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">UIView</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">UIKit.framework/Headers/UITextField.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">UIView</string>
<string key="superclassName">UIResponder</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">UIKit.framework/Headers/UIView.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">UIViewController</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">UIKit.framework/Headers/UINavigationController.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">UIViewController</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">UIKit.framework/Headers/UITabBarController.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">UIViewController</string>
<string key="superclassName">UIResponder</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">UIKit.framework/Headers/UIViewController.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">UIWebView</string>
<string key="superclassName">UIView</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">UIKit.framework/Headers/UIWebView.h</string>
</object> </object>
</object> </object>
</object> </object>
</object> </object>
<int key="IBDocument.localizationMode">0</int> <int key="IBDocument.localizationMode">0</int>
<nil key="IBDocument.LastKnownRelativeProjectPath"/> <string key="IBDocument.TargetRuntimeIdentifier">IBCocoaTouchFramework</string>
<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencies">
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS</string>
<integer value="768" key="NS.object.0"/>
</object>
<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencyDefaults">
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS</string>
<integer value="784" key="NS.object.0"/>
</object>
<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3</string>
<integer value="3000" key="NS.object.0"/>
</object>
<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
<string key="IBDocument.LastKnownRelativeProjectPath">../ZXing.xcodeproj</string>
<int key="IBDocument.defaultPropertyAccessControl">3</int> <int key="IBDocument.defaultPropertyAccessControl">3</int>
<string key="IBCocoaTouchPluginVersion">87</string>
</data> </data>
</archive> </archive>

View file

@ -10,8 +10,8 @@
<p style="font-weight: bold;"> <p style="font-weight: bold;">
<img style="width: 128px; height: 128px;" alt="ZXing Project Logo" src="../ZxingLarge.png"></p> <img style="width: 128px; height: 128px;" alt="ZXing Project Logo" src="../ZxingLarge.png"></p>
<h2>Barcodes</h2> <h2>Barcodes</h2>
<p>Version 1.0</p> <p>Version 1.1</p>
<p>&copy; 2008 The <a href="http://code.google.com/p/zxing/">ZXing</a> <p>&copy; 2008-2010 The <a href="http://code.google.com/p/zxing/">ZXing</a>
Authors<br> Authors<br>
</p> </p>
<p> <p>

View file

@ -1,11 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="7.02"> <archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="7.10">
<data> <data>
<int key="IBDocument.SystemTarget">512</int> <int key="IBDocument.SystemTarget">768</int>
<string key="IBDocument.SystemVersion">9E17</string> <string key="IBDocument.SystemVersion">10D573</string>
<string key="IBDocument.InterfaceBuilderVersion">670</string> <string key="IBDocument.InterfaceBuilderVersion">762</string>
<string key="IBDocument.AppKitVersion">949.33</string> <string key="IBDocument.AppKitVersion">1038.29</string>
<string key="IBDocument.HIToolboxVersion">352.00</string> <string key="IBDocument.HIToolboxVersion">460.00</string>
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
<string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="NS.object.0">87</string>
</object>
<object class="NSMutableArray" key="IBDocument.EditedObjectIDs"> <object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
</object> </object>
@ -13,13 +17,24 @@
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string> <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
</object> </object>
<object class="NSMutableDictionary" key="IBDocument.Metadata">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSArray" key="dict.sortedKeys" id="0">
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
</object>
<object class="NSMutableArray" key="IBDocument.RootObjects" id="1000"> <object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
<object class="IBProxyObject" id="372490531"> <object class="IBProxyObject" id="372490531">
<string key="IBProxiedObjectIdentifier">IBFilesOwner</string> <string key="IBProxiedObjectIdentifier">IBFilesOwner</string>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
</object> </object>
<object class="IBProxyObject" id="711762367"> <object class="IBProxyObject" id="711762367">
<string key="IBProxiedObjectIdentifier">IBFirstResponder</string> <string key="IBProxiedObjectIdentifier">IBFirstResponder</string>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
</object> </object>
<object class="IBUIWebView" id="221386056"> <object class="IBUIWebView" id="221386056">
<nil key="NSNextResponder"/> <nil key="NSNextResponder"/>
@ -31,6 +46,7 @@
</object> </object>
<bool key="IBUIClipsSubviews">YES</bool> <bool key="IBUIClipsSubviews">YES</bool>
<bool key="IBUIMultipleTouchEnabled">YES</bool> <bool key="IBUIMultipleTouchEnabled">YES</bool>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
<bool key="IBUIScalesPageToFit">YES</bool> <bool key="IBUIScalesPageToFit">YES</bool>
</object> </object>
</object> </object>
@ -43,7 +59,7 @@
<reference key="source" ref="372490531"/> <reference key="source" ref="372490531"/>
<reference key="destination" ref="221386056"/> <reference key="destination" ref="221386056"/>
</object> </object>
<int key="connectionID">5</int> <int key="connectionID">6</int>
</object> </object>
</object> </object>
<object class="IBMutableOrderedSet" key="objectRecords"> <object class="IBMutableOrderedSet" key="objectRecords">
@ -51,33 +67,31 @@
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
<object class="IBObjectRecord"> <object class="IBObjectRecord">
<int key="objectID">0</int> <int key="objectID">0</int>
<object class="NSArray" key="object" id="360949347"> <reference key="object" ref="0"/>
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
<reference key="children" ref="1000"/> <reference key="children" ref="1000"/>
<nil key="parent"/> <nil key="parent"/>
</object> </object>
<object class="IBObjectRecord"> <object class="IBObjectRecord">
<int key="objectID">-1</int> <int key="objectID">-1</int>
<reference key="object" ref="372490531"/> <reference key="object" ref="372490531"/>
<reference key="parent" ref="360949347"/> <reference key="parent" ref="0"/>
<string type="base64-UTF8" key="objectName">RmlsZSdzIE93bmVyA</string> <string key="objectName">File's Owner</string>
</object> </object>
<object class="IBObjectRecord"> <object class="IBObjectRecord">
<int key="objectID">-2</int> <int key="objectID">-2</int>
<reference key="object" ref="711762367"/> <reference key="object" ref="711762367"/>
<reference key="parent" ref="360949347"/> <reference key="parent" ref="0"/>
</object> </object>
<object class="IBObjectRecord"> <object class="IBObjectRecord">
<int key="objectID">4</int> <int key="objectID">4</int>
<reference key="object" ref="221386056"/> <reference key="object" ref="221386056"/>
<reference key="parent" ref="360949347"/> <reference key="parent" ref="0"/>
</object> </object>
</object> </object>
</object> </object>
<object class="NSMutableDictionary" key="flattenedProperties"> <object class="NSMutableDictionary" key="flattenedProperties">
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSMutableArray" key="dict.sortedKeys"> <object class="NSArray" key="dict.sortedKeys">
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
<string>-1.CustomClassName</string> <string>-1.CustomClassName</string>
<string>-2.CustomClassName</string> <string>-2.CustomClassName</string>
@ -85,16 +99,14 @@
</object> </object>
<object class="NSMutableArray" key="dict.values"> <object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
<string>HintsViewController</string> <string>MessageViewController</string>
<string>UIResponder</string> <string>UIResponder</string>
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string> <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
</object> </object>
</object> </object>
<object class="NSMutableDictionary" key="unlocalizedProperties"> <object class="NSMutableDictionary" key="unlocalizedProperties">
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSArray" key="dict.sortedKeys"> <reference key="dict.sortedKeys" ref="0"/>
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
<object class="NSMutableArray" key="dict.values"> <object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
</object> </object>
@ -102,31 +114,236 @@
<nil key="activeLocalization"/> <nil key="activeLocalization"/>
<object class="NSMutableDictionary" key="localizations"> <object class="NSMutableDictionary" key="localizations">
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSArray" key="dict.sortedKeys"> <reference key="dict.sortedKeys" ref="0"/>
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
<object class="NSMutableArray" key="dict.values"> <object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
</object> </object>
</object> </object>
<nil key="sourceID"/> <nil key="sourceID"/>
<int key="maxID">5</int> <int key="maxID">6</int>
</object> </object>
<object class="IBClassDescriber" key="IBDocument.Classes"> <object class="IBClassDescriber" key="IBDocument.Classes">
<object class="NSMutableArray" key="referencedPartialClassDescriptions"> <object class="NSMutableArray" key="referencedPartialClassDescriptions">
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
<object class="IBPartialClassDescription"> <object class="IBPartialClassDescription">
<string key="className">HintsViewController</string> <string key="className">MessageViewController</string>
<string key="superclassName">UIViewController</string> <string key="superclassName">UIViewController</string>
<object class="NSMutableDictionary" key="outlets">
<string key="NS.key.0">callbackTarget</string>
<string key="NS.object.0">id</string>
</object>
<object class="IBClassDescriptionSource" key="sourceIdentifier"> <object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string> <string key="majorKey">IBProjectSource</string>
<string key="minorKey">Classes/HintsViewController.h</string> <string key="minorKey">Classes/MessageViewController.h</string>
</object>
</object>
</object>
<object class="NSMutableArray" key="referencedPartialClassDescriptionsV3.2+">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSError.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSFileManager.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSKeyValueCoding.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSKeyValueObserving.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSKeyedArchiver.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSNetServices.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSObject.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSPort.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSRunLoop.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSStream.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSThread.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSURL.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSURLConnection.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSXMLParser.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">UIKit.framework/Headers/UIAccessibility.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">UIKit.framework/Headers/UINibLoading.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier" id="25161611">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">UIKit.framework/Headers/UIResponder.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">UIResponder</string>
<string key="superclassName">NSObject</string>
<reference key="sourceIdentifier" ref="25161611"/>
</object>
<object class="IBPartialClassDescription">
<string key="className">UISearchBar</string>
<string key="superclassName">UIView</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">UIKit.framework/Headers/UISearchBar.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">UISearchDisplayController</string>
<string key="superclassName">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">UIKit.framework/Headers/UISearchDisplayController.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">UIView</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">UIKit.framework/Headers/UITextField.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">UIView</string>
<string key="superclassName">UIResponder</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">UIKit.framework/Headers/UIView.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">UIViewController</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">UIKit.framework/Headers/UINavigationController.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">UIViewController</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">UIKit.framework/Headers/UITabBarController.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">UIViewController</string>
<string key="superclassName">UIResponder</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">UIKit.framework/Headers/UIViewController.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">UIWebView</string>
<string key="superclassName">UIView</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">UIKit.framework/Headers/UIWebView.h</string>
</object> </object>
</object> </object>
</object> </object>
</object> </object>
<int key="IBDocument.localizationMode">0</int> <int key="IBDocument.localizationMode">0</int>
<nil key="IBDocument.LastKnownRelativeProjectPath"/> <string key="IBDocument.TargetRuntimeIdentifier">IBCocoaTouchFramework</string>
<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencies">
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS</string>
<integer value="768" key="NS.object.0"/>
</object>
<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencyDefaults">
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS</string>
<integer value="784" key="NS.object.0"/>
</object>
<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3</string>
<integer value="3000" key="NS.object.0"/>
</object>
<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
<string key="IBDocument.LastKnownRelativeProjectPath">../ZXing.xcodeproj</string>
<int key="IBDocument.defaultPropertyAccessControl">3</int> <int key="IBDocument.defaultPropertyAccessControl">3</int>
<string key="IBCocoaTouchPluginVersion">87</string>
</data> </data>
</archive> </archive>

View file

@ -10,8 +10,8 @@
<p style="font-weight: bold;"> <p style="font-weight: bold;">
<img style="width: 128px; height: 128px;" alt="ZXing Project Logo" src="../ZxingLarge.png"></p> <img style="width: 128px; height: 128px;" alt="ZXing Project Logo" src="../ZxingLarge.png"></p>
<h2>Streckkoder</h2> <h2>Streckkoder</h2>
<p>Version 1.0</p> <p>Version 1.1</p>
<p>&copy; 2008 The <a href="http://code.google.com/p/zxing/">ZXing</a> <p>&copy; 2008-2010 The <a href="http://code.google.com/p/zxing/">ZXing</a>
Authors<br> Authors<br>
</p> </p>
<p> <p>

View file

@ -1,11 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="7.02"> <archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="7.10">
<data> <data>
<int key="IBDocument.SystemTarget">512</int> <int key="IBDocument.SystemTarget">768</int>
<string key="IBDocument.SystemVersion">9E17</string> <string key="IBDocument.SystemVersion">10D573</string>
<string key="IBDocument.InterfaceBuilderVersion">670</string> <string key="IBDocument.InterfaceBuilderVersion">762</string>
<string key="IBDocument.AppKitVersion">949.33</string> <string key="IBDocument.AppKitVersion">1038.29</string>
<string key="IBDocument.HIToolboxVersion">352.00</string> <string key="IBDocument.HIToolboxVersion">460.00</string>
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
<string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="NS.object.0">87</string>
</object>
<object class="NSMutableArray" key="IBDocument.EditedObjectIDs"> <object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
</object> </object>
@ -13,13 +17,24 @@
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string> <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
</object> </object>
<object class="NSMutableDictionary" key="IBDocument.Metadata">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSArray" key="dict.sortedKeys" id="0">
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
</object>
<object class="NSMutableArray" key="IBDocument.RootObjects" id="1000"> <object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
<object class="IBProxyObject" id="372490531"> <object class="IBProxyObject" id="372490531">
<string key="IBProxiedObjectIdentifier">IBFilesOwner</string> <string key="IBProxiedObjectIdentifier">IBFilesOwner</string>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
</object> </object>
<object class="IBProxyObject" id="711762367"> <object class="IBProxyObject" id="711762367">
<string key="IBProxiedObjectIdentifier">IBFirstResponder</string> <string key="IBProxiedObjectIdentifier">IBFirstResponder</string>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
</object> </object>
<object class="IBUIWebView" id="221386056"> <object class="IBUIWebView" id="221386056">
<nil key="NSNextResponder"/> <nil key="NSNextResponder"/>
@ -31,6 +46,7 @@
</object> </object>
<bool key="IBUIClipsSubviews">YES</bool> <bool key="IBUIClipsSubviews">YES</bool>
<bool key="IBUIMultipleTouchEnabled">YES</bool> <bool key="IBUIMultipleTouchEnabled">YES</bool>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
<bool key="IBUIScalesPageToFit">YES</bool> <bool key="IBUIScalesPageToFit">YES</bool>
</object> </object>
</object> </object>
@ -51,33 +67,31 @@
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
<object class="IBObjectRecord"> <object class="IBObjectRecord">
<int key="objectID">0</int> <int key="objectID">0</int>
<object class="NSArray" key="object" id="360949347"> <reference key="object" ref="0"/>
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
<reference key="children" ref="1000"/> <reference key="children" ref="1000"/>
<nil key="parent"/> <nil key="parent"/>
</object> </object>
<object class="IBObjectRecord"> <object class="IBObjectRecord">
<int key="objectID">-1</int> <int key="objectID">-1</int>
<reference key="object" ref="372490531"/> <reference key="object" ref="372490531"/>
<reference key="parent" ref="360949347"/> <reference key="parent" ref="0"/>
<string type="base64-UTF8" key="objectName">RmlsZSdzIE93bmVyA</string> <string key="objectName">File's Owner</string>
</object> </object>
<object class="IBObjectRecord"> <object class="IBObjectRecord">
<int key="objectID">-2</int> <int key="objectID">-2</int>
<reference key="object" ref="711762367"/> <reference key="object" ref="711762367"/>
<reference key="parent" ref="360949347"/> <reference key="parent" ref="0"/>
</object> </object>
<object class="IBObjectRecord"> <object class="IBObjectRecord">
<int key="objectID">4</int> <int key="objectID">4</int>
<reference key="object" ref="221386056"/> <reference key="object" ref="221386056"/>
<reference key="parent" ref="360949347"/> <reference key="parent" ref="0"/>
</object> </object>
</object> </object>
</object> </object>
<object class="NSMutableDictionary" key="flattenedProperties"> <object class="NSMutableDictionary" key="flattenedProperties">
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSMutableArray" key="dict.sortedKeys"> <object class="NSArray" key="dict.sortedKeys">
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
<string>-1.CustomClassName</string> <string>-1.CustomClassName</string>
<string>-2.CustomClassName</string> <string>-2.CustomClassName</string>
@ -85,16 +99,14 @@
</object> </object>
<object class="NSMutableArray" key="dict.values"> <object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
<string>HintsViewController</string> <string>MessageViewController</string>
<string>UIResponder</string> <string>UIResponder</string>
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string> <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
</object> </object>
</object> </object>
<object class="NSMutableDictionary" key="unlocalizedProperties"> <object class="NSMutableDictionary" key="unlocalizedProperties">
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSArray" key="dict.sortedKeys"> <reference key="dict.sortedKeys" ref="0"/>
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
<object class="NSMutableArray" key="dict.values"> <object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
</object> </object>
@ -102,9 +114,7 @@
<nil key="activeLocalization"/> <nil key="activeLocalization"/>
<object class="NSMutableDictionary" key="localizations"> <object class="NSMutableDictionary" key="localizations">
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSArray" key="dict.sortedKeys"> <reference key="dict.sortedKeys" ref="0"/>
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
<object class="NSMutableArray" key="dict.values"> <object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
</object> </object>
@ -116,17 +126,224 @@
<object class="NSMutableArray" key="referencedPartialClassDescriptions"> <object class="NSMutableArray" key="referencedPartialClassDescriptions">
<bool key="EncodedWithXMLCoder">YES</bool> <bool key="EncodedWithXMLCoder">YES</bool>
<object class="IBPartialClassDescription"> <object class="IBPartialClassDescription">
<string key="className">HintsViewController</string> <string key="className">MessageViewController</string>
<string key="superclassName">UIViewController</string> <string key="superclassName">UIViewController</string>
<object class="NSMutableDictionary" key="outlets">
<string key="NS.key.0">callbackTarget</string>
<string key="NS.object.0">id</string>
</object>
<object class="IBClassDescriptionSource" key="sourceIdentifier"> <object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string> <string key="majorKey">IBProjectSource</string>
<string key="minorKey">Classes/HintsViewController.h</string> <string key="minorKey">Classes/MessageViewController.h</string>
</object>
</object>
</object>
<object class="NSMutableArray" key="referencedPartialClassDescriptionsV3.2+">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSError.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSFileManager.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSKeyValueCoding.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSKeyValueObserving.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSKeyedArchiver.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSNetServices.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSObject.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSPort.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSRunLoop.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSStream.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSThread.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSURL.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSURLConnection.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">Foundation.framework/Headers/NSXMLParser.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">UIKit.framework/Headers/UIAccessibility.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">UIKit.framework/Headers/UINibLoading.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier" id="63869399">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">UIKit.framework/Headers/UIResponder.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">UIResponder</string>
<string key="superclassName">NSObject</string>
<reference key="sourceIdentifier" ref="63869399"/>
</object>
<object class="IBPartialClassDescription">
<string key="className">UISearchBar</string>
<string key="superclassName">UIView</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">UIKit.framework/Headers/UISearchBar.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">UISearchDisplayController</string>
<string key="superclassName">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">UIKit.framework/Headers/UISearchDisplayController.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">UIView</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">UIKit.framework/Headers/UITextField.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">UIView</string>
<string key="superclassName">UIResponder</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">UIKit.framework/Headers/UIView.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">UIViewController</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">UIKit.framework/Headers/UINavigationController.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">UIViewController</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">UIKit.framework/Headers/UITabBarController.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">UIViewController</string>
<string key="superclassName">UIResponder</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">UIKit.framework/Headers/UIViewController.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">UIWebView</string>
<string key="superclassName">UIView</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBFrameworkSource</string>
<string key="minorKey">UIKit.framework/Headers/UIWebView.h</string>
</object> </object>
</object> </object>
</object> </object>
</object> </object>
<int key="IBDocument.localizationMode">0</int> <int key="IBDocument.localizationMode">0</int>
<nil key="IBDocument.LastKnownRelativeProjectPath"/> <string key="IBDocument.TargetRuntimeIdentifier">IBCocoaTouchFramework</string>
<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencies">
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS</string>
<integer value="768" key="NS.object.0"/>
</object>
<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencyDefaults">
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS</string>
<integer value="784" key="NS.object.0"/>
</object>
<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3</string>
<integer value="3000" key="NS.object.0"/>
</object>
<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
<string key="IBDocument.LastKnownRelativeProjectPath">../ZXing.xcodeproj</string>
<int key="IBDocument.defaultPropertyAccessControl">3</int> <int key="IBDocument.defaultPropertyAccessControl">3</int>
<string key="IBCocoaTouchPluginVersion">87</string>
</data> </data>
</archive> </archive>