* 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;
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);
}
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;
}
}
// 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;
}
}