Issue 1825. PDF417Reader can't modify the image. When it doesn't, it actually reduces the number of images that pass unfortunately.

git-svn-id: https://zxing.googlecode.com/svn/trunk@3001 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
srowen 2013-12-20 16:44:39 +00:00
parent 10c2f71671
commit 6463455d26
13 changed files with 144 additions and 162 deletions

View file

@ -136,4 +136,13 @@ public final class BinaryBitmap {
return new BinaryBitmap(binarizer.createBinarizer(newSource));
}
@Override
public String toString() {
try {
return getBlackMatrix().toString();
} catch (NotFoundException e) {
return "";
}
}
}

View file

@ -16,12 +16,14 @@
package com.google.zxing.common;
import java.util.Arrays;
/**
* <p>A simple, fast array of bits, represented compactly by an array of ints internally.</p>
*
* @author Sean Owen
*/
public final class BitArray {
public final class BitArray implements Cloneable {
private int[] bits;
private int size;
@ -334,6 +336,20 @@ public final class BitArray {
return new int[(size + 31) / 32];
}
@Override
public boolean equals(Object o) {
if (!(o instanceof BitArray)) {
return false;
}
BitArray other = (BitArray) o;
return size == other.size && Arrays.equals(bits, other.bits);
}
@Override
public int hashCode() {
return 31 * size + Arrays.hashCode(bits);
}
@Override
public String toString() {
StringBuilder result = new StringBuilder(size);
@ -346,4 +362,9 @@ public final class BitArray {
return result.toString();
}
@Override
public BitArray clone() {
return new BitArray(bits.clone(), size);
}
}

View file

@ -16,6 +16,8 @@
package com.google.zxing.common;
import java.util.Arrays;
/**
* <p>Represents a 2D matrix of bits. In function arguments below, and throughout the common
* module, x is the column position, and y is the row position. The ordering is always x, y.
@ -31,7 +33,7 @@ package com.google.zxing.common;
* @author Sean Owen
* @author dswitkin@google.com (Daniel Switkin)
*/
public final class BitMatrix {
public final class BitMatrix implements Cloneable {
private final int width;
private final int height;
@ -53,6 +55,13 @@ public final class BitMatrix {
bits = new int[rowSize * height];
}
private BitMatrix(int width, int height, int rowSize, int[] bits) {
this.width = width;
this.height = height;
this.rowSize = rowSize;
this.bits = bits;
}
/**
* <p>Gets the requested bit, where true means black.</p>
*
@ -136,6 +145,8 @@ public final class BitMatrix {
public BitArray getRow(int y, BitArray row) {
if (row == null || row.getSize() < width) {
row = new BitArray(width);
} else {
row.clear();
}
int offset = y * rowSize;
for (int x = 0; x < rowSize; x++) {
@ -152,10 +163,28 @@ public final class BitMatrix {
System.arraycopy(row.getBitArray(), 0, bits, y * rowSize, rowSize);
}
/**
* Modifies this {@code BitMatrix} to represent the same but rotated 180 degrees
*/
public void rotate180() {
int width = getWidth();
int height = getHeight();
BitArray topRow = new BitArray(width);
BitArray bottomRow = new BitArray(width);
for (int i = 0; i < (height+1) / 2; i++) {
topRow = getRow(i, topRow);
bottomRow = getRow(height - 1 - i, bottomRow);
topRow.reverse();
bottomRow.reverse();
setRow(i, bottomRow);
setRow(height - 1 - i, topRow);
}
}
/**
* This is useful in detecting the enclosing rectangle of a 'pure' barcode.
*
* @return {left,top,width,height} enclosing rectangle of all 1 bits, or null if it is all white
* @return {@code left,top,width,height} enclosing rectangle of all 1 bits, or null if it is all white
*/
public int[] getEnclosingRectangle() {
int left = width;
@ -208,7 +237,7 @@ public final class BitMatrix {
/**
* This is useful in detecting a corner of a 'pure' barcode.
*
* @return {x,y} coordinate of top-left-most 1 bit, or null if it is all white
* @return {@code x,y} coordinate of top-left-most 1 bit, or null if it is all white
*/
public int[] getTopLeftOnBit() {
int bitsOffset = 0;
@ -272,16 +301,8 @@ public final class BitMatrix {
return false;
}
BitMatrix other = (BitMatrix) o;
if (width != other.width || height != other.height ||
rowSize != other.rowSize || bits.length != other.bits.length) {
return false;
}
for (int i = 0; i < bits.length; i++) {
if (bits[i] != other.bits[i]) {
return false;
}
}
return true;
return width == other.width && height == other.height && rowSize == other.rowSize &&
Arrays.equals(bits, other.bits);
}
@Override
@ -290,9 +311,7 @@ public final class BitMatrix {
hash = 31 * hash + width;
hash = 31 * hash + height;
hash = 31 * hash + rowSize;
for (int bit : bits) {
hash = 31 * hash + bit;
}
hash = 31 * hash + Arrays.hashCode(bits);
return hash;
}
@ -308,4 +327,9 @@ public final class BitMatrix {
return result.toString();
}
@Override
public BitMatrix clone() {
return new BitMatrix(width, height, rowSize, bits.clone());
}
}

View file

@ -20,7 +20,6 @@ import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.NotFoundException;
import com.google.zxing.ResultPoint;
import com.google.zxing.common.BitArray;
import com.google.zxing.common.BitMatrix;
import java.util.ArrayList;
@ -82,7 +81,8 @@ public final class Detector {
List<ResultPoint[]> barcodeCoordinates = detect(multiple, bitMatrix);
if (barcodeCoordinates.isEmpty()) {
rotate180(bitMatrix);
bitMatrix = bitMatrix.clone();
bitMatrix.rotate180();
barcodeCoordinates = detect(multiple, bitMatrix);
}
return new PDF417DetectorResult(bitMatrix, barcodeCoordinates);
@ -141,39 +141,6 @@ public final class Detector {
return barcodeCoordinates;
}
// The following could go to the BitMatrix class (maybe in a more efficient version using the BitMatrix internal
// data structures)
/**
* Rotates a bit matrix by 180 degrees.
* @param bitMatrix bit matrix to rotate
*/
static void rotate180(BitMatrix bitMatrix) {
int width = bitMatrix.getWidth();
int height = bitMatrix.getHeight();
BitArray firstRowBitArray = new BitArray(width);
BitArray secondRowBitArray = new BitArray(width);
BitArray tmpBitArray = new BitArray(width);
for (int y = 0; y < height + 1 >> 1; y++) {
firstRowBitArray = bitMatrix.getRow(y, firstRowBitArray);
bitMatrix.setRow(y, mirror(bitMatrix.getRow(height - 1 - y, secondRowBitArray), tmpBitArray));
bitMatrix.setRow(height - 1 - y, mirror(firstRowBitArray, tmpBitArray));
}
}
/**
* Copies the bits from the input to the result BitArray in reverse order
*/
static BitArray mirror(BitArray input, BitArray result) {
result.clear();
int size = input.getSize();
for (int i = 0; i < size; i++) {
if (input.get(i)) {
result.set(size - 1 - i);
}
}
return result;
}
/**
* Locate the vertices and the codewords area of a black blob using the Start
* and Stop patterns as locators.

View file

@ -25,6 +25,8 @@ import org.junit.Test;
*/
public final class BitMatrixTestCase extends Assert {
private static final int[] BIT_MATRIX_POINTS = { 1, 2, 2, 0, 3, 1 };
@Test
public void testGetSet() {
BitMatrix matrix = new BitMatrix(33);
@ -127,4 +129,56 @@ public final class BitMatrixTestCase extends Assert {
}
}
@Test
public void testRotate180Simple() {
BitMatrix matrix = new BitMatrix(3, 3);
matrix.set(0, 0);
matrix.set(0, 1);
matrix.set(1, 2);
matrix.set(2, 1);
matrix.rotate180();
assertTrue(matrix.get(2, 2));
assertTrue(matrix.get(2, 1));
assertTrue(matrix.get(1, 0));
assertTrue(matrix.get(0, 1));
}
@Test
public void testRotate180() {
testRotate180(7, 4);
testRotate180(7, 5);
testRotate180(8, 4);
testRotate180(8, 5);
}
private static void testRotate180(int width, int height) {
BitMatrix input = getInput(width, height);
input.rotate180();
BitMatrix expected = getExpected(width, height);
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
assertEquals("(" + x + ',' + y + ')', expected.get(x, y), input.get(x, y));
}
}
}
private static BitMatrix getExpected(int width, int height) {
BitMatrix result = new BitMatrix(width, height);
for (int i = 0; i < BIT_MATRIX_POINTS.length; i += 2) {
result.set(width - 1 - BIT_MATRIX_POINTS[i], height - 1 - BIT_MATRIX_POINTS[i + 1]);
}
return result;
}
private static BitMatrix getInput(int width, int height) {
BitMatrix result = new BitMatrix(width, height);
for (int i = 0; i < BIT_MATRIX_POINTS.length; i += 2) {
result.set(BIT_MATRIX_POINTS[i], BIT_MATRIX_POINTS[i + 1]);
}
return result;
}
}

View file

@ -27,10 +27,10 @@ public final class DataMatrixBlackBox2TestCase extends AbstractBlackBoxTestCase
public DataMatrixBlackBox2TestCase() {
super("src/test/resources/blackbox/datamatrix-2", new MultiFormatReader(), BarcodeFormat.DATA_MATRIX);
addTest(8, 15, 0, 1, 0.0f);
addTest(14, 16, 0, 1, 90.0f);
addTest(14, 15, 0, 1, 180.0f);
addTest(13, 16, 0, 1, 270.0f);
addTest(8, 8, 0, 1, 0.0f);
addTest(14, 14, 0, 1, 90.0f);
addTest(14, 14, 0, 1, 180.0f);
addTest(13, 13, 0, 1, 270.0f);
}
}

View file

@ -1,93 +0,0 @@
/*
* Copyright 2013 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.zxing.pdf417.detector;
import com.google.zxing.common.BitArray;
import com.google.zxing.common.BitMatrix;
import org.junit.Assert;
import org.junit.Test;
public final class DetectorTest extends Assert {
private static final int[] BIT_SET_INDEX = { 1, 2, 3, 5 };
private static final int[] BIT_MATRIX_POINTS = { 1, 2, 2, 0, 3, 1 };
@Test
public void testMirror() {
testMirror(7);
testMirror(8);
}
private static void testMirror(int size) {
BitArray result = new BitArray(size);
Detector.mirror(getInput(size), result);
assertEquals(getExpected(size).toString(), result.toString());
}
@Test
public void testRotate180() {
testRotate180(7, 4);
testRotate180(7, 5);
testRotate180(8, 4);
testRotate180(8, 5);
}
private static void testRotate180(int width, int height) {
BitMatrix input = getInput(width, height);
Detector.rotate180(input);
BitMatrix expected = getExpected(width, height);
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
assertEquals("(" + x + ',' + y + ')', expected.get(x, y), input.get(x, y));
}
}
}
private static BitMatrix getExpected(int width, int height) {
BitMatrix result = new BitMatrix(width, height);
for (int i = 0; i < BIT_MATRIX_POINTS.length; i += 2) {
result.set(width - 1 - BIT_MATRIX_POINTS[i], height - 1 - BIT_MATRIX_POINTS[i + 1]);
}
return result;
}
private static BitMatrix getInput(int width, int height) {
BitMatrix result = new BitMatrix(width, height);
for (int i = 0; i < BIT_MATRIX_POINTS.length; i += 2) {
result.set(BIT_MATRIX_POINTS[i], BIT_MATRIX_POINTS[i + 1]);
}
return result;
}
private static BitArray getExpected(int size) {
BitArray expected = new BitArray(size);
for (int index : BIT_SET_INDEX) {
expected.set(size - 1 - index);
}
return expected;
}
private static BitArray getInput(int size) {
BitArray input = new BitArray(size);
for (int index : BIT_SET_INDEX) {
input.set(index);
}
return input;
}
}

View file

@ -28,9 +28,9 @@ public final class QRCodeBlackBox1TestCase extends AbstractBlackBoxTestCase {
public QRCodeBlackBox1TestCase() {
super("src/test/resources/blackbox/qrcode-1", new MultiFormatReader(), BarcodeFormat.QR_CODE);
addTest(17, 17, 0.0f);
addTest(14, 15, 90.0f);
addTest(14, 14, 90.0f);
addTest(17, 17, 180.0f);
addTest(14, 15, 270.0f);
addTest(14, 14, 270.0f);
}
}

View file

@ -27,10 +27,10 @@ public final class QRCodeBlackBox2TestCase extends AbstractBlackBoxTestCase {
public QRCodeBlackBox2TestCase() {
super("src/test/resources/blackbox/qrcode-2", new MultiFormatReader(), BarcodeFormat.QR_CODE);
addTest(30, 31, 0.0f);
addTest(29, 30, 90.0f);
addTest(30, 30, 0.0f);
addTest(29, 29, 90.0f);
addTest(30, 30, 180.0f);
addTest(29, 30, 270.0f);
addTest(29, 29, 270.0f);
}
}

View file

@ -28,8 +28,8 @@ public final class QRCodeBlackBox3TestCase extends AbstractBlackBoxTestCase {
public QRCodeBlackBox3TestCase() {
super("src/test/resources/blackbox/qrcode-3", new MultiFormatReader(), BarcodeFormat.QR_CODE);
addTest(38, 38, 0.0f);
addTest(38, 39, 90.0f);
addTest(36, 38, 180.0f);
addTest(38, 38, 90.0f);
addTest(36, 36, 180.0f);
addTest(39, 39, 270.0f);
}

View file

@ -31,8 +31,8 @@ public final class QRCodeBlackBox4TestCase extends AbstractBlackBoxTestCase {
super("src/test/resources/blackbox/qrcode-4", new MultiFormatReader(), BarcodeFormat.QR_CODE);
addTest(36, 36, 0.0f);
addTest(35, 35, 90.0f);
addTest(35, 36, 180.0f);
addTest(35, 36, 270.0f);
addTest(35, 35, 180.0f);
addTest(35, 35, 270.0f);
}
}

View file

@ -34,7 +34,7 @@ public final class QRCodeBlackBox5TestCase extends AbstractBlackBoxTestCase {
addTest(19, 19, 0.0f);
addTest(19, 19, 90.0f);
addTest(19, 19, 180.0f);
addTest(18, 19, 270.0f);
addTest(18, 18, 270.0f);
}
}

View file

@ -29,9 +29,9 @@ public final class QRCodeBlackBox6TestCase extends AbstractBlackBoxTestCase {
public QRCodeBlackBox6TestCase() {
super("src/test/resources/blackbox/qrcode-6", new MultiFormatReader(), BarcodeFormat.QR_CODE);
addTest(15, 15, 0.0f);
addTest(14, 15, 90.0f);
addTest(12, 15, 180.0f);
addTest(14, 15, 270.0f);
addTest(14, 14, 90.0f);
addTest(12, 13, 180.0f);
addTest(14, 14, 270.0f);
}
}