mirror of
https://github.com/zxing/zxing.git
synced 2025-03-05 20:48:51 -08:00
Finished work on the local binarizer and renamed it to HybridBinarizer. It uses the old histogram for 1D and the new approach for 2D. The unit tests don't fully demonstrate how much better this is in real-world lighting, but it pretty much solves the situation of pointing at a QR Code for 30 seconds without scanning, due to a shadow or gradient.
HybridBinarizer is now the default across all the fast clients and the unit tests. git-svn-id: https://zxing.googlecode.com/svn/trunk@1157 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
parent
fde805cc02
commit
5cc1df3c92
|
@ -23,7 +23,7 @@ import com.google.zxing.MultiFormatReader;
|
||||||
import com.google.zxing.ReaderException;
|
import com.google.zxing.ReaderException;
|
||||||
import com.google.zxing.Result;
|
import com.google.zxing.Result;
|
||||||
import com.google.zxing.ResultPointCallback;
|
import com.google.zxing.ResultPointCallback;
|
||||||
import com.google.zxing.common.GlobalHistogramBinarizer;
|
import com.google.zxing.common.HybridBinarizer;
|
||||||
|
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
@ -165,7 +165,7 @@ final class DecodeThread extends Thread {
|
||||||
long start = System.currentTimeMillis();
|
long start = System.currentTimeMillis();
|
||||||
Result rawResult = null;
|
Result rawResult = null;
|
||||||
PlanarYUVLuminanceSource source = CameraManager.get().buildLuminanceSource(data, width, height);
|
PlanarYUVLuminanceSource source = CameraManager.get().buildLuminanceSource(data, width, height);
|
||||||
BinaryBitmap bitmap = new BinaryBitmap(new GlobalHistogramBinarizer(source));
|
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
|
||||||
try {
|
try {
|
||||||
rawResult = multiFormatReader.decodeWithState(bitmap);
|
rawResult = multiFormatReader.decodeWithState(bitmap);
|
||||||
} catch (ReaderException re) {
|
} catch (ReaderException re) {
|
||||||
|
|
|
@ -20,7 +20,7 @@ import com.google.zxing.BinaryBitmap;
|
||||||
import com.google.zxing.MultiFormatReader;
|
import com.google.zxing.MultiFormatReader;
|
||||||
import com.google.zxing.ReaderException;
|
import com.google.zxing.ReaderException;
|
||||||
import com.google.zxing.Result;
|
import com.google.zxing.Result;
|
||||||
import com.google.zxing.common.GlobalHistogramBinarizer;
|
import com.google.zxing.common.HybridBinarizer;
|
||||||
|
|
||||||
import android.os.Debug;
|
import android.os.Debug;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
|
@ -94,7 +94,7 @@ final class BenchmarkThread extends Thread {
|
||||||
// scheduling and what else is happening in the system.
|
// scheduling and what else is happening in the system.
|
||||||
long now = Debug.threadCpuTimeNanos();
|
long now = Debug.threadCpuTimeNanos();
|
||||||
try {
|
try {
|
||||||
BinaryBitmap bitmap = new BinaryBitmap(new GlobalHistogramBinarizer(source));
|
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
|
||||||
result = mMultiFormatReader.decodeWithState(bitmap);
|
result = mMultiFormatReader.decodeWithState(bitmap);
|
||||||
success = true;
|
success = true;
|
||||||
} catch (ReaderException e) {
|
} catch (ReaderException e) {
|
||||||
|
|
|
@ -26,10 +26,12 @@ import com.google.zxing.ReaderException;
|
||||||
* algorithm. However, because it picks a global black point, it cannot handle difficult shadows
|
* algorithm. However, because it picks a global black point, it cannot handle difficult shadows
|
||||||
* and gradients.
|
* and gradients.
|
||||||
*
|
*
|
||||||
|
* Faster mobile devices and all desktop applications should probably use HybridBinarizer instead.
|
||||||
|
*
|
||||||
* @author dswitkin@google.com (Daniel Switkin)
|
* @author dswitkin@google.com (Daniel Switkin)
|
||||||
* @author Sean Owen
|
* @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_BITS = 5;
|
||||||
private static final int LUMINANCE_SHIFT = 8 - LUMINANCE_BITS;
|
private static final int LUMINANCE_SHIFT = 8 - LUMINANCE_BITS;
|
||||||
|
@ -105,7 +107,7 @@ public final class GlobalHistogramBinarizer extends Binarizer {
|
||||||
for (int y = 0; y < height; y++) {
|
for (int y = 0; y < height; y++) {
|
||||||
int offset = y * width;
|
int offset = y * width;
|
||||||
for (int x = 0; x< width; x++) {
|
for (int x = 0; x< width; x++) {
|
||||||
int pixel = localLuminances[offset + x] & 0xff;
|
int pixel = localLuminances[offset + x] & 0xff;
|
||||||
if (pixel < blackPoint) {
|
if (pixel < blackPoint) {
|
||||||
matrix.set(x, y);
|
matrix.set(x, y);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ package com.google.zxing.common;
|
||||||
|
|
||||||
import com.google.zxing.Binarizer;
|
import com.google.zxing.Binarizer;
|
||||||
import com.google.zxing.LuminanceSource;
|
import com.google.zxing.LuminanceSource;
|
||||||
|
import com.google.zxing.ReaderException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class implements a local thresholding algorithm, which while slower than the
|
* This class implements a local thresholding algorithm, which while slower than the
|
||||||
|
@ -27,51 +28,56 @@ import com.google.zxing.LuminanceSource;
|
||||||
* However it tends to produce artifacts on lower frequency images and is therefore not
|
* However it tends to produce artifacts on lower frequency images and is therefore not
|
||||||
* a good general purpose binarizer for uses outside ZXing.
|
* a good general purpose binarizer for uses outside ZXing.
|
||||||
*
|
*
|
||||||
* NOTE: This class is still experimental and may not be ready for prime time yet.
|
* This class extends GlobalHistogramBinarizer, using the older histogram approach for 1D readers,
|
||||||
|
* and the newer local approach for 2D readers. 1D decoding using a per-row histogram is already
|
||||||
|
* inherently local, and only fails for horizontal gradients. We can revisit that problem later,
|
||||||
|
* but for now it was not a win to use local blocks for 1D.
|
||||||
|
*
|
||||||
|
* This Binarizer is the default for the unit tests and the recommended class for library users.
|
||||||
*
|
*
|
||||||
* @author dswitkin@google.com (Daniel Switkin)
|
* @author dswitkin@google.com (Daniel Switkin)
|
||||||
*/
|
*/
|
||||||
public final class LocalBlockBinarizer extends Binarizer {
|
public final class HybridBinarizer extends GlobalHistogramBinarizer {
|
||||||
|
|
||||||
|
// This class uses 5x5 blocks to compute local luminance, where each block is 8x8 pixels.
|
||||||
|
// So this is the smallest dimension in each axis we can accept.
|
||||||
|
private static final int MINIMUM_DIMENSION = 40;
|
||||||
|
|
||||||
private BitMatrix matrix = null;
|
private BitMatrix matrix = null;
|
||||||
|
|
||||||
public LocalBlockBinarizer(LuminanceSource source) {
|
public HybridBinarizer(LuminanceSource source) {
|
||||||
super(source);
|
super(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Consider a different strategy for 1D Readers.
|
public BitMatrix getBlackMatrix() throws ReaderException {
|
||||||
public BitArray getBlackRow(int y, BitArray row) {
|
|
||||||
binarizeEntireImage();
|
|
||||||
return matrix.getRow(y, row);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: If getBlackRow() calculates its own values, removing sharpening here.
|
|
||||||
public BitMatrix getBlackMatrix() {
|
|
||||||
binarizeEntireImage();
|
binarizeEntireImage();
|
||||||
return matrix;
|
return matrix;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Binarizer createBinarizer(LuminanceSource source) {
|
public Binarizer createBinarizer(LuminanceSource source) {
|
||||||
return new LocalBlockBinarizer(source);
|
return new HybridBinarizer(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculates the final BitMatrix once for all requests. This could be called once from the
|
// Calculates the final BitMatrix once for all requests. This could be called once from the
|
||||||
// constructor instead, but there are some advantages to doing it lazily, such as making
|
// constructor instead, but there are some advantages to doing it lazily, such as making
|
||||||
// profiling easier, and not doing heavy lifting when callers don't expect it.
|
// profiling easier, and not doing heavy lifting when callers don't expect it.
|
||||||
private void binarizeEntireImage() {
|
private void binarizeEntireImage() throws ReaderException {
|
||||||
if (matrix == null) {
|
if (matrix == null) {
|
||||||
LuminanceSource source = getLuminanceSource();
|
LuminanceSource source = getLuminanceSource();
|
||||||
byte[] luminances = source.getMatrix();
|
if (source.getWidth() >= MINIMUM_DIMENSION && source.getHeight() >= MINIMUM_DIMENSION) {
|
||||||
int width = source.getWidth();
|
byte[] luminances = source.getMatrix();
|
||||||
int height = source.getHeight();
|
int width = source.getWidth();
|
||||||
sharpenRow(luminances, width, height);
|
int height = source.getHeight();
|
||||||
|
int subWidth = width >> 3;
|
||||||
|
int subHeight = height >> 3;
|
||||||
|
int[][] blackPoints = calculateBlackPoints(luminances, subWidth, subHeight, width);
|
||||||
|
|
||||||
int subWidth = width >> 3;
|
matrix = new BitMatrix(width, height);
|
||||||
int subHeight = height >> 3;
|
calculateThresholdForBlock(luminances, subWidth, subHeight, width, blackPoints, matrix);
|
||||||
int[][] blackPoints = calculateBlackPoints(luminances, subWidth, subHeight, width);
|
} else {
|
||||||
|
// If the image is too small, fall back to the global histogram approach.
|
||||||
matrix = new BitMatrix(width, height);
|
matrix = super.getBlackMatrix();
|
||||||
calculateThresholdForBlock(luminances, subWidth, subHeight, width, blackPoints, matrix);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,26 +154,4 @@ public final class LocalBlockBinarizer extends Binarizer {
|
||||||
return blackPoints;
|
return blackPoints;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Applies a simple -1 4 -1 box filter with a weight of 2 to each row.
|
|
||||||
private static void sharpenRow(byte[] luminances, int width, int height) {
|
|
||||||
for (int y = 0; y < height; y++) {
|
|
||||||
int offset = y * width;
|
|
||||||
int left = luminances[offset] & 0xff;
|
|
||||||
int center = luminances[offset + 1] & 0xff;
|
|
||||||
for (int x = 1; x < width - 1; x++) {
|
|
||||||
int right = luminances[offset + x + 1] & 0xff;
|
|
||||||
int pixel = ((center << 2) - left - right) >> 1;
|
|
||||||
// Must clamp values to 0..255 so they will fit in a byte.
|
|
||||||
if (pixel > 255) {
|
|
||||||
pixel = 255;
|
|
||||||
} else if (pixel < 0) {
|
|
||||||
pixel = 0;
|
|
||||||
}
|
|
||||||
luminances[offset + x] = (byte)pixel;
|
|
||||||
left = center;
|
|
||||||
center = right;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
Binary file not shown.
Before Width: | Height: | Size: 842 B After Width: | Height: | Size: 856 B |
|
@ -184,7 +184,7 @@ public abstract class AbstractBlackBoxTestCase extends TestCase {
|
||||||
float rotation = testResults.get(x).getRotation();
|
float rotation = testResults.get(x).getRotation();
|
||||||
BufferedImage rotatedImage = rotateImage(image, rotation);
|
BufferedImage rotatedImage = rotateImage(image, rotation);
|
||||||
LuminanceSource source = new BufferedImageLuminanceSource(rotatedImage);
|
LuminanceSource source = new BufferedImageLuminanceSource(rotatedImage);
|
||||||
BinaryBitmap bitmap = new BinaryBitmap(new GlobalHistogramBinarizer(source));
|
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
|
||||||
if (decode(bitmap, rotation, expectedText, false)) {
|
if (decode(bitmap, rotation, expectedText, false)) {
|
||||||
passedCounts[x]++;
|
passedCounts[x]++;
|
||||||
}
|
}
|
||||||
|
@ -294,4 +294,4 @@ public abstract class AbstractBlackBoxTestCase extends TestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,7 +109,7 @@ public abstract class AbstractNegativeBlackBoxTestCase extends AbstractBlackBoxT
|
||||||
private boolean checkForFalsePositives(BufferedImage image, float rotationInDegrees) {
|
private boolean checkForFalsePositives(BufferedImage image, float rotationInDegrees) {
|
||||||
BufferedImage rotatedImage = rotateImage(image, rotationInDegrees);
|
BufferedImage rotatedImage = rotateImage(image, rotationInDegrees);
|
||||||
LuminanceSource source = new BufferedImageLuminanceSource(rotatedImage);
|
LuminanceSource source = new BufferedImageLuminanceSource(rotatedImage);
|
||||||
BinaryBitmap bitmap = new BinaryBitmap(new GlobalHistogramBinarizer(source));
|
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
|
||||||
Result result;
|
Result result;
|
||||||
try {
|
try {
|
||||||
result = getReader().decode(bitmap);
|
result = getReader().decode(bitmap);
|
||||||
|
|
|
@ -27,10 +27,10 @@ public final class DataMatrixBlackBox2TestCase extends AbstractBlackBoxTestCase
|
||||||
public DataMatrixBlackBox2TestCase() {
|
public DataMatrixBlackBox2TestCase() {
|
||||||
// TODO use MultiFormatReader here once Data Matrix decoder is done
|
// TODO use MultiFormatReader here once Data Matrix decoder is done
|
||||||
super("test/data/blackbox/datamatrix-2", new DataMatrixReader(), BarcodeFormat.DATAMATRIX);
|
super("test/data/blackbox/datamatrix-2", new DataMatrixReader(), BarcodeFormat.DATAMATRIX);
|
||||||
addTest(2, 2, 0.0f);
|
addTest(4, 4, 0.0f);
|
||||||
addTest(1, 1, 90.0f);
|
addTest(1, 1, 90.0f);
|
||||||
addTest(4, 4, 180.0f);
|
addTest(3, 3, 180.0f);
|
||||||
addTest(3, 3, 270.0f);
|
addTest(1, 1, 270.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ public final class PDF417BlackBox2TestCase extends AbstractBlackBoxTestCase {
|
||||||
public PDF417BlackBox2TestCase() {
|
public PDF417BlackBox2TestCase() {
|
||||||
super("test/data/blackbox/pdf417-2", new MultiFormatReader(), BarcodeFormat.PDF417);
|
super("test/data/blackbox/pdf417-2", new MultiFormatReader(), BarcodeFormat.PDF417);
|
||||||
addTest(11, 11, 0.0f);
|
addTest(11, 11, 0.0f);
|
||||||
addTest(12, 12, 180.0f);
|
addTest(11, 11, 180.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -46,4 +46,4 @@ public final class PDF417BlackBox2TestCase extends AbstractBlackBoxTestCase {
|
||||||
return table;
|
return table;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,10 +27,10 @@ public final class QRCodeBlackBox1TestCase extends AbstractBlackBoxTestCase {
|
||||||
|
|
||||||
public QRCodeBlackBox1TestCase() {
|
public QRCodeBlackBox1TestCase() {
|
||||||
super("test/data/blackbox/qrcode-1", new MultiFormatReader(), BarcodeFormat.QR_CODE);
|
super("test/data/blackbox/qrcode-1", new MultiFormatReader(), BarcodeFormat.QR_CODE);
|
||||||
addTest(19, 19, 0.0f);
|
addTest(17, 17, 0.0f);
|
||||||
addTest(15, 15, 90.0f);
|
addTest(13, 13, 90.0f);
|
||||||
addTest(17, 17, 180.0f);
|
addTest(16, 16, 180.0f);
|
||||||
addTest(15, 15, 270.0f);
|
addTest(14, 14, 270.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,10 +27,10 @@ public final class QRCodeBlackBox2TestCase extends AbstractBlackBoxTestCase {
|
||||||
|
|
||||||
public QRCodeBlackBox2TestCase() {
|
public QRCodeBlackBox2TestCase() {
|
||||||
super("test/data/blackbox/qrcode-2", new MultiFormatReader(), BarcodeFormat.QR_CODE);
|
super("test/data/blackbox/qrcode-2", new MultiFormatReader(), BarcodeFormat.QR_CODE);
|
||||||
addTest(23, 23, 0.0f);
|
addTest(21, 21, 0.0f);
|
||||||
addTest(21, 21, 90.0f);
|
addTest(18, 18, 90.0f);
|
||||||
addTest(20, 20, 180.0f);
|
addTest(20, 20, 180.0f);
|
||||||
addTest(18, 18, 270.0f);
|
addTest(18, 18, 270.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,10 +27,10 @@ public final class QRCodeBlackBox3TestCase extends AbstractBlackBoxTestCase {
|
||||||
|
|
||||||
public QRCodeBlackBox3TestCase() {
|
public QRCodeBlackBox3TestCase() {
|
||||||
super("test/data/blackbox/qrcode-3", new MultiFormatReader(), BarcodeFormat.QR_CODE);
|
super("test/data/blackbox/qrcode-3", new MultiFormatReader(), BarcodeFormat.QR_CODE);
|
||||||
addTest(33, 33, 0.0f);
|
addTest(36, 36, 0.0f);
|
||||||
addTest(36, 36, 90.0f);
|
addTest(37, 37, 90.0f);
|
||||||
addTest(32, 32, 180.0f);
|
addTest(35, 35, 180.0f);
|
||||||
addTest(38, 38, 270.0f);
|
addTest(37, 37, 270.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,10 +29,10 @@ public final class QRCodeBlackBox4TestCase extends AbstractBlackBoxTestCase {
|
||||||
|
|
||||||
public QRCodeBlackBox4TestCase() {
|
public QRCodeBlackBox4TestCase() {
|
||||||
super("test/data/blackbox/qrcode-4", new MultiFormatReader(), BarcodeFormat.QR_CODE);
|
super("test/data/blackbox/qrcode-4", new MultiFormatReader(), BarcodeFormat.QR_CODE);
|
||||||
addTest(32, 32, 0.0f);
|
addTest(35, 35, 0.0f);
|
||||||
addTest(37, 37, 90.0f);
|
addTest(36, 36, 90.0f);
|
||||||
addTest(36, 36, 180.0f);
|
addTest(34, 34, 180.0f);
|
||||||
addTest(34, 34, 270.0f);
|
addTest(34, 34, 270.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ import com.google.zxing.common.AbstractBlackBoxTestCase;
|
||||||
/**
|
/**
|
||||||
* Some very difficult exposure conditions including self-shadowing, which happens a lot when
|
* Some very difficult exposure conditions including self-shadowing, which happens a lot when
|
||||||
* pointing down at a barcode (i.e. the phone's shadow falls across part of the image).
|
* pointing down at a barcode (i.e. the phone's shadow falls across part of the image).
|
||||||
|
* The global histogram gets about 5/15, where the local one gets 15/15.
|
||||||
*
|
*
|
||||||
* @author dswitkin@google.com (Daniel Switkin)
|
* @author dswitkin@google.com (Daniel Switkin)
|
||||||
*/
|
*/
|
||||||
|
@ -30,10 +31,10 @@ public final class QRCodeBlackBox5TestCase extends AbstractBlackBoxTestCase {
|
||||||
|
|
||||||
public QRCodeBlackBox5TestCase() {
|
public QRCodeBlackBox5TestCase() {
|
||||||
super("test/data/blackbox/qrcode-5", new MultiFormatReader(), BarcodeFormat.QR_CODE);
|
super("test/data/blackbox/qrcode-5", new MultiFormatReader(), BarcodeFormat.QR_CODE);
|
||||||
addTest(5, 5, 0.0f);
|
addTest(15, 15, 0.0f);
|
||||||
addTest(4, 4, 90.0f);
|
addTest(15, 15, 90.0f);
|
||||||
addTest(5, 5, 180.0f);
|
addTest(15, 15, 180.0f);
|
||||||
addTest(5, 5, 270.0f);
|
addTest(15, 15, 270.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,18 +16,18 @@
|
||||||
|
|
||||||
package com.google.zxing.client.j2se;
|
package com.google.zxing.client.j2se;
|
||||||
|
|
||||||
|
import com.google.zxing.BarcodeFormat;
|
||||||
import com.google.zxing.BinaryBitmap;
|
import com.google.zxing.BinaryBitmap;
|
||||||
import com.google.zxing.DecodeHintType;
|
import com.google.zxing.DecodeHintType;
|
||||||
import com.google.zxing.LuminanceSource;
|
import com.google.zxing.LuminanceSource;
|
||||||
import com.google.zxing.MultiFormatReader;
|
import com.google.zxing.MultiFormatReader;
|
||||||
import com.google.zxing.ReaderException;
|
import com.google.zxing.ReaderException;
|
||||||
import com.google.zxing.Result;
|
import com.google.zxing.Result;
|
||||||
import com.google.zxing.BarcodeFormat;
|
|
||||||
import com.google.zxing.client.result.ParsedResult;
|
import com.google.zxing.client.result.ParsedResult;
|
||||||
import com.google.zxing.client.result.ResultParser;
|
import com.google.zxing.client.result.ResultParser;
|
||||||
import com.google.zxing.common.BitArray;
|
import com.google.zxing.common.BitArray;
|
||||||
import com.google.zxing.common.BitMatrix;
|
import com.google.zxing.common.BitMatrix;
|
||||||
import com.google.zxing.common.GlobalHistogramBinarizer;
|
import com.google.zxing.common.HybridBinarizer;
|
||||||
|
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
@ -200,7 +200,7 @@ public final class CommandLineRunner {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
LuminanceSource source = new BufferedImageLuminanceSource(image);
|
LuminanceSource source = new BufferedImageLuminanceSource(image);
|
||||||
BinaryBitmap bitmap = new BinaryBitmap(new GlobalHistogramBinarizer(source));
|
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
|
||||||
if (dumpBlackPoint) {
|
if (dumpBlackPoint) {
|
||||||
dumpBlackPoint(uri, image, bitmap);
|
dumpBlackPoint(uri, image, bitmap);
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ import com.google.zxing.LuminanceSource;
|
||||||
import com.google.zxing.MultiFormatReader;
|
import com.google.zxing.MultiFormatReader;
|
||||||
import com.google.zxing.ReaderException;
|
import com.google.zxing.ReaderException;
|
||||||
import com.google.zxing.Result;
|
import com.google.zxing.Result;
|
||||||
import com.google.zxing.common.GlobalHistogramBinarizer;
|
import com.google.zxing.common.HybridBinarizer;
|
||||||
|
|
||||||
import java.awt.Container;
|
import java.awt.Container;
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
|
@ -95,7 +95,7 @@ public final class GUIRunner extends JFrame {
|
||||||
return "Could not decode image";
|
return "Could not decode image";
|
||||||
}
|
}
|
||||||
LuminanceSource source = new BufferedImageLuminanceSource(image);
|
LuminanceSource source = new BufferedImageLuminanceSource(image);
|
||||||
BinaryBitmap bitmap = new BinaryBitmap(new GlobalHistogramBinarizer(source));
|
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
|
||||||
Result result;
|
Result result;
|
||||||
try {
|
try {
|
||||||
result = new MultiFormatReader().decode(bitmap);
|
result = new MultiFormatReader().decode(bitmap);
|
||||||
|
|
|
@ -21,7 +21,7 @@ import com.google.zxing.LuminanceSource;
|
||||||
import com.google.zxing.ReaderException;
|
import com.google.zxing.ReaderException;
|
||||||
import com.google.zxing.common.BitArray;
|
import com.google.zxing.common.BitArray;
|
||||||
import com.google.zxing.common.BitMatrix;
|
import com.google.zxing.common.BitMatrix;
|
||||||
import com.google.zxing.common.GlobalHistogramBinarizer;
|
import com.google.zxing.common.HybridBinarizer;
|
||||||
|
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
@ -96,7 +96,7 @@ public final class ImageConverter {
|
||||||
private static void convertImage(URI uri) throws IOException {
|
private static void convertImage(URI uri) throws IOException {
|
||||||
BufferedImage image = ImageIO.read(uri.toURL());
|
BufferedImage image = ImageIO.read(uri.toURL());
|
||||||
LuminanceSource source = new BufferedImageLuminanceSource(image);
|
LuminanceSource source = new BufferedImageLuminanceSource(image);
|
||||||
BinaryBitmap bitmap = new BinaryBitmap(new GlobalHistogramBinarizer(source));
|
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
|
||||||
int width = bitmap.getWidth();
|
int width = bitmap.getWidth();
|
||||||
int height = bitmap.getHeight();
|
int height = bitmap.getHeight();
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ import com.google.zxing.Reader;
|
||||||
import com.google.zxing.ReaderException;
|
import com.google.zxing.ReaderException;
|
||||||
import com.google.zxing.Result;
|
import com.google.zxing.Result;
|
||||||
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
|
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
|
||||||
import com.google.zxing.common.GlobalHistogramBinarizer;
|
import com.google.zxing.common.HybridBinarizer;
|
||||||
|
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -147,7 +147,7 @@ final class DecodeEmailTask extends TimerTask {
|
||||||
Result result = null;
|
Result result = null;
|
||||||
try {
|
try {
|
||||||
LuminanceSource source = new BufferedImageLuminanceSource(image);
|
LuminanceSource source = new BufferedImageLuminanceSource(image);
|
||||||
BinaryBitmap bitmap = new BinaryBitmap(new GlobalHistogramBinarizer(source));
|
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
|
||||||
result = reader.decode(bitmap, DecodeServlet.HINTS);
|
result = reader.decode(bitmap, DecodeServlet.HINTS);
|
||||||
} catch (ReaderException re) {
|
} catch (ReaderException re) {
|
||||||
log.info("Decoding FAILED");
|
log.info("Decoding FAILED");
|
||||||
|
@ -191,4 +191,4 @@ final class DecodeEmailTask extends TimerTask {
|
||||||
new DecodeEmailTask(emailAddress, emailAuthenticator).run();
|
new DecodeEmailTask(emailAddress, emailAuthenticator).run();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ import com.google.zxing.Result;
|
||||||
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
|
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
|
||||||
import com.google.zxing.client.result.ParsedResult;
|
import com.google.zxing.client.result.ParsedResult;
|
||||||
import com.google.zxing.client.result.ResultParser;
|
import com.google.zxing.client.result.ResultParser;
|
||||||
import com.google.zxing.common.GlobalHistogramBinarizer;
|
import com.google.zxing.common.HybridBinarizer;
|
||||||
|
|
||||||
import org.apache.commons.fileupload.FileItem;
|
import org.apache.commons.fileupload.FileItem;
|
||||||
import org.apache.commons.fileupload.FileUploadException;
|
import org.apache.commons.fileupload.FileUploadException;
|
||||||
|
@ -78,7 +78,7 @@ import javax.servlet.http.HttpServletResponse;
|
||||||
/**
|
/**
|
||||||
* {@link HttpServlet} which decodes images containing barcodes. Given a URL, it will
|
* {@link HttpServlet} which decodes images containing barcodes. Given a URL, it will
|
||||||
* retrieve the image and decode it. It can also process image files uploaded via POST.
|
* retrieve the image and decode it. It can also process image files uploaded via POST.
|
||||||
*
|
*
|
||||||
* @author Sean Owen
|
* @author Sean Owen
|
||||||
*/
|
*/
|
||||||
public final class DecodeServlet extends HttpServlet {
|
public final class DecodeServlet extends HttpServlet {
|
||||||
|
@ -102,7 +102,7 @@ public final class DecodeServlet extends HttpServlet {
|
||||||
possibleFormats.add(BarcodeFormat.ITF);
|
possibleFormats.add(BarcodeFormat.ITF);
|
||||||
possibleFormats.add(BarcodeFormat.QR_CODE);
|
possibleFormats.add(BarcodeFormat.QR_CODE);
|
||||||
possibleFormats.add(BarcodeFormat.DATAMATRIX);
|
possibleFormats.add(BarcodeFormat.DATAMATRIX);
|
||||||
possibleFormats.add(BarcodeFormat.PDF417);
|
possibleFormats.add(BarcodeFormat.PDF417);
|
||||||
HINTS.put(DecodeHintType.POSSIBLE_FORMATS, possibleFormats);
|
HINTS.put(DecodeHintType.POSSIBLE_FORMATS, possibleFormats);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,7 +249,7 @@ public final class DecodeServlet extends HttpServlet {
|
||||||
Result result;
|
Result result;
|
||||||
try {
|
try {
|
||||||
LuminanceSource source = new BufferedImageLuminanceSource(image);
|
LuminanceSource source = new BufferedImageLuminanceSource(image);
|
||||||
BinaryBitmap bitmap = new BinaryBitmap(new GlobalHistogramBinarizer(source));
|
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
|
||||||
result = reader.decode(bitmap, HINTS);
|
result = reader.decode(bitmap, HINTS);
|
||||||
} catch (ReaderException re) {
|
} catch (ReaderException re) {
|
||||||
log.info("DECODE FAILED: " + re.toString());
|
log.info("DECODE FAILED: " + re.toString());
|
||||||
|
|
Loading…
Reference in a new issue