diff --git a/core/src/com/google/zxing/qrcode/encoder/MaskUtil.java b/core/src/com/google/zxing/qrcode/encoder/MaskUtil.java index 9a4a7f111..4b2696361 100644 --- a/core/src/com/google/zxing/qrcode/encoder/MaskUtil.java +++ b/core/src/com/google/zxing/qrcode/encoder/MaskUtil.java @@ -63,61 +63,61 @@ final class MaskUtil { } /** - * Apply mask penalty rule 3 and return the penalty. Find consecutive cells of 00001011101 or - * 10111010000, and give penalty to them. If we find patterns like 000010111010000, we give - * penalties twice (i.e. 40 * 2). + * Apply mask penalty rule 3 and return the penalty. Find consecutive runs of 1:1:3:1:1:4 + * starting with black, or 4:1:1:3:1:1 starting with white, and give penalty to them. If we + * find patterns like 000010111010000, we give penalty once. */ static int applyMaskPenaltyRule3(ByteMatrix matrix) { - int penalty = 0; + int numPenalties = 0; byte[][] array = matrix.getArray(); int width = matrix.getWidth(); int height = matrix.getHeight(); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { - // Tried to simplify following conditions but failed. - if (x + 6 < width && - array[y][x] == 1 && - array[y][x + 1] == 0 && - array[y][x + 2] == 1 && - array[y][x + 3] == 1 && - array[y][x + 4] == 1 && - array[y][x + 5] == 0 && - array[y][x + 6] == 1 && - ((x + 10 < width && - array[y][x + 7] == 0 && - array[y][x + 8] == 0 && - array[y][x + 9] == 0 && - array[y][x + 10] == 0) || - (x - 4 >= 0 && - array[y][x - 1] == 0 && - array[y][x - 2] == 0 && - array[y][x - 3] == 0 && - array[y][x - 4] == 0))) { - penalty += N3; + byte[] arrayY = array[y]; // We can at least optimize this access + if (x + 8 < width && + arrayY[x] == 0 && + arrayY[x + 1] == 1 && + arrayY[x + 2] == 0 && + arrayY[x + 3] == 1 && + arrayY[x + 4] == 1 && + arrayY[x + 5] == 1 && + arrayY[x + 6] == 0 && + arrayY[x + 7] == 1 && + arrayY[x + 8] == 0 && + ((x + 11 < width && + arrayY[x + 9] == 0 && + arrayY[x + 10] == 0 && + arrayY[x + 11] == 0) || + (x - 3 >= 0 && + arrayY[x - 1] == 0 && + arrayY[x - 2] == 0 && + arrayY[x - 3] == 0))) { + numPenalties++; } - if (y + 6 < height && - array[y][x] == 1 && - array[y + 1][x] == 0 && - array[y + 2][x] == 1 && - array[y + 3][x] == 1 && - array[y + 4][x] == 1 && - array[y + 5][x] == 0 && - array[y + 6][x] == 1 && - ((y + 10 < height && - array[y + 7][x] == 0 && - array[y + 8][x] == 0 && + if (y + 8 < height && + array[y][x] == 0 && + array[y + 1][x] == 1 && + array[y + 2][x] == 0 && + array[y + 3][x] == 1 && + array[y + 4][x] == 1 && + array[y + 5][x] == 1 && + array[y + 6][x] == 0 && + array[y + 7][x] == 1 && + array[y + 8][x] == 0 && + ((y + 11 < height && array[y + 9][x] == 0 && - array[y + 10][x] == 0) || - (y - 4 >= 0 && + array[y + 10][x] == 0 && + array[y + 11][x] == 0) || + (y - 3 >= 0 && array[y - 1][x] == 0 && array[y - 2][x] == 0 && - array[y - 3][x] == 0 && - array[y - 4][x] == 0))) { - penalty += N3; + array[y - 3][x] == 0))) { + numPenalties++; } } } - return penalty; + return numPenalties * N3; } /** @@ -138,8 +138,7 @@ final class MaskUtil { } } int numTotalCells = matrix.getHeight() * matrix.getWidth(); - double darkRatio = (double) numDarkCells / numTotalCells; - int fivePercentVariances = (int) (Math.abs(darkRatio - 0.5) * 20.0); // * 100.0 / 5.0 + int fivePercentVariances = Math.abs(numDarkCells * 2 - numTotalCells) * 10 / numTotalCells; return fivePercentVariances * N4; } diff --git a/core/test/data/golden/qrcode/renderer-test-02.png b/core/test/data/golden/qrcode/renderer-test-02.png deleted file mode 100644 index 5fd25040b..000000000 Binary files a/core/test/data/golden/qrcode/renderer-test-02.png and /dev/null differ diff --git a/core/test/data/golden/qrcode/renderer-test-03.png b/core/test/data/golden/qrcode/renderer-test-03.png deleted file mode 100644 index 884024d6d..000000000 Binary files a/core/test/data/golden/qrcode/renderer-test-03.png and /dev/null differ diff --git a/core/test/src/com/google/zxing/qrcode/QRCodeWriterTestCase.java b/core/test/src/com/google/zxing/qrcode/QRCodeWriterTestCase.java index a5d9739ce..146025c7b 100644 --- a/core/test/src/com/google/zxing/qrcode/QRCodeWriterTestCase.java +++ b/core/test/src/com/google/zxing/qrcode/QRCodeWriterTestCase.java @@ -128,18 +128,6 @@ public final class QRCodeWriterTestCase extends Assert { public void testRegressionTest() throws Exception { compareToGoldenFile("http://www.google.com/", ErrorCorrectionLevel.M, 99, "renderer-test-01.png"); - - compareToGoldenFile("12345", ErrorCorrectionLevel.L, 58, "renderer-test-02.png"); - - // Test in Katakana in Shift_JIS. - // TODO: this test is bogus now that byte mode has been basically fixed to assuming ISO-8859-1 encoding - // The real solution is to implement Kanji mode, in which case the golden file will be wrong again - /* - compareToGoldenFile( - new String(new byte[] {(byte)0x83, 0x65, (byte)0x83, 0x58, (byte)0x83, 0x67}, "Shift_JIS"), - ErrorCorrectionLevel.H, 145, - "renderer-test-03.png"); - */ } } diff --git a/core/test/src/com/google/zxing/qrcode/encoder/EncoderTestCase.java b/core/test/src/com/google/zxing/qrcode/encoder/EncoderTestCase.java index fe3d134eb..04367ffdc 100644 --- a/core/test/src/com/google/zxing/qrcode/encoder/EncoderTestCase.java +++ b/core/test/src/com/google/zxing/qrcode/encoder/EncoderTestCase.java @@ -137,29 +137,29 @@ public final class EncoderTestCase extends Assert { " mode: BYTE\n" + " ecLevel: H\n" + " version: 1\n" + - " maskPattern: 3\n" + + " maskPattern: 0\n" + " matrix:\n" + - " 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1\n" + - " 1 0 0 0 0 0 1 0 0 0 1 0 1 0 1 0 0 0 0 0 1\n" + - " 1 0 1 1 1 0 1 0 0 1 0 1 0 0 1 0 1 1 1 0 1\n" + - " 1 0 1 1 1 0 1 0 0 1 1 0 1 0 1 0 1 1 1 0 1\n" + - " 1 0 1 1 1 0 1 0 1 0 1 0 1 0 1 0 1 1 1 0 1\n" + - " 1 0 0 0 0 0 1 0 0 0 0 0 1 0 1 0 0 0 0 0 1\n" + + " 1 1 1 1 1 1 1 0 1 1 1 0 0 0 1 1 1 1 1 1 1\n" + + " 1 0 0 0 0 0 1 0 0 1 1 0 1 0 1 0 0 0 0 0 1\n" + + " 1 0 1 1 1 0 1 0 0 1 0 1 1 0 1 0 1 1 1 0 1\n" + + " 1 0 1 1 1 0 1 0 1 1 1 1 0 0 1 0 1 1 1 0 1\n" + + " 1 0 1 1 1 0 1 0 0 0 0 1 0 0 1 0 1 1 1 0 1\n" + + " 1 0 0 0 0 0 1 0 0 1 1 1 1 0 1 0 0 0 0 0 1\n" + " 1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1\n" + - " 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0\n" + - " 0 0 1 1 0 0 1 1 1 1 0 0 0 1 1 0 1 0 0 0 0\n" + - " 0 0 1 1 1 0 0 0 0 0 1 1 0 0 0 1 0 1 1 1 0\n" + - " 0 1 0 1 0 1 1 1 0 1 0 1 0 0 0 0 0 1 1 1 1\n" + - " 1 1 0 0 1 0 0 1 1 0 0 1 1 1 1 0 1 0 1 1 0\n" + - " 0 0 0 0 1 0 1 1 1 1 0 0 0 0 0 1 0 0 1 0 0\n" + - " 0 0 0 0 0 0 0 0 1 1 1 1 0 0 1 1 1 0 0 0 1\n" + - " 1 1 1 1 1 1 1 0 1 1 1 0 1 0 1 1 0 0 1 0 0\n" + - " 1 0 0 0 0 0 1 0 0 0 1 0 0 1 1 1 1 1 1 0 1\n" + - " 1 0 1 1 1 0 1 0 0 1 0 0 0 0 1 1 0 0 0 0 0\n" + - " 1 0 1 1 1 0 1 0 1 1 1 0 1 0 0 0 1 1 0 0 0\n" + - " 1 0 1 1 1 0 1 0 1 1 0 0 0 1 0 0 1 0 0 0 0\n" + - " 1 0 0 0 0 0 1 0 0 0 0 1 1 0 1 0 1 0 1 1 0\n" + - " 1 1 1 1 1 1 1 0 0 1 0 1 1 1 0 1 1 0 0 0 0\n" + + " 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0\n" + + " 0 0 1 0 1 1 1 0 1 1 0 0 1 1 0 0 0 1 0 0 1\n" + + " 1 1 1 1 1 1 0 1 0 0 1 0 1 1 0 1 0 0 0 0 0\n" + + " 1 1 0 1 1 0 1 1 0 1 1 0 1 0 0 0 1 0 0 1 1\n" + + " 1 1 0 1 0 1 0 1 1 1 1 0 1 1 1 1 0 1 1 1 0\n" + + " 0 0 1 1 0 0 1 1 0 0 1 0 0 0 1 0 1 0 1 0 1\n" + + " 0 0 0 0 0 0 0 0 1 0 1 1 0 1 0 0 1 0 0 1 0\n" + + " 1 1 1 1 1 1 1 0 0 1 1 0 0 1 0 1 0 0 0 1 1\n" + + " 1 0 0 0 0 0 1 0 1 0 1 1 1 0 1 1 1 0 0 1 1\n" + + " 1 0 1 1 1 0 1 0 1 1 1 1 1 0 1 1 1 1 1 0 0\n" + + " 1 0 1 1 1 0 1 0 0 0 0 1 1 0 0 1 0 0 0 0 0\n" + + " 1 0 1 1 1 0 1 0 1 0 1 0 0 1 1 1 0 0 0 0 1\n" + + " 1 0 0 0 0 0 1 0 0 1 0 1 1 1 0 1 1 0 1 0 1\n" + + " 1 1 1 1 1 1 1 0 0 1 0 1 0 0 1 1 1 0 1 1 1\n" + ">>\n"; assertEquals(expected, qrCode.toString()); } diff --git a/core/test/src/com/google/zxing/qrcode/encoder/MaskUtilTestCase.java b/core/test/src/com/google/zxing/qrcode/encoder/MaskUtilTestCase.java index e35034304..7af8abd99 100644 --- a/core/test/src/com/google/zxing/qrcode/encoder/MaskUtilTestCase.java +++ b/core/test/src/com/google/zxing/qrcode/encoder/MaskUtilTestCase.java @@ -91,7 +91,7 @@ public final class MaskUtilTestCase extends Assert { @Test public void testApplyMaskPenaltyRule3() { // Horizontal 00001011101. - ByteMatrix matrix = new ByteMatrix(11, 1); + ByteMatrix matrix = new ByteMatrix(12, 1); matrix.set(0, 0, 0); matrix.set(1, 0, 0); matrix.set(2, 0, 0); @@ -103,23 +103,25 @@ public final class MaskUtilTestCase extends Assert { matrix.set(8, 0, 1); matrix.set(9, 0, 0); matrix.set(10, 0, 1); + matrix.set(11, 0, 0); assertEquals(40, MaskUtil.applyMaskPenaltyRule3(matrix)); // Horizontal 10111010000. - matrix = new ByteMatrix(11, 1); - matrix.set(0, 0, 1); - matrix.set(1, 0, 0); - matrix.set(2, 0, 1); + matrix = new ByteMatrix(12, 1); + matrix.set(0, 0, 0); + matrix.set(1, 0, 1); + matrix.set(2, 0, 0); matrix.set(3, 0, 1); matrix.set(4, 0, 1); - matrix.set(5, 0, 0); - matrix.set(6, 0, 1); - matrix.set(7, 0, 0); + matrix.set(5, 0, 1); + matrix.set(6, 0, 0); + matrix.set(7, 0, 1); matrix.set(8, 0, 0); matrix.set(9, 0, 0); matrix.set(10, 0, 0); + matrix.set(11, 0, 0); assertEquals(40, MaskUtil.applyMaskPenaltyRule3(matrix)); // Vertical 00001011101. - matrix = new ByteMatrix(1, 11); + matrix = new ByteMatrix(1, 12); matrix.set(0, 0, 0); matrix.set(0, 1, 0); matrix.set(0, 2, 0); @@ -131,20 +133,22 @@ public final class MaskUtilTestCase extends Assert { matrix.set(0, 8, 1); matrix.set(0, 9, 0); matrix.set(0, 10, 1); + matrix.set(0, 11, 0); assertEquals(40, MaskUtil.applyMaskPenaltyRule3(matrix)); // Vertical 10111010000. - matrix = new ByteMatrix(1, 11); - matrix.set(0, 0, 1); - matrix.set(0, 1, 0); - matrix.set(0, 2, 1); + matrix = new ByteMatrix(1, 12); + matrix.set(0, 0, 0); + matrix.set(0, 1, 1); + matrix.set(0, 2, 0); matrix.set(0, 3, 1); matrix.set(0, 4, 1); - matrix.set(0, 5, 0); - matrix.set(0, 6, 1); - matrix.set(0, 7, 0); + matrix.set(0, 5, 1); + matrix.set(0, 6, 0); + matrix.set(0, 7, 1); matrix.set(0, 8, 0); matrix.set(0, 9, 0); matrix.set(0, 10, 0); + matrix.set(0, 11, 0); assertEquals(40, MaskUtil.applyMaskPenaltyRule3(matrix)); }