import com.google.zxing.Binarizer;
import com.google.zxing.LuminanceSource;
-import com.google.zxing.ReaderException;
+import com.google.zxing.NotFoundException;
/**
* This Binarizer implementation uses the old ZXing global histogram approach. It is suitable
* algorithm. However, because it picks a global black point, it cannot handle difficult shadows
* and gradients.
*
+ * Faster mobile devices and all desktop applications should probably use HybridBinarizer instead.
+ *
* @author dswitkin@google.com (Daniel Switkin)
* @author Sean Owen
*/
-public final class GlobalHistogramBinarizer extends Binarizer {
+public class GlobalHistogramBinarizer extends Binarizer {
private static final int LUMINANCE_BITS = 5;
private static final int LUMINANCE_SHIFT = 8 - LUMINANCE_BITS;
}
// Applies simple sharpening to the row data to improve performance of the 1D Readers.
- public BitArray getBlackRow(int y, BitArray row) throws ReaderException {
+ public BitArray getBlackRow(int y, BitArray row) throws NotFoundException {
LuminanceSource source = getLuminanceSource();
int width = source.getWidth();
if (row == null || row.getSize() < width) {
}
// Does not sharpen the data, as this call is intended to only be used by 2D Readers.
- public BitMatrix getBlackMatrix() throws ReaderException {
+ public BitMatrix getBlackMatrix() throws NotFoundException {
LuminanceSource source = getLuminanceSource();
int width = source.getWidth();
int height = source.getHeight();
for (int y = 1; y < 5; y++) {
int row = height * y / 5;
byte[] localLuminances = source.getRow(row, luminances);
- int right = width * 4 / 5;
+ int right = (width << 2) / 5;
for (int x = width / 5; x < right; x++) {
int pixel = localLuminances[x] & 0xff;
localBuckets[pixel >> LUMINANCE_SHIFT]++;
for (int y = 0; y < height; y++) {
int offset = y * width;
for (int x = 0; x< width; x++) {
- int pixel = localLuminances[offset + x] & 0xff;
+ int pixel = localLuminances[offset + x] & 0xff;
if (pixel < blackPoint) {
matrix.set(x, y);
}
}
}
- private static int estimateBlackPoint(int[] buckets) throws ReaderException {
+ private static int estimateBlackPoint(int[] buckets) throws NotFoundException {
// Find the tallest peak in the histogram.
int numBuckets = buckets.length;
int maxBucketCount = 0;
int firstPeak = 0;
int firstPeakSize = 0;
- for (int i = 0; i < numBuckets; i++) {
- if (buckets[i] > firstPeakSize) {
- firstPeak = i;
- firstPeakSize = buckets[i];
+ for (int x = 0; x < numBuckets; x++) {
+ if (buckets[x] > firstPeakSize) {
+ firstPeak = x;
+ firstPeakSize = buckets[x];
}
- if (buckets[i] > maxBucketCount) {
- maxBucketCount = buckets[i];
+ if (buckets[x] > maxBucketCount) {
+ maxBucketCount = buckets[x];
}
}
// Find the second-tallest peak which is somewhat far from the tallest peak.
int secondPeak = 0;
int secondPeakScore = 0;
- for (int i = 0; i < numBuckets; i++) {
- int distanceToBiggest = i - firstPeak;
+ for (int x = 0; x < numBuckets; x++) {
+ int distanceToBiggest = x - firstPeak;
// Encourage more distant second peaks by multiplying by square of distance.
- int score = buckets[i] * distanceToBiggest * distanceToBiggest;
+ int score = buckets[x] * distanceToBiggest * distanceToBiggest;
if (score > secondPeakScore) {
- secondPeak = i;
+ secondPeak = x;
secondPeakScore = score;
}
}
// TODO: It might be worth comparing the brightest and darkest pixels seen, rather than the
// two peaks, to determine the contrast.
if (secondPeak - firstPeak <= numBuckets >> 4) {
- throw ReaderException.getInstance();
+ throw NotFoundException.getNotFoundInstance();
}
// 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;
- int score = fromFirst * fromFirst * (secondPeak - i) * (maxBucketCount - buckets[i]);
+ for (int x = secondPeak - 1; x > firstPeak; x--) {
+ int fromFirst = x - firstPeak;
+ int score = fromFirst * fromFirst * (secondPeak - x) * (maxBucketCount - buckets[x]);
if (score > bestValleyScore) {
- bestValley = i;
+ bestValley = x;
bestValleyScore = score;
}
}