diff --git a/core/src/main/java/com/google/zxing/DecodeHintType.java b/core/src/main/java/com/google/zxing/DecodeHintType.java
index 11f579e62..a53275003 100644
--- a/core/src/main/java/com/google/zxing/DecodeHintType.java
+++ b/core/src/main/java/com/google/zxing/DecodeHintType.java
@@ -98,6 +98,12 @@ public enum DecodeHintType {
*/
ALLOWED_EAN_EXTENSIONS(int[].class),
+ /**
+ * If true, also tries to decode as inverted image. All configured decoders are simply called a
+ * second time with an inverted image. Doesn't matter what it maps to; use {@link Boolean#TRUE}.
+ */
+ ALSO_INVERTED(Void.class),
+
// End of enumeration values.
;
diff --git a/core/src/main/java/com/google/zxing/MultiFormatReader.java b/core/src/main/java/com/google/zxing/MultiFormatReader.java
index 44cef6d17..c7a566f40 100644
--- a/core/src/main/java/com/google/zxing/MultiFormatReader.java
+++ b/core/src/main/java/com/google/zxing/MultiFormatReader.java
@@ -175,6 +175,17 @@ public final class MultiFormatReader implements Reader {
// continue
}
}
+ if (hints != null && hints.containsKey(DecodeHintType.ALSO_INVERTED)) {
+ // Calling all readers again with inverted image
+ image.getBlackMatrix().flip();
+ for (Reader reader : readers) {
+ try {
+ return reader.decode(image, hints);
+ } catch (ReaderException re) {
+ // continue
+ }
+ }
+ }
}
throw NotFoundException.getNotFoundInstance();
}
diff --git a/core/src/main/java/com/google/zxing/common/BitMatrix.java b/core/src/main/java/com/google/zxing/common/BitMatrix.java
index 6eea3b618..7438306f6 100755
--- a/core/src/main/java/com/google/zxing/common/BitMatrix.java
+++ b/core/src/main/java/com/google/zxing/common/BitMatrix.java
@@ -189,6 +189,16 @@ public final class BitMatrix implements Cloneable {
bits[offset] ^= 1 << (x & 0x1f);
}
+ /**
+ *
Flips every bit in the matrix.
+ */
+ public void flip() {
+ int max = bits.length;
+ for (int i = 0; i < max; i++) {
+ bits[i] = ~bits[i];
+ }
+ }
+
/**
* Exclusive-or (XOR): Flip the bit in this {@code BitMatrix} if the corresponding
* mask bit is set.
diff --git a/core/src/test/java/com/google/zxing/common/AbstractBlackBoxTestCase.java b/core/src/test/java/com/google/zxing/common/AbstractBlackBoxTestCase.java
index cc2374371..f295f31dc 100644
--- a/core/src/test/java/com/google/zxing/common/AbstractBlackBoxTestCase.java
+++ b/core/src/test/java/com/google/zxing/common/AbstractBlackBoxTestCase.java
@@ -62,6 +62,7 @@ public abstract class AbstractBlackBoxTestCase extends Assert {
private final Reader barcodeReader;
private final BarcodeFormat expectedFormat;
private final List testResults;
+ private final EnumMap hints = new EnumMap<>(DecodeHintType.class);
public static Path buildTestBase(String testBasePathSuffix) {
// A little workaround to prevent aggravation in my IDE
@@ -92,6 +93,10 @@ public abstract class AbstractBlackBoxTestCase extends Assert {
addTest(mustPassCount, tryHarderCount, 0, 0, rotation);
}
+ protected void addHint(DecodeHintType hint) {
+ hints.put(hint, Boolean.TRUE);
+ }
+
/**
* Adds a new test for the current directory of images.
*
@@ -252,7 +257,7 @@ public abstract class AbstractBlackBoxTestCase extends Assert {
String suffix = String.format(" (%srotation: %d)", tryHarder ? "try harder, " : "", (int) rotation);
- Map hints = new EnumMap<>(DecodeHintType.class);
+ Map hints = this.hints.clone();
if (tryHarder) {
hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
}
diff --git a/core/src/test/java/com/google/zxing/inverted/InvertedDataMatrixBlackBoxTestCase.java b/core/src/test/java/com/google/zxing/inverted/InvertedDataMatrixBlackBoxTestCase.java
new file mode 100644
index 000000000..c2c942e44
--- /dev/null
+++ b/core/src/test/java/com/google/zxing/inverted/InvertedDataMatrixBlackBoxTestCase.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2008 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.inverted;
+
+import com.google.zxing.BarcodeFormat;
+import com.google.zxing.DecodeHintType;
+import com.google.zxing.MultiFormatReader;
+import com.google.zxing.common.AbstractBlackBoxTestCase;
+
+/**
+ * Inverted barcodes
+ */
+public final class InvertedDataMatrixBlackBoxTestCase extends AbstractBlackBoxTestCase {
+
+ public InvertedDataMatrixBlackBoxTestCase() {
+ super("src/test/resources/blackbox/inverted", new MultiFormatReader(), BarcodeFormat.DATA_MATRIX);
+ addHint(DecodeHintType.ALSO_INVERTED);
+ addTest(1, 1, 0.0f);
+ addTest(1, 1, 90.0f);
+ addTest(1, 1, 180.0f);
+ addTest(1, 1, 270.0f);
+ }
+
+}
diff --git a/core/src/test/java/com/google/zxing/inverted/NoHintInvertedDataMatrixBlackBoxTestCase.java b/core/src/test/java/com/google/zxing/inverted/NoHintInvertedDataMatrixBlackBoxTestCase.java
new file mode 100644
index 000000000..ca3a6b2c2
--- /dev/null
+++ b/core/src/test/java/com/google/zxing/inverted/NoHintInvertedDataMatrixBlackBoxTestCase.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2008 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.inverted;
+
+import com.google.zxing.common.AbstractNegativeBlackBoxTestCase;
+
+/**
+ * Without hint inverted barcodes should not be found.
+ */
+public final class NoHintInvertedDataMatrixBlackBoxTestCase extends AbstractNegativeBlackBoxTestCase {
+
+ public NoHintInvertedDataMatrixBlackBoxTestCase() {
+ super("src/test/resources/blackbox/inverted");
+ addTest(0, 0.0f);
+ addTest(0, 90.0f);
+ addTest(0, 180.0f);
+ addTest(0, 270.0f);
+ }
+
+}
diff --git a/core/src/test/resources/blackbox/inverted/datamatrix-0123456789.png b/core/src/test/resources/blackbox/inverted/datamatrix-0123456789.png
new file mode 100644
index 000000000..72e7de88e
Binary files /dev/null and b/core/src/test/resources/blackbox/inverted/datamatrix-0123456789.png differ
diff --git a/core/src/test/resources/blackbox/inverted/datamatrix-0123456789.txt b/core/src/test/resources/blackbox/inverted/datamatrix-0123456789.txt
new file mode 100644
index 000000000..ad471007b
--- /dev/null
+++ b/core/src/test/resources/blackbox/inverted/datamatrix-0123456789.txt
@@ -0,0 +1 @@
+0123456789
\ No newline at end of file