mirror of
https://github.com/starovoid/rxing.git
synced 2026-07-26 04:12:34 +00:00
housekeeping for tests for qrcode and aztec
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
pub mod aztec;
|
||||
pub mod qrcode;
|
||||
pub mod client;
|
||||
pub mod common;
|
||||
mod exceptions;
|
||||
|
||||
136
src/qrcode/QRCodeWriterTestCase.java
Normal file
136
src/qrcode/QRCodeWriterTestCase.java
Normal file
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* 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.qrcode;
|
||||
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
import com.google.zxing.EncodeHintType;
|
||||
import com.google.zxing.Writer;
|
||||
import com.google.zxing.WriterException;
|
||||
import com.google.zxing.common.BitMatrix;
|
||||
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.EnumMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author satorux@google.com (Satoru Takabayashi) - creator
|
||||
* @author dswitkin@google.com (Daniel Switkin) - ported and expanded from C++
|
||||
*/
|
||||
public final class QRCodeWriterTestCase extends Assert {
|
||||
|
||||
private static final Path BASE_IMAGE_PATH = Paths.get("src/test/resources/golden/qrcode/");
|
||||
|
||||
private static BufferedImage loadImage(String fileName) throws IOException {
|
||||
Path file = BASE_IMAGE_PATH.resolve(fileName);
|
||||
if (!Files.exists(file)) {
|
||||
// try starting with 'core' since the test base is often given as the project root
|
||||
file = Paths.get("core/").resolve(BASE_IMAGE_PATH).resolve(fileName);
|
||||
}
|
||||
assertTrue("Please download and install test images, and run from the 'core' directory", Files.exists(file));
|
||||
return ImageIO.read(file.toFile());
|
||||
}
|
||||
|
||||
// In case the golden images are not monochromatic, convert the RGB values to greyscale.
|
||||
private static BitMatrix createMatrixFromImage(BufferedImage image) {
|
||||
int width = image.getWidth();
|
||||
int height = image.getHeight();
|
||||
int[] pixels = new int[width * height];
|
||||
image.getRGB(0, 0, width, height, pixels, 0, width);
|
||||
|
||||
BitMatrix matrix = new BitMatrix(width, height);
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
int pixel = pixels[y * width + x];
|
||||
int luminance = (306 * ((pixel >> 16) & 0xFF) +
|
||||
601 * ((pixel >> 8) & 0xFF) +
|
||||
117 * (pixel & 0xFF)) >> 10;
|
||||
if (luminance <= 0x7F) {
|
||||
matrix.set(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
return matrix;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQRCodeWriter() throws WriterException {
|
||||
// The QR should be multiplied up to fit, with extra padding if necessary
|
||||
int bigEnough = 256;
|
||||
Writer writer = new QRCodeWriter();
|
||||
BitMatrix matrix = writer.encode("http://www.google.com/", BarcodeFormat.QR_CODE, bigEnough,
|
||||
bigEnough, null);
|
||||
assertNotNull(matrix);
|
||||
assertEquals(bigEnough, matrix.getWidth());
|
||||
assertEquals(bigEnough, matrix.getHeight());
|
||||
|
||||
// The QR will not fit in this size, so the matrix should come back bigger
|
||||
int tooSmall = 20;
|
||||
matrix = writer.encode("http://www.google.com/", BarcodeFormat.QR_CODE, tooSmall,
|
||||
tooSmall, null);
|
||||
assertNotNull(matrix);
|
||||
assertTrue(tooSmall < matrix.getWidth());
|
||||
assertTrue(tooSmall < matrix.getHeight());
|
||||
|
||||
// We should also be able to handle non-square requests by padding them
|
||||
int strangeWidth = 500;
|
||||
int strangeHeight = 100;
|
||||
matrix = writer.encode("http://www.google.com/", BarcodeFormat.QR_CODE, strangeWidth,
|
||||
strangeHeight, null);
|
||||
assertNotNull(matrix);
|
||||
assertEquals(strangeWidth, matrix.getWidth());
|
||||
assertEquals(strangeHeight, matrix.getHeight());
|
||||
}
|
||||
|
||||
private static void compareToGoldenFile(String contents,
|
||||
ErrorCorrectionLevel ecLevel,
|
||||
int resolution,
|
||||
String fileName) throws WriterException, IOException {
|
||||
|
||||
BufferedImage image = loadImage(fileName);
|
||||
assertNotNull(image);
|
||||
BitMatrix goldenRXingResult = createMatrixFromImage(image);
|
||||
assertNotNull(goldenRXingResult);
|
||||
|
||||
Map<EncodeHintType,Object> hints = new EnumMap<>(EncodeHintType.class);
|
||||
hints.put(EncodeHintType.ERROR_CORRECTION, ecLevel);
|
||||
Writer writer = new QRCodeWriter();
|
||||
BitMatrix generatedRXingResult = writer.encode(contents, BarcodeFormat.QR_CODE, resolution,
|
||||
resolution, hints);
|
||||
|
||||
assertEquals(resolution, generatedRXingResult.getWidth());
|
||||
assertEquals(resolution, generatedRXingResult.getHeight());
|
||||
assertEquals(goldenRXingResult, generatedRXingResult);
|
||||
}
|
||||
|
||||
// Golden images are generated with "qrcode_sample.cc". The images are checked with both eye balls
|
||||
// and cell phones. We expect pixel-perfect results, because the error correction level is known,
|
||||
// and the pixel dimensions matches exactly.
|
||||
@Test
|
||||
public void testRegressionTest() throws Exception {
|
||||
compareToGoldenFile("http://www.google.com/", ErrorCorrectionLevel.M, 99,
|
||||
"renderer-test-01.png");
|
||||
}
|
||||
|
||||
}
|
||||
94
src/qrcode/decoder/DataMaskTestCase.java
Normal file
94
src/qrcode/decoder/DataMaskTestCase.java
Normal file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright 2007 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.qrcode.decoder;
|
||||
|
||||
import com.google.zxing.common.BitMatrix;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author Sean Owen
|
||||
*/
|
||||
public final class DataMaskTestCase extends Assert {
|
||||
|
||||
@Test
|
||||
public void testMask0() {
|
||||
testMaskAcrossDimensions(0, (i, j) -> (i + j) % 2 == 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMask1() {
|
||||
testMaskAcrossDimensions(1, (i, j) -> i % 2 == 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMask2() {
|
||||
testMaskAcrossDimensions(2, (i, j) -> j % 3 == 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMask3() {
|
||||
testMaskAcrossDimensions(3, (i, j) -> (i + j) % 3 == 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMask4() {
|
||||
testMaskAcrossDimensions(4, (i, j) -> (i / 2 + j / 3) % 2 == 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMask5() {
|
||||
testMaskAcrossDimensions(5, (i, j) -> (i * j) % 2 + (i * j) % 3 == 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMask6() {
|
||||
testMaskAcrossDimensions(6, (i, j) -> ((i * j) % 2 + (i * j) % 3) % 2 == 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMask7() {
|
||||
testMaskAcrossDimensions(7, (i, j) -> ((i + j) % 2 + (i * j) % 3) % 2 == 0);
|
||||
}
|
||||
|
||||
private static void testMaskAcrossDimensions(int reference, MaskCondition condition) {
|
||||
DataMask mask = DataMask.values()[reference];
|
||||
for (int version = 1; version <= 40; version++) {
|
||||
int dimension = 17 + 4 * version;
|
||||
testMask(mask, dimension, condition);
|
||||
}
|
||||
}
|
||||
|
||||
private static void testMask(DataMask mask, int dimension, MaskCondition condition) {
|
||||
BitMatrix bits = new BitMatrix(dimension);
|
||||
mask.unmaskBitMatrix(bits, dimension);
|
||||
for (int i = 0; i < dimension; i++) {
|
||||
for (int j = 0; j < dimension; j++) {
|
||||
assertEquals(
|
||||
"(" + i + ',' + j + ')',
|
||||
condition.isMasked(i, j),
|
||||
bits.get(j, i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
private interface MaskCondition {
|
||||
boolean isMasked(int i, int j);
|
||||
}
|
||||
|
||||
}
|
||||
99
src/qrcode/decoder/DecodedBitStreamParserTestCase.java
Normal file
99
src/qrcode/decoder/DecodedBitStreamParserTestCase.java
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* 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.qrcode.decoder;
|
||||
|
||||
import com.google.zxing.common.BitSourceBuilder;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Tests {@link DecodedBitStreamParser}.
|
||||
*
|
||||
* @author Sean Owen
|
||||
*/
|
||||
public final class DecodedBitStreamParserTestCase extends Assert {
|
||||
|
||||
@Test
|
||||
public void testSimpleByteMode() throws Exception {
|
||||
BitSourceBuilder builder = new BitSourceBuilder();
|
||||
builder.write(0x04, 4); // Byte mode
|
||||
builder.write(0x03, 8); // 3 bytes
|
||||
builder.write(0xF1, 8);
|
||||
builder.write(0xF2, 8);
|
||||
builder.write(0xF3, 8);
|
||||
String result = DecodedBitStreamParser.decode(builder.toByteArray(),
|
||||
Version.getVersionForNumber(1), null, null).getText();
|
||||
assertEquals("\u00f1\u00f2\u00f3", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleSJIS() throws Exception {
|
||||
BitSourceBuilder builder = new BitSourceBuilder();
|
||||
builder.write(0x04, 4); // Byte mode
|
||||
builder.write(0x04, 8); // 4 bytes
|
||||
builder.write(0xA1, 8);
|
||||
builder.write(0xA2, 8);
|
||||
builder.write(0xA3, 8);
|
||||
builder.write(0xD0, 8);
|
||||
String result = DecodedBitStreamParser.decode(builder.toByteArray(),
|
||||
Version.getVersionForNumber(1), null, null).getText();
|
||||
assertEquals("\uff61\uff62\uff63\uff90", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testECI() throws Exception {
|
||||
BitSourceBuilder builder = new BitSourceBuilder();
|
||||
builder.write(0x07, 4); // ECI mode
|
||||
builder.write(0x02, 8); // ECI 2 = CP437 encoding
|
||||
builder.write(0x04, 4); // Byte mode
|
||||
builder.write(0x03, 8); // 3 bytes
|
||||
builder.write(0xA1, 8);
|
||||
builder.write(0xA2, 8);
|
||||
builder.write(0xA3, 8);
|
||||
String result = DecodedBitStreamParser.decode(builder.toByteArray(),
|
||||
Version.getVersionForNumber(1), null, null).getText();
|
||||
assertEquals("\u00ed\u00f3\u00fa", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHanzi() throws Exception {
|
||||
BitSourceBuilder builder = new BitSourceBuilder();
|
||||
builder.write(0x0D, 4); // Hanzi mode
|
||||
builder.write(0x01, 4); // Subset 1 = GB2312 encoding
|
||||
builder.write(0x01, 8); // 1 characters
|
||||
builder.write(0x03C1, 13);
|
||||
String result = DecodedBitStreamParser.decode(builder.toByteArray(),
|
||||
Version.getVersionForNumber(1), null, null).getText();
|
||||
assertEquals("\u963f", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHanziLevel1() throws Exception {
|
||||
BitSourceBuilder builder = new BitSourceBuilder();
|
||||
builder.write(0x0D, 4); // Hanzi mode
|
||||
builder.write(0x01, 4); // Subset 1 = GB2312 encoding
|
||||
builder.write(0x01, 8); // 1 characters
|
||||
// A5A2 (U+30A2) => A5A2 - A1A1 = 401, 4*60 + 01 = 0181
|
||||
builder.write(0x0181, 13);
|
||||
String result = DecodedBitStreamParser.decode(builder.toByteArray(),
|
||||
Version.getVersionForNumber(1), null, null).getText();
|
||||
assertEquals("\u30a2", result);
|
||||
}
|
||||
|
||||
// TODO definitely need more tests here
|
||||
|
||||
}
|
||||
40
src/qrcode/decoder/ErrorCorrectionLevelTestCase.java
Normal file
40
src/qrcode/decoder/ErrorCorrectionLevelTestCase.java
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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.qrcode.decoder;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author Sean Owen
|
||||
*/
|
||||
public final class ErrorCorrectionLevelTestCase extends Assert {
|
||||
|
||||
@Test
|
||||
public void testForBits() {
|
||||
assertSame(ErrorCorrectionLevel.M, ErrorCorrectionLevel.forBits(0));
|
||||
assertSame(ErrorCorrectionLevel.L, ErrorCorrectionLevel.forBits(1));
|
||||
assertSame(ErrorCorrectionLevel.H, ErrorCorrectionLevel.forBits(2));
|
||||
assertSame(ErrorCorrectionLevel.Q, ErrorCorrectionLevel.forBits(3));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testBadECLevel() {
|
||||
ErrorCorrectionLevel.forBits(4);
|
||||
}
|
||||
|
||||
}
|
||||
74
src/qrcode/decoder/FormatInformationTestCase.java
Normal file
74
src/qrcode/decoder/FormatInformationTestCase.java
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2007 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.qrcode.decoder;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author Sean Owen
|
||||
*/
|
||||
public final class FormatInformationTestCase extends Assert {
|
||||
|
||||
private static final int MASKED_TEST_FORMAT_INFO = 0x2BED;
|
||||
private static final int UNMASKED_TEST_FORMAT_INFO = MASKED_TEST_FORMAT_INFO ^ 0x5412;
|
||||
|
||||
@Test
|
||||
public void testBitsDiffering() {
|
||||
assertEquals(0, FormatInformation.numBitsDiffering(1, 1));
|
||||
assertEquals(1, FormatInformation.numBitsDiffering(0, 2));
|
||||
assertEquals(2, FormatInformation.numBitsDiffering(1, 2));
|
||||
assertEquals(32, FormatInformation.numBitsDiffering(-1, 0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDecode() {
|
||||
// Normal case
|
||||
FormatInformation expected =
|
||||
FormatInformation.decodeFormatInformation(MASKED_TEST_FORMAT_INFO, MASKED_TEST_FORMAT_INFO);
|
||||
assertNotNull(expected);
|
||||
assertEquals((byte) 0x07, expected.getDataMask());
|
||||
assertSame(ErrorCorrectionLevel.Q, expected.getErrorCorrectionLevel());
|
||||
// where the code forgot the mask!
|
||||
assertEquals(expected,
|
||||
FormatInformation.decodeFormatInformation(UNMASKED_TEST_FORMAT_INFO, MASKED_TEST_FORMAT_INFO));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDecodeWithBitDifference() {
|
||||
FormatInformation expected =
|
||||
FormatInformation.decodeFormatInformation(MASKED_TEST_FORMAT_INFO, MASKED_TEST_FORMAT_INFO);
|
||||
// 1,2,3,4 bits difference
|
||||
assertEquals(expected, FormatInformation.decodeFormatInformation(
|
||||
MASKED_TEST_FORMAT_INFO ^ 0x01, MASKED_TEST_FORMAT_INFO ^ 0x01));
|
||||
assertEquals(expected, FormatInformation.decodeFormatInformation(
|
||||
MASKED_TEST_FORMAT_INFO ^ 0x03, MASKED_TEST_FORMAT_INFO ^ 0x03));
|
||||
assertEquals(expected, FormatInformation.decodeFormatInformation(
|
||||
MASKED_TEST_FORMAT_INFO ^ 0x07, MASKED_TEST_FORMAT_INFO ^ 0x07));
|
||||
assertNull(FormatInformation.decodeFormatInformation(
|
||||
MASKED_TEST_FORMAT_INFO ^ 0x0F, MASKED_TEST_FORMAT_INFO ^ 0x0F));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDecodeWithMisread() {
|
||||
FormatInformation expected =
|
||||
FormatInformation.decodeFormatInformation(MASKED_TEST_FORMAT_INFO, MASKED_TEST_FORMAT_INFO);
|
||||
assertEquals(expected, FormatInformation.decodeFormatInformation(
|
||||
MASKED_TEST_FORMAT_INFO ^ 0x03, MASKED_TEST_FORMAT_INFO ^ 0x0F));
|
||||
}
|
||||
|
||||
}
|
||||
52
src/qrcode/decoder/ModeTestCase.java
Normal file
52
src/qrcode/decoder/ModeTestCase.java
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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.qrcode.decoder;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author Sean Owen
|
||||
*/
|
||||
public final class ModeTestCase extends Assert {
|
||||
|
||||
@Test
|
||||
public void testForBits() {
|
||||
assertSame(Mode.TERMINATOR, Mode.forBits(0x00));
|
||||
assertSame(Mode.NUMERIC, Mode.forBits(0x01));
|
||||
assertSame(Mode.ALPHANUMERIC, Mode.forBits(0x02));
|
||||
assertSame(Mode.BYTE, Mode.forBits(0x04));
|
||||
assertSame(Mode.KANJI, Mode.forBits(0x08));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testBadMode() {
|
||||
Mode.forBits(0x10);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCharacterCount() {
|
||||
// Spot check a few values
|
||||
assertEquals(10, Mode.NUMERIC.getCharacterCountBits(Version.getVersionForNumber(5)));
|
||||
assertEquals(12, Mode.NUMERIC.getCharacterCountBits(Version.getVersionForNumber(26)));
|
||||
assertEquals(14, Mode.NUMERIC.getCharacterCountBits(Version.getVersionForNumber(40)));
|
||||
assertEquals(9, Mode.ALPHANUMERIC.getCharacterCountBits(Version.getVersionForNumber(6)));
|
||||
assertEquals(8, Mode.BYTE.getCharacterCountBits(Version.getVersionForNumber(7)));
|
||||
assertEquals(8, Mode.KANJI.getCharacterCountBits(Version.getVersionForNumber(8)));
|
||||
}
|
||||
|
||||
}
|
||||
78
src/qrcode/decoder/VersionTestCase.java
Normal file
78
src/qrcode/decoder/VersionTestCase.java
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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.qrcode.decoder;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author Sean Owen
|
||||
*/
|
||||
public final class VersionTestCase extends Assert {
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testBadVersion() {
|
||||
Version.getVersionForNumber(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVersionForNumber() {
|
||||
for (int i = 1; i <= 40; i++) {
|
||||
checkVersion(Version.getVersionForNumber(i), i, 4 * i + 17);
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkVersion(Version version, int number, int dimension) {
|
||||
assertNotNull(version);
|
||||
assertEquals(number, version.getVersionNumber());
|
||||
assertNotNull(version.getAlignmentPatternCenters());
|
||||
if (number > 1) {
|
||||
assertTrue(version.getAlignmentPatternCenters().length > 0);
|
||||
}
|
||||
assertEquals(dimension, version.getDimensionForVersion());
|
||||
assertNotNull(version.getECBlocksForLevel(ErrorCorrectionLevel.H));
|
||||
assertNotNull(version.getECBlocksForLevel(ErrorCorrectionLevel.L));
|
||||
assertNotNull(version.getECBlocksForLevel(ErrorCorrectionLevel.M));
|
||||
assertNotNull(version.getECBlocksForLevel(ErrorCorrectionLevel.Q));
|
||||
assertNotNull(version.buildFunctionPattern());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetProvisionalVersionForDimension() throws Exception {
|
||||
for (int i = 1; i <= 40; i++) {
|
||||
assertEquals(i, Version.getProvisionalVersionForDimension(4 * i + 17).getVersionNumber());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDecodeVersionInformation() {
|
||||
// Spot check
|
||||
doTestVersion(7, 0x07C94);
|
||||
doTestVersion(12, 0x0C762);
|
||||
doTestVersion(17, 0x1145D);
|
||||
doTestVersion(22, 0x168C9);
|
||||
doTestVersion(27, 0x1B08E);
|
||||
doTestVersion(32, 0x209D5);
|
||||
}
|
||||
|
||||
private static void doTestVersion(int expectedVersion, int mask) {
|
||||
Version version = Version.decodeVersionInformation(mask);
|
||||
assertNotNull(version);
|
||||
assertEquals(expectedVersion, version.getVersionNumber());
|
||||
}
|
||||
|
||||
}
|
||||
180
src/qrcode/encoder/BitVectorTestCase.java
Normal file
180
src/qrcode/encoder/BitVectorTestCase.java
Normal file
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
* 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.qrcode.encoder;
|
||||
|
||||
import com.google.zxing.common.BitArray;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author satorux@google.com (Satoru Takabayashi) - creator
|
||||
* @author dswitkin@google.com (Daniel Switkin) - ported from C++
|
||||
*/
|
||||
public final class BitVectorTestCase extends Assert {
|
||||
|
||||
private static long getUnsignedInt(BitArray v) {
|
||||
long result = 0L;
|
||||
for (int i = 0, offset = 0; i < 32; i++) {
|
||||
if (v.get(offset + i)) {
|
||||
result |= 1L << (31 - i);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAppendBit() {
|
||||
BitArray v = new BitArray();
|
||||
assertEquals(0, v.getSizeInBytes());
|
||||
// 1
|
||||
v.appendBit(true);
|
||||
assertEquals(1, v.getSize());
|
||||
assertEquals(0x80000000L, getUnsignedInt(v));
|
||||
// 10
|
||||
v.appendBit(false);
|
||||
assertEquals(2, v.getSize());
|
||||
assertEquals(0x80000000L, getUnsignedInt(v));
|
||||
// 101
|
||||
v.appendBit(true);
|
||||
assertEquals(3, v.getSize());
|
||||
assertEquals(0xa0000000L, getUnsignedInt(v));
|
||||
// 1010
|
||||
v.appendBit(false);
|
||||
assertEquals(4, v.getSize());
|
||||
assertEquals(0xa0000000L, getUnsignedInt(v));
|
||||
// 10101
|
||||
v.appendBit(true);
|
||||
assertEquals(5, v.getSize());
|
||||
assertEquals(0xa8000000L, getUnsignedInt(v));
|
||||
// 101010
|
||||
v.appendBit(false);
|
||||
assertEquals(6, v.getSize());
|
||||
assertEquals(0xa8000000L, getUnsignedInt(v));
|
||||
// 1010101
|
||||
v.appendBit(true);
|
||||
assertEquals(7, v.getSize());
|
||||
assertEquals(0xaa000000L, getUnsignedInt(v));
|
||||
// 10101010
|
||||
v.appendBit(false);
|
||||
assertEquals(8, v.getSize());
|
||||
assertEquals(0xaa000000L, getUnsignedInt(v));
|
||||
// 10101010 1
|
||||
v.appendBit(true);
|
||||
assertEquals(9, v.getSize());
|
||||
assertEquals(0xaa800000L, getUnsignedInt(v));
|
||||
// 10101010 10
|
||||
v.appendBit(false);
|
||||
assertEquals(10, v.getSize());
|
||||
assertEquals(0xaa800000L, getUnsignedInt(v));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAppendBits() {
|
||||
BitArray v = new BitArray();
|
||||
v.appendBits(0x1, 1);
|
||||
assertEquals(1, v.getSize());
|
||||
assertEquals(0x80000000L, getUnsignedInt(v));
|
||||
v = new BitArray();
|
||||
v.appendBits(0xff, 8);
|
||||
assertEquals(8, v.getSize());
|
||||
assertEquals(0xff000000L, getUnsignedInt(v));
|
||||
v = new BitArray();
|
||||
v.appendBits(0xff7, 12);
|
||||
assertEquals(12, v.getSize());
|
||||
assertEquals(0xff700000L, getUnsignedInt(v));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNumBytes() {
|
||||
BitArray v = new BitArray();
|
||||
assertEquals(0, v.getSizeInBytes());
|
||||
v.appendBit(false);
|
||||
// 1 bit was added in the vector, so 1 byte should be consumed.
|
||||
assertEquals(1, v.getSizeInBytes());
|
||||
v.appendBits(0, 7);
|
||||
assertEquals(1, v.getSizeInBytes());
|
||||
v.appendBits(0, 8);
|
||||
assertEquals(2, v.getSizeInBytes());
|
||||
v.appendBits(0, 1);
|
||||
// We now have 17 bits, so 3 bytes should be consumed.
|
||||
assertEquals(3, v.getSizeInBytes());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAppendBitVector() {
|
||||
BitArray v1 = new BitArray();
|
||||
v1.appendBits(0xbe, 8);
|
||||
BitArray v2 = new BitArray();
|
||||
v2.appendBits(0xef, 8);
|
||||
v1.appendBitArray(v2);
|
||||
// beef = 1011 1110 1110 1111
|
||||
assertEquals(" X.XXXXX. XXX.XXXX", v1.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testXOR() {
|
||||
BitArray v1 = new BitArray();
|
||||
v1.appendBits(0x5555aaaa, 32);
|
||||
BitArray v2 = new BitArray();
|
||||
v2.appendBits(0xaaaa5555, 32);
|
||||
v1.xor(v2);
|
||||
assertEquals(0xffffffffL, getUnsignedInt(v1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testXOR2() {
|
||||
BitArray v1 = new BitArray();
|
||||
v1.appendBits(0x2a, 7); // 010 1010
|
||||
BitArray v2 = new BitArray();
|
||||
v2.appendBits(0x55, 7); // 101 0101
|
||||
v1.xor(v2);
|
||||
assertEquals(0xfe000000L, getUnsignedInt(v1)); // 1111 1110
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAt() {
|
||||
BitArray v = new BitArray();
|
||||
v.appendBits(0xdead, 16); // 1101 1110 1010 1101
|
||||
assertTrue(v.get(0));
|
||||
assertTrue(v.get(1));
|
||||
assertFalse(v.get(2));
|
||||
assertTrue(v.get(3));
|
||||
|
||||
assertTrue(v.get(4));
|
||||
assertTrue(v.get(5));
|
||||
assertTrue(v.get(6));
|
||||
assertFalse(v.get(7));
|
||||
|
||||
assertTrue(v.get(8));
|
||||
assertFalse(v.get(9));
|
||||
assertTrue(v.get(10));
|
||||
assertFalse(v.get(11));
|
||||
|
||||
assertTrue(v.get(12));
|
||||
assertTrue(v.get(13));
|
||||
assertFalse(v.get(14));
|
||||
assertTrue(v.get(15));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToString() {
|
||||
BitArray v = new BitArray();
|
||||
v.appendBits(0xdead, 16); // 1101 1110 1010 1101
|
||||
assertEquals(" XX.XXXX. X.X.XX.X", v.toString());
|
||||
}
|
||||
|
||||
}
|
||||
987
src/qrcode/encoder/EncoderTestCase.java
Normal file
987
src/qrcode/encoder/EncoderTestCase.java
Normal file
@@ -0,0 +1,987 @@
|
||||
/*
|
||||
* 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.qrcode.encoder;
|
||||
|
||||
import com.google.zxing.EncodeHintType;
|
||||
import com.google.zxing.WriterException;
|
||||
import com.google.zxing.common.BitArray;
|
||||
import com.google.zxing.common.StringUtils;
|
||||
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
|
||||
import com.google.zxing.qrcode.decoder.Mode;
|
||||
import com.google.zxing.qrcode.decoder.Version;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.EnumMap;
|
||||
import java.util.Map;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/**
|
||||
* @author satorux@google.com (Satoru Takabayashi) - creator
|
||||
* @author mysen@google.com (Chris Mysen) - ported from C++
|
||||
*/
|
||||
public final class EncoderTestCase extends Assert {
|
||||
|
||||
@Test
|
||||
public void testGetAlphanumericCode() {
|
||||
// The first ten code points are numbers.
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
assertEquals(i, Encoder.getAlphanumericCode('0' + i));
|
||||
}
|
||||
|
||||
// The next 26 code points are capital alphabet letters.
|
||||
for (int i = 10; i < 36; ++i) {
|
||||
assertEquals(i, Encoder.getAlphanumericCode('A' + i - 10));
|
||||
}
|
||||
|
||||
// Others are symbol letters
|
||||
assertEquals(36, Encoder.getAlphanumericCode(' '));
|
||||
assertEquals(37, Encoder.getAlphanumericCode('$'));
|
||||
assertEquals(38, Encoder.getAlphanumericCode('%'));
|
||||
assertEquals(39, Encoder.getAlphanumericCode('*'));
|
||||
assertEquals(40, Encoder.getAlphanumericCode('+'));
|
||||
assertEquals(41, Encoder.getAlphanumericCode('-'));
|
||||
assertEquals(42, Encoder.getAlphanumericCode('.'));
|
||||
assertEquals(43, Encoder.getAlphanumericCode('/'));
|
||||
assertEquals(44, Encoder.getAlphanumericCode(':'));
|
||||
|
||||
// Should return -1 for other letters;
|
||||
assertEquals(-1, Encoder.getAlphanumericCode('a'));
|
||||
assertEquals(-1, Encoder.getAlphanumericCode('#'));
|
||||
assertEquals(-1, Encoder.getAlphanumericCode('\0'));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChooseMode() {
|
||||
// Numeric mode.
|
||||
assertSame(Mode.NUMERIC, Encoder.chooseMode("0"));
|
||||
assertSame(Mode.NUMERIC, Encoder.chooseMode("0123456789"));
|
||||
// Alphanumeric mode.
|
||||
assertSame(Mode.ALPHANUMERIC, Encoder.chooseMode("A"));
|
||||
assertSame(Mode.ALPHANUMERIC,
|
||||
Encoder.chooseMode("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:"));
|
||||
// 8-bit byte mode.
|
||||
assertSame(Mode.BYTE, Encoder.chooseMode("a"));
|
||||
assertSame(Mode.BYTE, Encoder.chooseMode("#"));
|
||||
assertSame(Mode.BYTE, Encoder.chooseMode(""));
|
||||
// Kanji mode. We used to use MODE_KANJI for these, but we stopped
|
||||
// doing that as we cannot distinguish Shift_JIS from other encodings
|
||||
// from data bytes alone. See also comments in qrcode_encoder.h.
|
||||
|
||||
// AIUE in Hiragana in Shift_JIS
|
||||
assertSame(Mode.BYTE,
|
||||
Encoder.chooseMode(shiftJISString(bytes(0x8, 0xa, 0x8, 0xa, 0x8, 0xa, 0x8, 0xa6))));
|
||||
|
||||
// Nihon in Kanji in Shift_JIS.
|
||||
assertSame(Mode.BYTE, Encoder.chooseMode(shiftJISString(bytes(0x9, 0xf, 0x9, 0x7b))));
|
||||
|
||||
// Sou-Utsu-Byou in Kanji in Shift_JIS.
|
||||
assertSame(Mode.BYTE, Encoder.chooseMode(shiftJISString(bytes(0xe, 0x4, 0x9, 0x5, 0x9, 0x61))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEncode() throws WriterException {
|
||||
QRCode qrCode = Encoder.encode("ABCDEF", ErrorCorrectionLevel.H);
|
||||
String expected = "<<\n" +
|
||||
" mode: ALPHANUMERIC\n" +
|
||||
" ecLevel: H\n" +
|
||||
" version: 1\n" +
|
||||
" maskPattern: 0\n" +
|
||||
" matrix:\n" +
|
||||
" 1 1 1 1 1 1 1 0 1 1 1 1 0 0 1 1 1 1 1 1 1\n" +
|
||||
" 1 0 0 0 0 0 1 0 0 1 1 1 0 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 0 1 0 1 0 1 1 1 0 1\n" +
|
||||
" 1 0 1 1 1 0 1 0 0 1 1 1 0 0 1 0 1 1 1 0 1\n" +
|
||||
" 1 0 0 0 0 0 1 0 0 1 0 0 0 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 0 0 1 0 1 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 0 1 1 1 0 0 1 0 0 0 1 0 1 0 0 0 0 0 0 0\n" +
|
||||
" 0 0 1 1 0 0 1 0 1 0 0 0 1 0 1 0 1 0 1 1 0\n" +
|
||||
" 1 1 0 1 0 1 0 1 1 1 0 1 0 1 0 0 0 0 0 1 0\n" +
|
||||
" 0 0 1 1 0 1 1 1 1 0 0 0 1 0 1 0 1 1 1 1 0\n" +
|
||||
" 0 0 0 0 0 0 0 0 1 0 0 1 1 1 0 1 0 1 0 0 0\n" +
|
||||
" 1 1 1 1 1 1 1 0 0 0 1 0 1 0 1 1 0 0 0 0 1\n" +
|
||||
" 1 0 0 0 0 0 1 0 1 1 1 1 0 1 0 1 1 1 1 0 1\n" +
|
||||
" 1 0 1 1 1 0 1 0 1 0 1 1 0 1 0 1 0 0 0 0 1\n" +
|
||||
" 1 0 1 1 1 0 1 0 0 1 1 0 1 1 1 1 0 1 0 1 0\n" +
|
||||
" 1 0 1 1 1 0 1 0 1 0 0 0 1 0 1 0 1 1 1 0 1\n" +
|
||||
" 1 0 0 0 0 0 1 0 0 1 1 0 1 1 0 1 0 0 0 1 1\n" +
|
||||
" 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 0 1 0 1\n" +
|
||||
">>\n";
|
||||
assertEquals(expected, qrCode.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEncodeWithVersion() throws WriterException {
|
||||
Map<EncodeHintType, Object> hints = new EnumMap<>(EncodeHintType.class);
|
||||
hints.put(EncodeHintType.QR_VERSION, 7);
|
||||
QRCode qrCode = Encoder.encode("ABCDEF", ErrorCorrectionLevel.H, hints);
|
||||
assertTrue(qrCode.toString().contains(" version: 7\n"));
|
||||
}
|
||||
|
||||
@Test(expected = WriterException.class)
|
||||
public void testEncodeWithVersionTooSmall() throws WriterException {
|
||||
Map<EncodeHintType, Object> hints = new EnumMap<>(EncodeHintType.class);
|
||||
hints.put(EncodeHintType.QR_VERSION, 3);
|
||||
Encoder.encode("THISMESSAGEISTOOLONGFORAQRCODEVERSION3", ErrorCorrectionLevel.H, hints);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleUTF8ECI() throws WriterException {
|
||||
Map<EncodeHintType,Object> hints = new EnumMap<>(EncodeHintType.class);
|
||||
hints.put(EncodeHintType.CHARACTER_SET, "UTF8");
|
||||
QRCode qrCode = Encoder.encode("hello", ErrorCorrectionLevel.H, hints);
|
||||
String expected = "<<\n" +
|
||||
" mode: BYTE\n" +
|
||||
" ecLevel: H\n" +
|
||||
" version: 1\n" +
|
||||
" maskPattern: 3\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 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" +
|
||||
">>\n";
|
||||
assertEquals(expected, qrCode.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEncodeKanjiMode() throws WriterException {
|
||||
Map<EncodeHintType,Object> hints = new EnumMap<>(EncodeHintType.class);
|
||||
hints.put(EncodeHintType.CHARACTER_SET, "Shift_JIS");
|
||||
// Nihon in Kanji
|
||||
QRCode qrCode = Encoder.encode("\u65e5\u672c", ErrorCorrectionLevel.M, hints);
|
||||
String expected = "<<\n" +
|
||||
" mode: KANJI\n" +
|
||||
" ecLevel: M\n" +
|
||||
" version: 1\n" +
|
||||
" maskPattern: 4\n" +
|
||||
" matrix:\n" +
|
||||
" 1 1 1 1 1 1 1 0 1 1 1 1 0 0 1 1 1 1 1 1 1\n" +
|
||||
" 1 0 0 0 0 0 1 0 0 0 0 1 1 0 1 0 0 0 0 0 1\n" +
|
||||
" 1 0 1 1 1 0 1 0 0 0 1 0 0 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 1 1 1 0 1 0 1 1 0 1 1 0 1 0 1 1 1 0 1\n" +
|
||||
" 1 0 0 0 0 0 1 0 1 0 1 0 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 0 0 0 0 0 0 0 0 0 0 0 0\n" +
|
||||
" 1 0 0 0 1 0 1 1 1 0 0 0 1 1 1 1 1 1 0 0 1\n" +
|
||||
" 0 1 1 0 0 1 0 1 1 0 1 0 1 1 1 0 0 0 1 0 1\n" +
|
||||
" 1 1 1 1 0 1 1 1 0 0 1 0 1 1 0 0 0 0 1 1 1\n" +
|
||||
" 1 0 1 0 1 1 0 0 0 0 1 1 1 0 0 1 0 0 1 1 0\n" +
|
||||
" 0 0 1 0 1 1 1 1 1 1 1 1 0 0 1 1 1 1 0 1 1\n" +
|
||||
" 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 1 0 1 0 0 0\n" +
|
||||
" 1 1 1 1 1 1 1 0 1 1 0 1 0 0 1 1 1 1 1 1 0\n" +
|
||||
" 1 0 0 0 0 0 1 0 0 0 0 0 0 1 1 0 1 0 1 0 1\n" +
|
||||
" 1 0 1 1 1 0 1 0 1 0 1 0 1 1 1 0 0 0 1 1 1\n" +
|
||||
" 1 0 1 1 1 0 1 0 0 1 0 0 1 1 1 0 0 0 1 1 1\n" +
|
||||
" 1 0 1 1 1 0 1 0 0 1 1 0 1 1 0 0 0 1 0 0 0\n" +
|
||||
" 1 0 0 0 0 0 1 0 0 0 1 1 1 0 0 1 0 1 0 0 0\n" +
|
||||
" 1 1 1 1 1 1 1 0 1 1 1 1 0 0 1 1 1 0 1 1 0\n" +
|
||||
">>\n";
|
||||
assertEquals(expected, qrCode.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEncodeShiftjisNumeric() throws WriterException {
|
||||
Map<EncodeHintType,Object> hints = new EnumMap<>(EncodeHintType.class);
|
||||
hints.put(EncodeHintType.CHARACTER_SET, "Shift_JIS");
|
||||
QRCode qrCode = Encoder.encode("0123", ErrorCorrectionLevel.M, hints);
|
||||
String expected = "<<\n" +
|
||||
" mode: NUMERIC\n" +
|
||||
" ecLevel: M\n" +
|
||||
" version: 1\n" +
|
||||
" maskPattern: 0\n" +
|
||||
" matrix:\n" +
|
||||
" 1 1 1 1 1 1 1 0 0 0 0 0 1 0 1 1 1 1 1 1 1\n" +
|
||||
" 1 0 0 0 0 0 1 0 1 1 0 1 0 0 1 0 0 0 0 0 1\n" +
|
||||
" 1 0 1 1 1 0 1 0 0 1 1 0 0 0 1 0 1 1 1 0 1\n" +
|
||||
" 1 0 1 1 1 0 1 0 0 0 1 0 0 0 1 0 1 1 1 0 1\n" +
|
||||
" 1 0 1 1 1 0 1 0 1 0 1 1 1 0 1 0 1 1 1 0 1\n" +
|
||||
" 1 0 0 0 0 0 1 0 0 1 0 1 0 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 0 1 1 0 0 0 0 0 0 0 0 0 0\n" +
|
||||
" 1 0 1 0 1 0 1 0 0 0 0 0 1 0 0 0 1 0 0 1 0\n" +
|
||||
" 0 0 0 0 0 0 0 1 1 0 1 1 0 1 0 1 0 1 0 1 0\n" +
|
||||
" 0 1 0 1 0 1 1 1 1 0 0 1 0 1 1 1 0 1 0 1 0\n" +
|
||||
" 0 1 1 1 0 0 0 0 0 0 1 1 1 1 0 1 1 1 0 1 0\n" +
|
||||
" 0 0 0 1 1 1 1 1 1 1 1 1 0 1 1 1 0 0 1 0 1\n" +
|
||||
" 0 0 0 0 0 0 0 0 1 1 0 0 0 0 1 0 0 0 1 1 0\n" +
|
||||
" 1 1 1 1 1 1 1 0 0 1 0 0 1 0 0 0 1 0 0 0 1\n" +
|
||||
" 1 0 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 0 1 0 0\n" +
|
||||
" 1 0 1 1 1 0 1 0 1 1 0 0 1 0 1 0 1 0 1 0 1\n" +
|
||||
" 1 0 1 1 1 0 1 0 0 1 1 1 0 1 0 1 0 1 0 1 0\n" +
|
||||
" 1 0 1 1 1 0 1 0 1 0 1 1 0 1 1 1 0 1 1 0 1\n" +
|
||||
" 1 0 0 0 0 0 1 0 0 0 1 1 1 1 0 1 1 1 0 0 0\n" +
|
||||
" 1 1 1 1 1 1 1 0 1 0 1 1 0 1 1 1 0 1 1 0 1\n" +
|
||||
">>\n";
|
||||
assertEquals(expected, qrCode.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEncodeGS1WithStringTypeHint() throws WriterException {
|
||||
Map<EncodeHintType, Object> hints = new EnumMap<>(EncodeHintType.class);
|
||||
hints.put(EncodeHintType.GS1_FORMAT, "true");
|
||||
QRCode qrCode = Encoder.encode("100001%11171218", ErrorCorrectionLevel.H, hints);
|
||||
verifyGS1EncodedData(qrCode);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEncodeGS1WithBooleanTypeHint() throws WriterException {
|
||||
Map<EncodeHintType, Object> hints = new EnumMap<>(EncodeHintType.class);
|
||||
hints.put(EncodeHintType.GS1_FORMAT, true);
|
||||
QRCode qrCode = Encoder.encode("100001%11171218", ErrorCorrectionLevel.H, hints);
|
||||
verifyGS1EncodedData(qrCode);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDoesNotEncodeGS1WhenBooleanTypeHintExplicitlyFalse() throws WriterException {
|
||||
Map<EncodeHintType, Object> hints = new EnumMap<>(EncodeHintType.class);
|
||||
hints.put(EncodeHintType.GS1_FORMAT, false);
|
||||
QRCode qrCode = Encoder.encode("ABCDEF", ErrorCorrectionLevel.H, hints);
|
||||
verifyNotGS1EncodedData(qrCode);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDoesNotEncodeGS1WhenStringTypeHintExplicitlyFalse() throws WriterException {
|
||||
Map<EncodeHintType, Object> hints = new EnumMap<>(EncodeHintType.class);
|
||||
hints.put(EncodeHintType.GS1_FORMAT, "false");
|
||||
QRCode qrCode = Encoder.encode("ABCDEF", ErrorCorrectionLevel.H, hints);
|
||||
verifyNotGS1EncodedData(qrCode);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGS1ModeHeaderWithECI() throws WriterException {
|
||||
Map<EncodeHintType,Object> hints = new EnumMap<>(EncodeHintType.class);
|
||||
hints.put(EncodeHintType.CHARACTER_SET, "UTF8");
|
||||
hints.put(EncodeHintType.GS1_FORMAT, true);
|
||||
QRCode qrCode = Encoder.encode("hello", ErrorCorrectionLevel.H, hints);
|
||||
String expected = "<<\n" +
|
||||
" mode: BYTE\n" +
|
||||
" ecLevel: H\n" +
|
||||
" version: 1\n" +
|
||||
" maskPattern: 6\n" +
|
||||
" matrix:\n" +
|
||||
" 1 1 1 1 1 1 1 0 0 0 1 1 0 0 1 1 1 1 1 1 1\n" +
|
||||
" 1 0 0 0 0 0 1 0 0 1 1 0 0 0 1 0 0 0 0 0 1\n" +
|
||||
" 1 0 1 1 1 0 1 0 1 1 0 0 0 0 1 0 1 1 1 0 1\n" +
|
||||
" 1 0 1 1 1 0 1 0 1 1 0 1 0 0 1 0 1 1 1 0 1\n" +
|
||||
" 1 0 1 1 1 0 1 0 0 0 1 1 0 0 1 0 1 1 1 0 1\n" +
|
||||
" 1 0 0 0 0 0 1 0 0 1 0 0 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 0 0 1 1 1 0 0 0 0 0 0 0 0\n" +
|
||||
" 0 0 0 1 1 0 1 1 0 1 0 0 0 0 0 0 0 1 1 0 0\n" +
|
||||
" 0 1 0 1 1 0 0 1 0 1 1 1 1 1 1 0 1 1 1 0 1\n" +
|
||||
" 0 1 1 1 1 0 1 0 0 1 0 1 0 1 1 1 0 0 1 0 1\n" +
|
||||
" 1 1 1 1 1 0 0 1 0 0 0 1 1 0 0 1 0 0 1 0 0\n" +
|
||||
" 1 0 0 1 0 0 1 1 0 1 1 0 1 0 1 0 0 1 0 0 1\n" +
|
||||
" 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 1 0 0 0 1\n" +
|
||||
" 1 1 1 1 1 1 1 0 1 0 0 1 0 1 1 0 1 0 1 0 0\n" +
|
||||
" 1 0 0 0 0 0 1 0 0 1 0 0 0 0 1 0 1 1 1 0 0\n" +
|
||||
" 1 0 1 1 1 0 1 0 1 1 0 1 1 0 0 0 1 1 0 0 0\n" +
|
||||
" 1 0 1 1 1 0 1 0 1 0 1 1 1 1 1 0 0 0 1 1 0\n" +
|
||||
" 1 0 1 1 1 0 1 0 0 0 1 0 0 1 0 0 1 0 1 1 1\n" +
|
||||
" 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 1 1 0 0\n" +
|
||||
" 1 1 1 1 1 1 1 0 0 1 0 1 0 0 1 0 0 0 0 0 0\n" +
|
||||
">>\n";
|
||||
assertEquals(expected, qrCode.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAppendModeInfo() {
|
||||
BitArray bits = new BitArray();
|
||||
Encoder.appendModeInfo(Mode.NUMERIC, bits);
|
||||
assertEquals(" ...X", bits.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAppendLengthInfo() throws WriterException {
|
||||
BitArray bits = new BitArray();
|
||||
Encoder.appendLengthInfo(1, // 1 letter (1/1).
|
||||
Version.getVersionForNumber(1),
|
||||
Mode.NUMERIC,
|
||||
bits);
|
||||
assertEquals(" ........ .X", bits.toString()); // 10 bits.
|
||||
bits = new BitArray();
|
||||
Encoder.appendLengthInfo(2, // 2 letters (2/1).
|
||||
Version.getVersionForNumber(10),
|
||||
Mode.ALPHANUMERIC,
|
||||
bits);
|
||||
assertEquals(" ........ .X.", bits.toString()); // 11 bits.
|
||||
bits = new BitArray();
|
||||
Encoder.appendLengthInfo(255, // 255 letter (255/1).
|
||||
Version.getVersionForNumber(27),
|
||||
Mode.BYTE,
|
||||
bits);
|
||||
assertEquals(" ........ XXXXXXXX", bits.toString()); // 16 bits.
|
||||
bits = new BitArray();
|
||||
Encoder.appendLengthInfo(512, // 512 letters (1024/2).
|
||||
Version.getVersionForNumber(40),
|
||||
Mode.KANJI,
|
||||
bits);
|
||||
assertEquals(" ..X..... ....", bits.toString()); // 12 bits.
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAppendBytes() throws WriterException {
|
||||
// Should use appendNumericBytes.
|
||||
// 1 = 01 = 0001 in 4 bits.
|
||||
BitArray bits = new BitArray();
|
||||
Encoder.appendBytes("1", Mode.NUMERIC, bits, Encoder.DEFAULT_BYTE_MODE_ENCODING);
|
||||
assertEquals(" ...X" , bits.toString());
|
||||
// Should use appendAlphanumericBytes.
|
||||
// A = 10 = 0xa = 001010 in 6 bits
|
||||
bits = new BitArray();
|
||||
Encoder.appendBytes("A", Mode.ALPHANUMERIC, bits, Encoder.DEFAULT_BYTE_MODE_ENCODING);
|
||||
assertEquals(" ..X.X." , bits.toString());
|
||||
// Lower letters such as 'a' cannot be encoded in MODE_ALPHANUMERIC.
|
||||
try {
|
||||
Encoder.appendBytes("a", Mode.ALPHANUMERIC, bits, Encoder.DEFAULT_BYTE_MODE_ENCODING);
|
||||
} catch (WriterException we) {
|
||||
// good
|
||||
}
|
||||
// Should use append8BitBytes.
|
||||
// 0x61, 0x62, 0x63
|
||||
bits = new BitArray();
|
||||
Encoder.appendBytes("abc", Mode.BYTE, bits, Encoder.DEFAULT_BYTE_MODE_ENCODING);
|
||||
assertEquals(" .XX....X .XX...X. .XX...XX", bits.toString());
|
||||
// Anything can be encoded in QRCode.MODE_8BIT_BYTE.
|
||||
Encoder.appendBytes("\0", Mode.BYTE, bits, Encoder.DEFAULT_BYTE_MODE_ENCODING);
|
||||
// Should use appendKanjiBytes.
|
||||
// 0x93, 0x5f
|
||||
bits = new BitArray();
|
||||
Encoder.appendBytes(shiftJISString(bytes(0x93, 0x5f)), Mode.KANJI, bits,
|
||||
Encoder.DEFAULT_BYTE_MODE_ENCODING);
|
||||
assertEquals(" .XX.XX.. XXXXX", bits.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTerminateBits() throws WriterException {
|
||||
BitArray v = new BitArray();
|
||||
Encoder.terminateBits(0, v);
|
||||
assertEquals("", v.toString());
|
||||
v = new BitArray();
|
||||
Encoder.terminateBits(1, v);
|
||||
assertEquals(" ........", v.toString());
|
||||
v = new BitArray();
|
||||
v.appendBits(0, 3); // Append 000
|
||||
Encoder.terminateBits(1, v);
|
||||
assertEquals(" ........", v.toString());
|
||||
v = new BitArray();
|
||||
v.appendBits(0, 5); // Append 00000
|
||||
Encoder.terminateBits(1, v);
|
||||
assertEquals(" ........", v.toString());
|
||||
v = new BitArray();
|
||||
v.appendBits(0, 8); // Append 00000000
|
||||
Encoder.terminateBits(1, v);
|
||||
assertEquals(" ........", v.toString());
|
||||
v = new BitArray();
|
||||
Encoder.terminateBits(2, v);
|
||||
assertEquals(" ........ XXX.XX..", v.toString());
|
||||
v = new BitArray();
|
||||
v.appendBits(0, 1); // Append 0
|
||||
Encoder.terminateBits(3, v);
|
||||
assertEquals(" ........ XXX.XX.. ...X...X", v.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetNumDataBytesAndNumECBytesForBlockID() throws WriterException {
|
||||
int[] numDataBytes = new int[1];
|
||||
int[] numEcBytes = new int[1];
|
||||
// Version 1-H.
|
||||
Encoder.getNumDataBytesAndNumECBytesForBlockID(26, 9, 1, 0, numDataBytes, numEcBytes);
|
||||
assertEquals(9, numDataBytes[0]);
|
||||
assertEquals(17, numEcBytes[0]);
|
||||
|
||||
// Version 3-H. 2 blocks.
|
||||
Encoder.getNumDataBytesAndNumECBytesForBlockID(70, 26, 2, 0, numDataBytes, numEcBytes);
|
||||
assertEquals(13, numDataBytes[0]);
|
||||
assertEquals(22, numEcBytes[0]);
|
||||
Encoder.getNumDataBytesAndNumECBytesForBlockID(70, 26, 2, 1, numDataBytes, numEcBytes);
|
||||
assertEquals(13, numDataBytes[0]);
|
||||
assertEquals(22, numEcBytes[0]);
|
||||
|
||||
// Version 7-H. (4 + 1) blocks.
|
||||
Encoder.getNumDataBytesAndNumECBytesForBlockID(196, 66, 5, 0, numDataBytes, numEcBytes);
|
||||
assertEquals(13, numDataBytes[0]);
|
||||
assertEquals(26, numEcBytes[0]);
|
||||
Encoder.getNumDataBytesAndNumECBytesForBlockID(196, 66, 5, 4, numDataBytes, numEcBytes);
|
||||
assertEquals(14, numDataBytes[0]);
|
||||
assertEquals(26, numEcBytes[0]);
|
||||
|
||||
// Version 40-H. (20 + 61) blocks.
|
||||
Encoder.getNumDataBytesAndNumECBytesForBlockID(3706, 1276, 81, 0, numDataBytes, numEcBytes);
|
||||
assertEquals(15, numDataBytes[0]);
|
||||
assertEquals(30, numEcBytes[0]);
|
||||
Encoder.getNumDataBytesAndNumECBytesForBlockID(3706, 1276, 81, 20, numDataBytes, numEcBytes);
|
||||
assertEquals(16, numDataBytes[0]);
|
||||
assertEquals(30, numEcBytes[0]);
|
||||
Encoder.getNumDataBytesAndNumECBytesForBlockID(3706, 1276, 81, 80, numDataBytes, numEcBytes);
|
||||
assertEquals(16, numDataBytes[0]);
|
||||
assertEquals(30, numEcBytes[0]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInterleaveWithECBytes() throws WriterException {
|
||||
byte[] dataBytes = bytes(32, 65, 205, 69, 41, 220, 46, 128, 236);
|
||||
BitArray in = new BitArray();
|
||||
for (byte dataByte: dataBytes) {
|
||||
in.appendBits(dataByte, 8);
|
||||
}
|
||||
BitArray out = Encoder.interleaveWithECBytes(in, 26, 9, 1);
|
||||
byte[] expected = bytes(
|
||||
// Data bytes.
|
||||
32, 65, 205, 69, 41, 220, 46, 128, 236,
|
||||
// Error correction bytes.
|
||||
42, 159, 74, 221, 244, 169, 239, 150, 138, 70,
|
||||
237, 85, 224, 96, 74, 219, 61
|
||||
);
|
||||
assertEquals(expected.length, out.getSizeInBytes());
|
||||
byte[] outArray = new byte[expected.length];
|
||||
out.toBytes(0, outArray, 0, expected.length);
|
||||
// Can't use Arrays.equals(), because outArray may be longer than out.sizeInBytes()
|
||||
for (int x = 0; x < expected.length; x++) {
|
||||
assertEquals(expected[x], outArray[x]);
|
||||
}
|
||||
// Numbers are from http://www.swetake.com/qr/qr8.html
|
||||
dataBytes = bytes(
|
||||
67, 70, 22, 38, 54, 70, 86, 102, 118, 134, 150, 166, 182,
|
||||
198, 214, 230, 247, 7, 23, 39, 55, 71, 87, 103, 119, 135,
|
||||
151, 166, 22, 38, 54, 70, 86, 102, 118, 134, 150, 166,
|
||||
182, 198, 214, 230, 247, 7, 23, 39, 55, 71, 87, 103, 119,
|
||||
135, 151, 160, 236, 17, 236, 17, 236, 17, 236,
|
||||
17
|
||||
);
|
||||
in = new BitArray();
|
||||
for (byte dataByte: dataBytes) {
|
||||
in.appendBits(dataByte, 8);
|
||||
}
|
||||
|
||||
out = Encoder.interleaveWithECBytes(in, 134, 62, 4);
|
||||
expected = bytes(
|
||||
// Data bytes.
|
||||
67, 230, 54, 55, 70, 247, 70, 71, 22, 7, 86, 87, 38, 23, 102, 103, 54, 39,
|
||||
118, 119, 70, 55, 134, 135, 86, 71, 150, 151, 102, 87, 166,
|
||||
160, 118, 103, 182, 236, 134, 119, 198, 17, 150,
|
||||
135, 214, 236, 166, 151, 230, 17, 182,
|
||||
166, 247, 236, 198, 22, 7, 17, 214, 38, 23, 236, 39,
|
||||
17,
|
||||
// Error correction bytes.
|
||||
175, 155, 245, 236, 80, 146, 56, 74, 155, 165,
|
||||
133, 142, 64, 183, 132, 13, 178, 54, 132, 108, 45,
|
||||
113, 53, 50, 214, 98, 193, 152, 233, 147, 50, 71, 65,
|
||||
190, 82, 51, 209, 199, 171, 54, 12, 112, 57, 113, 155, 117,
|
||||
211, 164, 117, 30, 158, 225, 31, 190, 242, 38,
|
||||
140, 61, 179, 154, 214, 138, 147, 87, 27, 96, 77, 47,
|
||||
187, 49, 156, 214
|
||||
);
|
||||
assertEquals(expected.length, out.getSizeInBytes());
|
||||
outArray = new byte[expected.length];
|
||||
out.toBytes(0, outArray, 0, expected.length);
|
||||
for (int x = 0; x < expected.length; x++) {
|
||||
assertEquals(expected[x], outArray[x]);
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] bytes(int... ints) {
|
||||
byte[] bytes = new byte[ints.length];
|
||||
for (int i = 0; i < ints.length; i++) {
|
||||
bytes[i] = (byte) ints[i];
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAppendNumericBytes() {
|
||||
// 1 = 01 = 0001 in 4 bits.
|
||||
BitArray bits = new BitArray();
|
||||
Encoder.appendNumericBytes("1", bits);
|
||||
assertEquals(" ...X" , bits.toString());
|
||||
// 12 = 0xc = 0001100 in 7 bits.
|
||||
bits = new BitArray();
|
||||
Encoder.appendNumericBytes("12", bits);
|
||||
assertEquals(" ...XX.." , bits.toString());
|
||||
// 123 = 0x7b = 0001111011 in 10 bits.
|
||||
bits = new BitArray();
|
||||
Encoder.appendNumericBytes("123", bits);
|
||||
assertEquals(" ...XXXX. XX" , bits.toString());
|
||||
// 1234 = "123" + "4" = 0001111011 + 0100
|
||||
bits = new BitArray();
|
||||
Encoder.appendNumericBytes("1234", bits);
|
||||
assertEquals(" ...XXXX. XX.X.." , bits.toString());
|
||||
// Empty.
|
||||
bits = new BitArray();
|
||||
Encoder.appendNumericBytes("", bits);
|
||||
assertEquals("" , bits.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAppendAlphanumericBytes() throws WriterException {
|
||||
// A = 10 = 0xa = 001010 in 6 bits
|
||||
BitArray bits = new BitArray();
|
||||
Encoder.appendAlphanumericBytes("A", bits);
|
||||
assertEquals(" ..X.X." , bits.toString());
|
||||
// AB = 10 * 45 + 11 = 461 = 0x1cd = 00111001101 in 11 bits
|
||||
bits = new BitArray();
|
||||
Encoder.appendAlphanumericBytes("AB", bits);
|
||||
assertEquals(" ..XXX..X X.X", bits.toString());
|
||||
// ABC = "AB" + "C" = 00111001101 + 001100
|
||||
bits = new BitArray();
|
||||
Encoder.appendAlphanumericBytes("ABC", bits);
|
||||
assertEquals(" ..XXX..X X.X..XX. ." , bits.toString());
|
||||
// Empty.
|
||||
bits = new BitArray();
|
||||
Encoder.appendAlphanumericBytes("", bits);
|
||||
assertEquals("" , bits.toString());
|
||||
// Invalid data.
|
||||
try {
|
||||
Encoder.appendAlphanumericBytes("abc", new BitArray());
|
||||
} catch (WriterException we) {
|
||||
// good
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAppend8BitBytes() {
|
||||
// 0x61, 0x62, 0x63
|
||||
BitArray bits = new BitArray();
|
||||
Encoder.append8BitBytes("abc", bits, Encoder.DEFAULT_BYTE_MODE_ENCODING);
|
||||
assertEquals(" .XX....X .XX...X. .XX...XX", bits.toString());
|
||||
// Empty.
|
||||
bits = new BitArray();
|
||||
Encoder.append8BitBytes("", bits, Encoder.DEFAULT_BYTE_MODE_ENCODING);
|
||||
assertEquals("", bits.toString());
|
||||
}
|
||||
|
||||
// Numbers are from page 21 of JISX0510:2004
|
||||
@Test
|
||||
public void testAppendKanjiBytes() throws WriterException {
|
||||
BitArray bits = new BitArray();
|
||||
Encoder.appendKanjiBytes(shiftJISString(bytes(0x93, 0x5f)), bits);
|
||||
assertEquals(" .XX.XX.. XXXXX", bits.toString());
|
||||
Encoder.appendKanjiBytes(shiftJISString(bytes(0xe4, 0xaa)), bits);
|
||||
assertEquals(" .XX.XX.. XXXXXXX. X.X.X.X. X.", bits.toString());
|
||||
}
|
||||
|
||||
// Numbers are from http://www.swetake.com/qr/qr3.html and
|
||||
// http://www.swetake.com/qr/qr9.html
|
||||
@Test
|
||||
public void testGenerateECBytes() {
|
||||
byte[] dataBytes = bytes(32, 65, 205, 69, 41, 220, 46, 128, 236);
|
||||
byte[] ecBytes = Encoder.generateECBytes(dataBytes, 17);
|
||||
int[] expected = {
|
||||
42, 159, 74, 221, 244, 169, 239, 150, 138, 70, 237, 85, 224, 96, 74, 219, 61
|
||||
};
|
||||
assertEquals(expected.length, ecBytes.length);
|
||||
for (int x = 0; x < expected.length; x++) {
|
||||
assertEquals(expected[x], ecBytes[x] & 0xFF);
|
||||
}
|
||||
dataBytes = bytes(67, 70, 22, 38, 54, 70, 86, 102, 118, 134, 150, 166, 182, 198, 214);
|
||||
ecBytes = Encoder.generateECBytes(dataBytes, 18);
|
||||
expected = new int[] {
|
||||
175, 80, 155, 64, 178, 45, 214, 233, 65, 209, 12, 155, 117, 31, 140, 214, 27, 187
|
||||
};
|
||||
assertEquals(expected.length, ecBytes.length);
|
||||
for (int x = 0; x < expected.length; x++) {
|
||||
assertEquals(expected[x], ecBytes[x] & 0xFF);
|
||||
}
|
||||
// High-order zero coefficient case.
|
||||
dataBytes = bytes(32, 49, 205, 69, 42, 20, 0, 236, 17);
|
||||
ecBytes = Encoder.generateECBytes(dataBytes, 17);
|
||||
expected = new int[] {
|
||||
0, 3, 130, 179, 194, 0, 55, 211, 110, 79, 98, 72, 170, 96, 211, 137, 213
|
||||
};
|
||||
assertEquals(expected.length, ecBytes.length);
|
||||
for (int x = 0; x < expected.length; x++) {
|
||||
assertEquals(expected[x], ecBytes[x] & 0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBugInBitVectorNumBytes() throws WriterException {
|
||||
// There was a bug in BitVector.sizeInBytes() that caused it to return a
|
||||
// smaller-by-one value (ex. 1465 instead of 1466) if the number of bits
|
||||
// in the vector is not 8-bit aligned. In QRCodeEncoder::InitQRCode(),
|
||||
// BitVector::sizeInBytes() is used for finding the smallest QR Code
|
||||
// version that can fit the given data. Hence there were corner cases
|
||||
// where we chose a wrong QR Code version that cannot fit the given
|
||||
// data. Note that the issue did not occur with MODE_8BIT_BYTE, as the
|
||||
// bits in the bit vector are always 8-bit aligned.
|
||||
//
|
||||
// Before the bug was fixed, the following test didn't pass, because:
|
||||
//
|
||||
// - MODE_NUMERIC is chosen as all bytes in the data are '0'
|
||||
// - The 3518-byte numeric data needs 1466 bytes
|
||||
// - 3518 / 3 * 10 + 7 = 11727 bits = 1465.875 bytes
|
||||
// - 3 numeric bytes are encoded in 10 bits, hence the first
|
||||
// 3516 bytes are encoded in 3516 / 3 * 10 = 11720 bits.
|
||||
// - 2 numeric bytes can be encoded in 7 bits, hence the last
|
||||
// 2 bytes are encoded in 7 bits.
|
||||
// - The version 27 QR Code with the EC level L has 1468 bytes for data.
|
||||
// - 1828 - 360 = 1468
|
||||
// - In InitQRCode(), 3 bytes are reserved for a header. Hence 1465 bytes
|
||||
// (1468 -3) are left for data.
|
||||
// - Because of the bug in BitVector::sizeInBytes(), InitQRCode() determines
|
||||
// the given data can fit in 1465 bytes, despite it needs 1466 bytes.
|
||||
// - Hence QRCodeEncoder.encode() failed and returned false.
|
||||
// - To be precise, it needs 11727 + 4 (getMode info) + 14 (length info) =
|
||||
// 11745 bits = 1468.125 bytes are needed (i.e. cannot fit in 1468
|
||||
// bytes).
|
||||
StringBuilder builder = new StringBuilder(3518);
|
||||
for (int x = 0; x < 3518; x++) {
|
||||
builder.append('0');
|
||||
}
|
||||
Encoder.encode(builder.toString(), ErrorCorrectionLevel.L);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinimalEncoder1() throws Exception {
|
||||
verifyMinimalEncoding("A", "ALPHANUMERIC(A)", null, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinimalEncoder2() throws Exception {
|
||||
verifyMinimalEncoding("AB", "ALPHANUMERIC(AB)", null, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinimalEncoder3() throws Exception {
|
||||
verifyMinimalEncoding("ABC", "ALPHANUMERIC(ABC)", null, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinimalEncoder4() throws Exception {
|
||||
verifyMinimalEncoding("ABCD", "ALPHANUMERIC(ABCD)", null, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinimalEncoder5() throws Exception {
|
||||
verifyMinimalEncoding("ABCDE", "ALPHANUMERIC(ABCDE)", null, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinimalEncoder6() throws Exception {
|
||||
verifyMinimalEncoding("ABCDEF", "ALPHANUMERIC(ABCDEF)", null, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinimalEncoder7() throws Exception {
|
||||
verifyMinimalEncoding("ABCDEFG", "ALPHANUMERIC(ABCDEFG)", null, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinimalEncoder8() throws Exception {
|
||||
verifyMinimalEncoding("1", "NUMERIC(1)", null, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinimalEncoder9() throws Exception {
|
||||
verifyMinimalEncoding("12", "NUMERIC(12)", null, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinimalEncoder10() throws Exception {
|
||||
verifyMinimalEncoding("123", "NUMERIC(123)", null, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinimalEncoder11() throws Exception {
|
||||
verifyMinimalEncoding("1234", "NUMERIC(1234)", null, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinimalEncoder12() throws Exception {
|
||||
verifyMinimalEncoding("12345", "NUMERIC(12345)", null, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinimalEncoder13() throws Exception {
|
||||
verifyMinimalEncoding("123456", "NUMERIC(123456)", null, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinimalEncoder14() throws Exception {
|
||||
verifyMinimalEncoding("123A", "ALPHANUMERIC(123A)", null, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinimalEncoder15() throws Exception {
|
||||
verifyMinimalEncoding("A1", "ALPHANUMERIC(A1)", null, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinimalEncoder16() throws Exception {
|
||||
verifyMinimalEncoding("A12", "ALPHANUMERIC(A12)", null, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinimalEncoder17() throws Exception {
|
||||
verifyMinimalEncoding("A123", "ALPHANUMERIC(A123)", null, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinimalEncoder18() throws Exception {
|
||||
verifyMinimalEncoding("A1234", "ALPHANUMERIC(A1234)", null, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinimalEncoder19() throws Exception {
|
||||
verifyMinimalEncoding("A12345", "ALPHANUMERIC(A12345)", null, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinimalEncoder20() throws Exception {
|
||||
verifyMinimalEncoding("A123456", "ALPHANUMERIC(A123456)", null, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinimalEncoder21() throws Exception {
|
||||
verifyMinimalEncoding("A1234567", "ALPHANUMERIC(A1234567)", null, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinimalEncoder22() throws Exception {
|
||||
verifyMinimalEncoding("A12345678", "BYTE(A),NUMERIC(12345678)", null, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinimalEncoder23() throws Exception {
|
||||
verifyMinimalEncoding("A123456789", "BYTE(A),NUMERIC(123456789)", null, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinimalEncoder24() throws Exception {
|
||||
verifyMinimalEncoding("A1234567890", "ALPHANUMERIC(A1),NUMERIC(234567890)", null, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinimalEncoder25() throws Exception {
|
||||
verifyMinimalEncoding("AB1", "ALPHANUMERIC(AB1)", null, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinimalEncoder26() throws Exception {
|
||||
verifyMinimalEncoding("AB12", "ALPHANUMERIC(AB12)", null, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinimalEncoder27() throws Exception {
|
||||
verifyMinimalEncoding("AB123", "ALPHANUMERIC(AB123)", null, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinimalEncoder28() throws Exception {
|
||||
verifyMinimalEncoding("AB1234", "ALPHANUMERIC(AB1234)", null, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinimalEncoder29() throws Exception {
|
||||
verifyMinimalEncoding("ABC1", "ALPHANUMERIC(ABC1)", null, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinimalEncoder30() throws Exception {
|
||||
verifyMinimalEncoding("ABC12", "ALPHANUMERIC(ABC12)", null, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinimalEncoder31() throws Exception {
|
||||
verifyMinimalEncoding("ABC1234", "ALPHANUMERIC(ABC1234)", null, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinimalEncoder32() throws Exception {
|
||||
verifyMinimalEncoding("http://foo.com", "BYTE(http://foo.com)" +
|
||||
"", null, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinimalEncoder33() throws Exception {
|
||||
verifyMinimalEncoding("HTTP://FOO.COM", "ALPHANUMERIC(HTTP://FOO.COM" +
|
||||
")", null, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinimalEncoder34() throws Exception {
|
||||
verifyMinimalEncoding("1001114670010%01201220%107211220%140045003267781",
|
||||
"NUMERIC(1001114670010),ALPHANUMERIC(%01201220%107211220%),NUMERIC(140045003267781)", null, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinimalEncoder35() throws Exception {
|
||||
verifyMinimalEncoding("\u0150", "ECI(ISO-8859-2),BYTE(.)", null, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinimalEncoder36() throws Exception {
|
||||
verifyMinimalEncoding("\u015C", "ECI(ISO-8859-3),BYTE(.)", null, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinimalEncoder37() throws Exception {
|
||||
verifyMinimalEncoding("\u0150\u015C", "ECI(UTF-8),BYTE(..)", null, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinimalEncoder38() throws Exception {
|
||||
verifyMinimalEncoding("\u0150\u0150\u015C\u015C", "ECI(ISO-8859-2),BYTE(." +
|
||||
".),ECI(ISO-8859-3),BYTE(..)", null, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinimalEncoder39() throws Exception {
|
||||
verifyMinimalEncoding("abcdef\u0150ghij", "ECI(ISO-8859-2),BYTE(abcde" +
|
||||
"f.ghij)", null, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinimalEncoder40() throws Exception {
|
||||
verifyMinimalEncoding("2938928329832983\u01502938928329832983\u015C2938928329832983",
|
||||
"NUMERIC(2938928329832983),ECI(ISO-8859-2),BYTE(.),NUMERIC(2938928329832983),ECI(ISO-8" +
|
||||
"859-3),BYTE(.),NUMERIC(2938928329832983)", null, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinimalEncoder41() throws Exception {
|
||||
verifyMinimalEncoding("1001114670010%01201220%107211220%140045003267781", "FNC1_FIRST_POSITION(),NUMERIC(100111" +
|
||||
"4670010),ALPHANUMERIC(%01201220%107211220%),NUMERIC(140045003267781)", null,
|
||||
true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinimalEncoder42() throws Exception {
|
||||
// test halfwidth Katakana character (they are single byte encoded in Shift_JIS)
|
||||
verifyMinimalEncoding("Katakana:\uFF66\uFF66\uFF66\uFF66\uFF66\uFF66", "ECI(Shift_JIS),BYTE(Katakana:......)", null
|
||||
, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinimalEncoder43() throws Exception {
|
||||
// The character \u30A2 encodes as double byte in Shift_JIS so KANJI is more compact in this case
|
||||
verifyMinimalEncoding("Katakana:\u30A2\u30A2\u30A2\u30A2\u30A2\u30A2", "BYTE(Katakana:),KANJI(......)", null,
|
||||
false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinimalEncoder44() throws Exception {
|
||||
// The character \u30A2 encodes as double byte in Shift_JIS but KANJI is not more compact in this case because
|
||||
// KANJI is only more compact when it encodes pairs of characters. In the case of mixed text it can however be
|
||||
// that Shift_JIS encoding is more compact as in this example
|
||||
verifyMinimalEncoding("Katakana:\u30A2a\u30A2a\u30A2a\u30A2a\u30A2a\u30A2", "ECI(Shift_JIS),BYTE(Katakana:.a.a.a" +
|
||||
".a.a.)", null, false);
|
||||
}
|
||||
|
||||
static void verifyMinimalEncoding(String input, String expectedRXingResult, Charset priorityCharset, boolean isGS1)
|
||||
throws Exception {
|
||||
MinimalEncoder.RXingResultList result = MinimalEncoder.encode(input, null, priorityCharset, isGS1,
|
||||
ErrorCorrectionLevel.L);
|
||||
assertEquals(result.toString(), expectedRXingResult);
|
||||
}
|
||||
|
||||
private static void verifyGS1EncodedData(QRCode qrCode) {
|
||||
String expected = "<<\n" +
|
||||
" mode: ALPHANUMERIC\n" +
|
||||
" ecLevel: H\n" +
|
||||
" version: 2\n" +
|
||||
" maskPattern: 2\n" +
|
||||
" matrix:\n" +
|
||||
" 1 1 1 1 1 1 1 0 1 0 1 1 1 1 0 1 1 0 1 1 1 1 1 1 1\n" +
|
||||
" 1 0 0 0 0 0 1 0 1 0 0 0 0 1 1 0 1 0 1 0 0 0 0 0 1\n" +
|
||||
" 1 0 1 1 1 0 1 0 1 0 1 1 0 1 1 0 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 1 1 0 1 0 1 1 1 0 1\n" +
|
||||
" 1 0 1 1 1 0 1 0 0 1 1 1 1 1 1 1 1 0 1 0 1 1 1 0 1\n" +
|
||||
" 1 0 0 0 0 0 1 0 1 0 0 1 1 1 0 0 0 0 1 0 0 0 0 0 1\n" +
|
||||
" 1 1 1 1 1 1 1 0 1 0 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 1 1 1 0 0 0 0 0 0 0 0\n" +
|
||||
" 0 0 1 1 1 0 1 0 1 1 1 1 0 1 1 0 1 1 1 1 0 0 1 1 1\n" +
|
||||
" 0 0 0 1 1 1 0 1 0 0 1 0 0 1 0 0 1 1 1 0 0 1 0 0 1\n" +
|
||||
" 1 0 1 1 0 0 1 0 1 1 0 0 0 0 1 0 1 1 1 0 0 1 0 0 1\n" +
|
||||
" 0 0 1 1 0 1 0 1 1 1 1 0 0 1 1 1 1 0 0 0 1 1 0 1 1\n" +
|
||||
" 0 0 1 0 0 0 1 0 0 0 1 1 0 1 0 0 0 1 0 1 1 1 0 1 0\n" +
|
||||
" 1 1 1 0 1 1 0 1 0 0 0 0 0 0 0 1 1 0 1 1 0 1 0 0 0\n" +
|
||||
" 1 0 1 0 1 0 1 1 0 1 0 1 0 1 1 0 0 0 0 0 1 1 0 0 1\n" +
|
||||
" 1 0 0 1 0 1 0 1 0 0 0 1 1 1 1 0 1 0 1 0 0 1 0 0 1\n" +
|
||||
" 1 0 1 0 0 1 1 1 0 1 1 0 0 1 0 0 1 1 1 1 1 1 0 0 0\n" +
|
||||
" 0 0 0 0 0 0 0 0 1 0 0 1 0 1 1 0 1 0 0 0 1 0 0 1 0\n" +
|
||||
" 1 1 1 1 1 1 1 0 0 0 0 1 0 0 1 1 1 0 1 0 1 0 1 1 1\n" +
|
||||
" 1 0 0 0 0 0 1 0 0 1 1 1 1 1 0 1 1 0 0 0 1 0 0 0 1\n" +
|
||||
" 1 0 1 1 1 0 1 0 1 0 1 0 0 1 1 1 1 1 1 1 1 0 0 0 1\n" +
|
||||
" 1 0 1 1 1 0 1 0 1 1 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0\n" +
|
||||
" 1 0 1 1 1 0 1 0 1 0 0 0 1 1 0 1 0 0 1 1 1 0 1 0 1\n" +
|
||||
" 1 0 0 0 0 0 1 0 0 1 0 1 0 1 1 1 0 1 0 0 1 1 1 1 1\n" +
|
||||
" 1 1 1 1 1 1 1 0 0 1 1 0 0 1 1 0 1 0 0 0 0 1 0 1 1\n" +
|
||||
">>\n";
|
||||
assertEquals(expected, qrCode.toString());
|
||||
}
|
||||
|
||||
private static void verifyNotGS1EncodedData(QRCode qrCode) {
|
||||
String expected = "<<\n" +
|
||||
" mode: ALPHANUMERIC\n" +
|
||||
" ecLevel: H\n" +
|
||||
" version: 1\n" +
|
||||
" maskPattern: 0\n" +
|
||||
" matrix:\n" +
|
||||
" 1 1 1 1 1 1 1 0 1 1 1 1 0 0 1 1 1 1 1 1 1\n" +
|
||||
" 1 0 0 0 0 0 1 0 0 1 1 1 0 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 0 1 0 1 0 1 1 1 0 1\n" +
|
||||
" 1 0 1 1 1 0 1 0 0 1 1 1 0 0 1 0 1 1 1 0 1\n" +
|
||||
" 1 0 0 0 0 0 1 0 0 1 0 0 0 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 0 0 1 0 1 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 0 1 1 1 0 0 1 0 0 0 1 0 1 0 0 0 0 0 0 0\n" +
|
||||
" 0 0 1 1 0 0 1 0 1 0 0 0 1 0 1 0 1 0 1 1 0\n" +
|
||||
" 1 1 0 1 0 1 0 1 1 1 0 1 0 1 0 0 0 0 0 1 0\n" +
|
||||
" 0 0 1 1 0 1 1 1 1 0 0 0 1 0 1 0 1 1 1 1 0\n" +
|
||||
" 0 0 0 0 0 0 0 0 1 0 0 1 1 1 0 1 0 1 0 0 0\n" +
|
||||
" 1 1 1 1 1 1 1 0 0 0 1 0 1 0 1 1 0 0 0 0 1\n" +
|
||||
" 1 0 0 0 0 0 1 0 1 1 1 1 0 1 0 1 1 1 1 0 1\n" +
|
||||
" 1 0 1 1 1 0 1 0 1 0 1 1 0 1 0 1 0 0 0 0 1\n" +
|
||||
" 1 0 1 1 1 0 1 0 0 1 1 0 1 1 1 1 0 1 0 1 0\n" +
|
||||
" 1 0 1 1 1 0 1 0 1 0 0 0 1 0 1 0 1 1 1 0 1\n" +
|
||||
" 1 0 0 0 0 0 1 0 0 1 1 0 1 1 0 1 0 0 0 1 1\n" +
|
||||
" 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 0 1 0 1\n" +
|
||||
">>\n";
|
||||
assertEquals(expected, qrCode.toString());
|
||||
}
|
||||
|
||||
private static String shiftJISString(byte[] bytes) {
|
||||
return new String(bytes, StringUtils.SHIFT_JIS_CHARSET);
|
||||
}
|
||||
|
||||
}
|
||||
279
src/qrcode/encoder/MaskUtilTestCase.java
Normal file
279
src/qrcode/encoder/MaskUtilTestCase.java
Normal file
@@ -0,0 +1,279 @@
|
||||
/*
|
||||
* 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.qrcode.encoder;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author satorux@google.com (Satoru Takabayashi) - creator
|
||||
* @author mysen@google.com (Chris Mysen) - ported from C++
|
||||
*/
|
||||
public final class MaskUtilTestCase extends Assert {
|
||||
|
||||
@Test
|
||||
public void testApplyMaskPenaltyRule1() {
|
||||
ByteMatrix matrix = new ByteMatrix(4, 1);
|
||||
matrix.set(0, 0, 0);
|
||||
matrix.set(1, 0, 0);
|
||||
matrix.set(2, 0, 0);
|
||||
matrix.set(3, 0, 0);
|
||||
assertEquals(0, MaskUtil.applyMaskPenaltyRule1(matrix));
|
||||
// Horizontal.
|
||||
matrix = new ByteMatrix(6, 1);
|
||||
matrix.set(0, 0, 0);
|
||||
matrix.set(1, 0, 0);
|
||||
matrix.set(2, 0, 0);
|
||||
matrix.set(3, 0, 0);
|
||||
matrix.set(4, 0, 0);
|
||||
matrix.set(5, 0, 1);
|
||||
assertEquals(3, MaskUtil.applyMaskPenaltyRule1(matrix));
|
||||
matrix.set(5, 0, 0);
|
||||
assertEquals(4, MaskUtil.applyMaskPenaltyRule1(matrix));
|
||||
// Vertical.
|
||||
matrix = new ByteMatrix(1, 6);
|
||||
matrix.set(0, 0, 0);
|
||||
matrix.set(0, 1, 0);
|
||||
matrix.set(0, 2, 0);
|
||||
matrix.set(0, 3, 0);
|
||||
matrix.set(0, 4, 0);
|
||||
matrix.set(0, 5, 1);
|
||||
assertEquals(3, MaskUtil.applyMaskPenaltyRule1(matrix));
|
||||
matrix.set(0, 5, 0);
|
||||
assertEquals(4, MaskUtil.applyMaskPenaltyRule1(matrix));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testApplyMaskPenaltyRule2() {
|
||||
ByteMatrix matrix = new ByteMatrix(1, 1);
|
||||
matrix.set(0, 0, 0);
|
||||
assertEquals(0, MaskUtil.applyMaskPenaltyRule2(matrix));
|
||||
matrix = new ByteMatrix(2, 2);
|
||||
matrix.set(0, 0, 0);
|
||||
matrix.set(1, 0, 0);
|
||||
matrix.set(0, 1, 0);
|
||||
matrix.set(1, 1, 1);
|
||||
assertEquals(0, MaskUtil.applyMaskPenaltyRule2(matrix));
|
||||
matrix = new ByteMatrix(2, 2);
|
||||
matrix.set(0, 0, 0);
|
||||
matrix.set(1, 0, 0);
|
||||
matrix.set(0, 1, 0);
|
||||
matrix.set(1, 1, 0);
|
||||
assertEquals(3, MaskUtil.applyMaskPenaltyRule2(matrix));
|
||||
matrix = new ByteMatrix(3, 3);
|
||||
matrix.set(0, 0, 0);
|
||||
matrix.set(1, 0, 0);
|
||||
matrix.set(2, 0, 0);
|
||||
matrix.set(0, 1, 0);
|
||||
matrix.set(1, 1, 0);
|
||||
matrix.set(2, 1, 0);
|
||||
matrix.set(0, 2, 0);
|
||||
matrix.set(1, 2, 0);
|
||||
matrix.set(2, 2, 0);
|
||||
// Four instances of 2x2 blocks.
|
||||
assertEquals(3 * 4, MaskUtil.applyMaskPenaltyRule2(matrix));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testApplyMaskPenaltyRule3() {
|
||||
// Horizontal 00001011101.
|
||||
ByteMatrix matrix = new ByteMatrix(11, 1);
|
||||
matrix.set(0, 0, 0);
|
||||
matrix.set(1, 0, 0);
|
||||
matrix.set(2, 0, 0);
|
||||
matrix.set(3, 0, 0);
|
||||
matrix.set(4, 0, 1);
|
||||
matrix.set(5, 0, 0);
|
||||
matrix.set(6, 0, 1);
|
||||
matrix.set(7, 0, 1);
|
||||
matrix.set(8, 0, 1);
|
||||
matrix.set(9, 0, 0);
|
||||
matrix.set(10, 0, 1);
|
||||
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.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(8, 0, 0);
|
||||
matrix.set(9, 0, 0);
|
||||
matrix.set(10, 0, 0);
|
||||
assertEquals(40, MaskUtil.applyMaskPenaltyRule3(matrix));
|
||||
// Horizontal 1011101.
|
||||
matrix = new ByteMatrix(7, 1);
|
||||
matrix.set(0, 0, 1);
|
||||
matrix.set(1, 0, 0);
|
||||
matrix.set(2, 0, 1);
|
||||
matrix.set(3, 0, 1);
|
||||
matrix.set(4, 0, 1);
|
||||
matrix.set(5, 0, 0);
|
||||
matrix.set(6, 0, 1);
|
||||
assertEquals(0, MaskUtil.applyMaskPenaltyRule3(matrix));
|
||||
// Vertical 00001011101.
|
||||
matrix = new ByteMatrix(1, 11);
|
||||
matrix.set(0, 0, 0);
|
||||
matrix.set(0, 1, 0);
|
||||
matrix.set(0, 2, 0);
|
||||
matrix.set(0, 3, 0);
|
||||
matrix.set(0, 4, 1);
|
||||
matrix.set(0, 5, 0);
|
||||
matrix.set(0, 6, 1);
|
||||
matrix.set(0, 7, 1);
|
||||
matrix.set(0, 8, 1);
|
||||
matrix.set(0, 9, 0);
|
||||
matrix.set(0, 10, 1);
|
||||
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.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, 8, 0);
|
||||
matrix.set(0, 9, 0);
|
||||
matrix.set(0, 10, 0);
|
||||
// Vertical 1011101.
|
||||
matrix = new ByteMatrix(1, 7);
|
||||
matrix.set(0, 0, 1);
|
||||
matrix.set(0, 1, 0);
|
||||
matrix.set(0, 2, 1);
|
||||
matrix.set(0, 3, 1);
|
||||
matrix.set(0, 4, 1);
|
||||
matrix.set(0, 5, 0);
|
||||
matrix.set(0, 6, 1);
|
||||
assertEquals(0, MaskUtil.applyMaskPenaltyRule3(matrix));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testApplyMaskPenaltyRule4() {
|
||||
// Dark cell ratio = 0%
|
||||
ByteMatrix matrix = new ByteMatrix(1, 1);
|
||||
matrix.set(0, 0, 0);
|
||||
assertEquals(100, MaskUtil.applyMaskPenaltyRule4(matrix));
|
||||
// Dark cell ratio = 5%
|
||||
matrix = new ByteMatrix(2, 1);
|
||||
matrix.set(0, 0, 0);
|
||||
matrix.set(0, 0, 1);
|
||||
assertEquals(0, MaskUtil.applyMaskPenaltyRule4(matrix));
|
||||
// Dark cell ratio = 66.67%
|
||||
matrix = new ByteMatrix(6, 1);
|
||||
matrix.set(0, 0, 0);
|
||||
matrix.set(1, 0, 1);
|
||||
matrix.set(2, 0, 1);
|
||||
matrix.set(3, 0, 1);
|
||||
matrix.set(4, 0, 1);
|
||||
matrix.set(5, 0, 0);
|
||||
assertEquals(30, MaskUtil.applyMaskPenaltyRule4(matrix));
|
||||
}
|
||||
|
||||
private static boolean testGetDataMaskBitInternal(int maskPattern, int[][] expected) {
|
||||
for (int x = 0; x < 6; ++x) {
|
||||
for (int y = 0; y < 6; ++y) {
|
||||
if ((expected[y][x] == 1) != MaskUtil.getDataMaskBit(maskPattern, x, y)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// See mask patterns on the page 43 of JISX0510:2004.
|
||||
@Test
|
||||
public void testGetDataMaskBit() {
|
||||
int[][] mask0 = {
|
||||
{1, 0, 1, 0, 1, 0},
|
||||
{0, 1, 0, 1, 0, 1},
|
||||
{1, 0, 1, 0, 1, 0},
|
||||
{0, 1, 0, 1, 0, 1},
|
||||
{1, 0, 1, 0, 1, 0},
|
||||
{0, 1, 0, 1, 0, 1},
|
||||
};
|
||||
assertTrue(testGetDataMaskBitInternal(0, mask0));
|
||||
int[][] mask1 = {
|
||||
{1, 1, 1, 1, 1, 1},
|
||||
{0, 0, 0, 0, 0, 0},
|
||||
{1, 1, 1, 1, 1, 1},
|
||||
{0, 0, 0, 0, 0, 0},
|
||||
{1, 1, 1, 1, 1, 1},
|
||||
{0, 0, 0, 0, 0, 0},
|
||||
};
|
||||
assertTrue(testGetDataMaskBitInternal(1, mask1));
|
||||
int[][] mask2 = {
|
||||
{1, 0, 0, 1, 0, 0},
|
||||
{1, 0, 0, 1, 0, 0},
|
||||
{1, 0, 0, 1, 0, 0},
|
||||
{1, 0, 0, 1, 0, 0},
|
||||
{1, 0, 0, 1, 0, 0},
|
||||
{1, 0, 0, 1, 0, 0},
|
||||
};
|
||||
assertTrue(testGetDataMaskBitInternal(2, mask2));
|
||||
int[][] mask3 = {
|
||||
{1, 0, 0, 1, 0, 0},
|
||||
{0, 0, 1, 0, 0, 1},
|
||||
{0, 1, 0, 0, 1, 0},
|
||||
{1, 0, 0, 1, 0, 0},
|
||||
{0, 0, 1, 0, 0, 1},
|
||||
{0, 1, 0, 0, 1, 0},
|
||||
};
|
||||
assertTrue(testGetDataMaskBitInternal(3, mask3));
|
||||
int[][] mask4 = {
|
||||
{1, 1, 1, 0, 0, 0},
|
||||
{1, 1, 1, 0, 0, 0},
|
||||
{0, 0, 0, 1, 1, 1},
|
||||
{0, 0, 0, 1, 1, 1},
|
||||
{1, 1, 1, 0, 0, 0},
|
||||
{1, 1, 1, 0, 0, 0},
|
||||
};
|
||||
assertTrue(testGetDataMaskBitInternal(4, mask4));
|
||||
int[][] mask5 = {
|
||||
{1, 1, 1, 1, 1, 1},
|
||||
{1, 0, 0, 0, 0, 0},
|
||||
{1, 0, 0, 1, 0, 0},
|
||||
{1, 0, 1, 0, 1, 0},
|
||||
{1, 0, 0, 1, 0, 0},
|
||||
{1, 0, 0, 0, 0, 0},
|
||||
};
|
||||
assertTrue(testGetDataMaskBitInternal(5, mask5));
|
||||
int[][] mask6 = {
|
||||
{1, 1, 1, 1, 1, 1},
|
||||
{1, 1, 1, 0, 0, 0},
|
||||
{1, 1, 0, 1, 1, 0},
|
||||
{1, 0, 1, 0, 1, 0},
|
||||
{1, 0, 1, 1, 0, 1},
|
||||
{1, 0, 0, 0, 1, 1},
|
||||
};
|
||||
assertTrue(testGetDataMaskBitInternal(6, mask6));
|
||||
int[][] mask7 = {
|
||||
{1, 0, 1, 0, 1, 0},
|
||||
{0, 0, 0, 1, 1, 1},
|
||||
{1, 0, 0, 0, 1, 1},
|
||||
{0, 1, 0, 1, 0, 1},
|
||||
{1, 1, 1, 0, 0, 0},
|
||||
{0, 1, 1, 1, 0, 0},
|
||||
};
|
||||
assertTrue(testGetDataMaskBitInternal(7, mask7));
|
||||
}
|
||||
}
|
||||
311
src/qrcode/encoder/MatrixUtilTestCase.java
Normal file
311
src/qrcode/encoder/MatrixUtilTestCase.java
Normal file
@@ -0,0 +1,311 @@
|
||||
/*
|
||||
* 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.qrcode.encoder;
|
||||
|
||||
import com.google.zxing.WriterException;
|
||||
import com.google.zxing.common.BitArray;
|
||||
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
|
||||
import com.google.zxing.qrcode.decoder.Version;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author satorux@google.com (Satoru Takabayashi) - creator
|
||||
* @author mysen@google.com (Chris Mysen) - ported from C++
|
||||
*/
|
||||
public final class MatrixUtilTestCase extends Assert {
|
||||
|
||||
@Test
|
||||
public void testToString() {
|
||||
ByteMatrix array = new ByteMatrix(3, 3);
|
||||
array.set(0, 0, 0);
|
||||
array.set(1, 0, 1);
|
||||
array.set(2, 0, 0);
|
||||
array.set(0, 1, 1);
|
||||
array.set(1, 1, 0);
|
||||
array.set(2, 1, 1);
|
||||
array.set(0, 2, -1);
|
||||
array.set(1, 2, -1);
|
||||
array.set(2, 2, -1);
|
||||
String expected = " 0 1 0\n" + " 1 0 1\n" + " \n";
|
||||
assertEquals(expected, array.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClearMatrix() {
|
||||
ByteMatrix matrix = new ByteMatrix(2, 2);
|
||||
MatrixUtil.clearMatrix(matrix);
|
||||
assertEquals(-1, matrix.get(0, 0));
|
||||
assertEquals(-1, matrix.get(1, 0));
|
||||
assertEquals(-1, matrix.get(0, 1));
|
||||
assertEquals(-1, matrix.get(1, 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmbedBasicPatterns1() throws WriterException {
|
||||
// Version 1.
|
||||
ByteMatrix matrix = new ByteMatrix(21, 21);
|
||||
MatrixUtil.clearMatrix(matrix);
|
||||
MatrixUtil.embedBasicPatterns(Version.getVersionForNumber(1), matrix);
|
||||
String expected =
|
||||
" 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1\n" +
|
||||
" 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1\n" +
|
||||
" 1 0 1 1 1 0 1 0 0 1 0 1 1 1 0 1\n" +
|
||||
" 1 0 1 1 1 0 1 0 0 1 0 1 1 1 0 1\n" +
|
||||
" 1 0 1 1 1 0 1 0 0 1 0 1 1 1 0 1\n" +
|
||||
" 1 0 0 0 0 0 1 0 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 0 0 0 0 0 0 0 0\n" +
|
||||
" 1 \n" +
|
||||
" 0 \n" +
|
||||
" 1 \n" +
|
||||
" 0 \n" +
|
||||
" 1 \n" +
|
||||
" 0 0 0 0 0 0 0 0 1 \n" +
|
||||
" 1 1 1 1 1 1 1 0 \n" +
|
||||
" 1 0 0 0 0 0 1 0 \n" +
|
||||
" 1 0 1 1 1 0 1 0 \n" +
|
||||
" 1 0 1 1 1 0 1 0 \n" +
|
||||
" 1 0 1 1 1 0 1 0 \n" +
|
||||
" 1 0 0 0 0 0 1 0 \n" +
|
||||
" 1 1 1 1 1 1 1 0 \n";
|
||||
assertEquals(expected, matrix.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmbedBasicPatterns2() throws WriterException {
|
||||
// Version 2. Position adjustment pattern should apppear at right
|
||||
// bottom corner.
|
||||
ByteMatrix matrix = new ByteMatrix(25, 25);
|
||||
MatrixUtil.clearMatrix(matrix);
|
||||
MatrixUtil.embedBasicPatterns(Version.getVersionForNumber(2), matrix);
|
||||
String expected =
|
||||
" 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1\n" +
|
||||
" 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1\n" +
|
||||
" 1 0 1 1 1 0 1 0 0 1 0 1 1 1 0 1\n" +
|
||||
" 1 0 1 1 1 0 1 0 0 1 0 1 1 1 0 1\n" +
|
||||
" 1 0 1 1 1 0 1 0 0 1 0 1 1 1 0 1\n" +
|
||||
" 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1\n" +
|
||||
" 1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1\n" +
|
||||
" 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n" +
|
||||
" 1 \n" +
|
||||
" 0 \n" +
|
||||
" 1 \n" +
|
||||
" 0 \n" +
|
||||
" 1 \n" +
|
||||
" 0 \n" +
|
||||
" 1 \n" +
|
||||
" 0 \n" +
|
||||
" 1 1 1 1 1 1 \n" +
|
||||
" 0 0 0 0 0 0 0 0 1 1 0 0 0 1 \n" +
|
||||
" 1 1 1 1 1 1 1 0 1 0 1 0 1 \n" +
|
||||
" 1 0 0 0 0 0 1 0 1 0 0 0 1 \n" +
|
||||
" 1 0 1 1 1 0 1 0 1 1 1 1 1 \n" +
|
||||
" 1 0 1 1 1 0 1 0 \n" +
|
||||
" 1 0 1 1 1 0 1 0 \n" +
|
||||
" 1 0 0 0 0 0 1 0 \n" +
|
||||
" 1 1 1 1 1 1 1 0 \n";
|
||||
assertEquals(expected, matrix.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmbedTypeInfo() throws WriterException {
|
||||
// Type info bits = 100000011001110.
|
||||
ByteMatrix matrix = new ByteMatrix(21, 21);
|
||||
MatrixUtil.clearMatrix(matrix);
|
||||
MatrixUtil.embedTypeInfo(ErrorCorrectionLevel.M, 5, matrix);
|
||||
String expected =
|
||||
" 0 \n" +
|
||||
" 1 \n" +
|
||||
" 1 \n" +
|
||||
" 1 \n" +
|
||||
" 0 \n" +
|
||||
" 0 \n" +
|
||||
" \n" +
|
||||
" 1 \n" +
|
||||
" 1 0 0 0 0 0 0 1 1 1 0 0 1 1 1 0\n" +
|
||||
" \n" +
|
||||
" \n" +
|
||||
" \n" +
|
||||
" \n" +
|
||||
" \n" +
|
||||
" 0 \n" +
|
||||
" 0 \n" +
|
||||
" 0 \n" +
|
||||
" 0 \n" +
|
||||
" 0 \n" +
|
||||
" 0 \n" +
|
||||
" 1 \n";
|
||||
assertEquals(expected, matrix.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmbedVersionInfo() throws WriterException {
|
||||
// Version info bits = 000111 110010 010100
|
||||
// Actually, version 7 QR Code has 45x45 matrix but we use 21x21 here
|
||||
// since 45x45 matrix is too big to depict.
|
||||
ByteMatrix matrix = new ByteMatrix(21, 21);
|
||||
MatrixUtil.clearMatrix(matrix);
|
||||
MatrixUtil.maybeEmbedVersionInfo(Version.getVersionForNumber(7), matrix);
|
||||
String expected =
|
||||
" 0 0 1 \n" +
|
||||
" 0 1 0 \n" +
|
||||
" 0 1 0 \n" +
|
||||
" 0 1 1 \n" +
|
||||
" 1 1 1 \n" +
|
||||
" 0 0 0 \n" +
|
||||
" \n" +
|
||||
" \n" +
|
||||
" \n" +
|
||||
" \n" +
|
||||
" 0 0 0 0 1 0 \n" +
|
||||
" 0 1 1 1 1 0 \n" +
|
||||
" 1 0 0 1 1 0 \n" +
|
||||
" \n" +
|
||||
" \n" +
|
||||
" \n" +
|
||||
" \n" +
|
||||
" \n" +
|
||||
" \n" +
|
||||
" \n" +
|
||||
" \n";
|
||||
assertEquals(expected, matrix.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmbedDataBits() throws WriterException {
|
||||
// Cells other than basic patterns should be filled with zero.
|
||||
ByteMatrix matrix = new ByteMatrix(21, 21);
|
||||
MatrixUtil.clearMatrix(matrix);
|
||||
MatrixUtil.embedBasicPatterns(Version.getVersionForNumber(1), matrix);
|
||||
BitArray bits = new BitArray();
|
||||
MatrixUtil.embedDataBits(bits, -1, matrix);
|
||||
String expected =
|
||||
" 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 0 0 0 0 1 0 0 0 0 0 1\n" +
|
||||
" 1 0 1 1 1 0 1 0 0 0 0 0 0 0 1 0 1 1 1 0 1\n" +
|
||||
" 1 0 1 1 1 0 1 0 0 0 0 0 0 0 1 0 1 1 1 0 1\n" +
|
||||
" 1 0 1 1 1 0 1 0 0 0 0 0 0 0 1 0 1 1 1 0 1\n" +
|
||||
" 1 0 0 0 0 0 1 0 0 0 0 0 0 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 0 0 0 0 0 0 0 0 0 0 0 0 0\n" +
|
||||
" 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n" +
|
||||
" 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n" +
|
||||
" 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n" +
|
||||
" 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n" +
|
||||
" 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n" +
|
||||
" 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0\n" +
|
||||
" 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n" +
|
||||
" 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n" +
|
||||
" 1 0 1 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n" +
|
||||
" 1 0 1 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n" +
|
||||
" 1 0 1 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n" +
|
||||
" 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n" +
|
||||
" 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n";
|
||||
assertEquals(expected, matrix.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBuildMatrix() throws WriterException {
|
||||
// From http://www.swetake.com/qr/qr7.html
|
||||
char[] bytes = {32, 65, 205, 69, 41, 220, 46, 128, 236,
|
||||
42, 159, 74, 221, 244, 169, 239, 150, 138,
|
||||
70, 237, 85, 224, 96, 74, 219 , 61};
|
||||
BitArray bits = new BitArray();
|
||||
for (char c: bytes) {
|
||||
bits.appendBits(c, 8);
|
||||
}
|
||||
ByteMatrix matrix = new ByteMatrix(21, 21);
|
||||
MatrixUtil.buildMatrix(bits,
|
||||
ErrorCorrectionLevel.H,
|
||||
Version.getVersionForNumber(1), // Version 1
|
||||
3, // Mask pattern 3
|
||||
matrix);
|
||||
String expected =
|
||||
" 1 1 1 1 1 1 1 0 0 1 1 0 0 0 1 1 1 1 1 1 1\n" +
|
||||
" 1 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 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 1 1 1 0 1 0 0 1 1 0 0 0 1 0 1 1 1 0 1\n" +
|
||||
" 1 0 1 1 1 0 1 0 1 1 0 0 1 0 1 0 1 1 1 0 1\n" +
|
||||
" 1 0 0 0 0 0 1 0 0 0 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 0 1 1 0 0 0 0 0 0 0 0\n" +
|
||||
" 0 0 1 1 0 0 1 1 1 0 0 1 1 1 1 0 1 0 0 0 0\n" +
|
||||
" 1 0 1 0 1 0 0 0 0 0 1 1 1 0 0 1 0 1 1 1 0\n" +
|
||||
" 1 1 1 1 0 1 1 0 1 0 1 1 1 0 0 1 1 1 0 1 0\n" +
|
||||
" 1 0 1 0 1 1 0 1 1 1 0 0 1 1 1 0 0 1 0 1 0\n" +
|
||||
" 0 0 1 0 0 1 1 1 0 0 0 0 0 0 1 0 1 1 1 1 1\n" +
|
||||
" 0 0 0 0 0 0 0 0 1 1 0 1 0 0 0 0 0 1 0 1 1\n" +
|
||||
" 1 1 1 1 1 1 1 0 1 1 1 1 0 0 0 0 1 0 1 1 0\n" +
|
||||
" 1 0 0 0 0 0 1 0 0 0 0 1 0 1 1 1 0 0 0 0 0\n" +
|
||||
" 1 0 1 1 1 0 1 0 0 1 0 0 1 1 0 0 1 0 0 1 1\n" +
|
||||
" 1 0 1 1 1 0 1 0 1 1 0 1 0 0 0 0 0 1 1 1 0\n" +
|
||||
" 1 0 1 1 1 0 1 0 1 1 1 1 0 0 0 0 1 1 1 0 0\n" +
|
||||
" 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 1 0 0\n" +
|
||||
" 1 1 1 1 1 1 1 0 0 0 1 1 1 1 1 0 1 0 0 1 0\n";
|
||||
assertEquals(expected, matrix.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindMSBSet() {
|
||||
assertEquals(0, MatrixUtil.findMSBSet(0));
|
||||
assertEquals(1, MatrixUtil.findMSBSet(1));
|
||||
assertEquals(8, MatrixUtil.findMSBSet(0x80));
|
||||
assertEquals(32, MatrixUtil.findMSBSet(0x80000000));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCalculateBCHCode() {
|
||||
// Encoding of type information.
|
||||
// From Appendix C in JISX0510:2004 (p 65)
|
||||
assertEquals(0xdc, MatrixUtil.calculateBCHCode(5, 0x537));
|
||||
// From http://www.swetake.com/qr/qr6.html
|
||||
assertEquals(0x1c2, MatrixUtil.calculateBCHCode(0x13, 0x537));
|
||||
// From http://www.swetake.com/qr/qr11.html
|
||||
assertEquals(0x214, MatrixUtil.calculateBCHCode(0x1b, 0x537));
|
||||
|
||||
// Encoding of version information.
|
||||
// From Appendix D in JISX0510:2004 (p 68)
|
||||
assertEquals(0xc94, MatrixUtil.calculateBCHCode(7, 0x1f25));
|
||||
assertEquals(0x5bc, MatrixUtil.calculateBCHCode(8, 0x1f25));
|
||||
assertEquals(0xa99, MatrixUtil.calculateBCHCode(9, 0x1f25));
|
||||
assertEquals(0x4d3, MatrixUtil.calculateBCHCode(10, 0x1f25));
|
||||
assertEquals(0x9a6, MatrixUtil.calculateBCHCode(20, 0x1f25));
|
||||
assertEquals(0xd75, MatrixUtil.calculateBCHCode(30, 0x1f25));
|
||||
assertEquals(0xc69, MatrixUtil.calculateBCHCode(40, 0x1f25));
|
||||
}
|
||||
|
||||
// We don't test a lot of cases in this function since we've already
|
||||
// tested them in TEST(calculateBCHCode).
|
||||
@Test
|
||||
public void testMakeVersionInfoBits() throws WriterException {
|
||||
// From Appendix D in JISX0510:2004 (p 68)
|
||||
BitArray bits = new BitArray();
|
||||
MatrixUtil.makeVersionInfoBits(Version.getVersionForNumber(7), bits);
|
||||
assertEquals(" ...XXXXX ..X..X.X ..", bits.toString());
|
||||
}
|
||||
|
||||
// We don't test a lot of cases in this function since we've already
|
||||
// tested them in TEST(calculateBCHCode).
|
||||
@Test
|
||||
public void testMakeTypeInfoInfoBits() throws WriterException {
|
||||
// From Appendix C in JISX0510:2004 (p 65)
|
||||
BitArray bits = new BitArray();
|
||||
MatrixUtil.makeTypeInfoBits(ErrorCorrectionLevel.M, 5, bits);
|
||||
assertEquals(" X......X X..XXX.", bits.toString());
|
||||
}
|
||||
}
|
||||
128
src/qrcode/encoder/QRCodeTestCase.java
Normal file
128
src/qrcode/encoder/QRCodeTestCase.java
Normal file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* 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.qrcode.encoder;
|
||||
|
||||
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
|
||||
import com.google.zxing.qrcode.decoder.Mode;
|
||||
import com.google.zxing.qrcode.decoder.Version;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author satorux@google.com (Satoru Takabayashi) - creator
|
||||
* @author mysen@google.com (Chris Mysen) - ported from C++
|
||||
*/
|
||||
public final class QRCodeTestCase extends Assert {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
QRCode qrCode = new QRCode();
|
||||
|
||||
// First, test simple setters and getters.
|
||||
// We use numbers of version 7-H.
|
||||
qrCode.setMode(Mode.BYTE);
|
||||
qrCode.setECLevel(ErrorCorrectionLevel.H);
|
||||
qrCode.setVersion(Version.getVersionForNumber(7));
|
||||
qrCode.setMaskPattern(3);
|
||||
|
||||
assertSame(Mode.BYTE, qrCode.getMode());
|
||||
assertSame(ErrorCorrectionLevel.H, qrCode.getECLevel());
|
||||
assertEquals(7, qrCode.getVersion().getVersionNumber());
|
||||
assertEquals(3, qrCode.getMaskPattern());
|
||||
|
||||
// Prepare the matrix.
|
||||
ByteMatrix matrix = new ByteMatrix(45, 45);
|
||||
// Just set bogus zero/one values.
|
||||
for (int y = 0; y < 45; ++y) {
|
||||
for (int x = 0; x < 45; ++x) {
|
||||
matrix.set(x, y, (y + x) % 2);
|
||||
}
|
||||
}
|
||||
|
||||
// Set the matrix.
|
||||
qrCode.setMatrix(matrix);
|
||||
assertSame(matrix, qrCode.getMatrix());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToString1() {
|
||||
QRCode qrCode = new QRCode();
|
||||
String expected =
|
||||
"<<\n" +
|
||||
" mode: null\n" +
|
||||
" ecLevel: null\n" +
|
||||
" version: null\n" +
|
||||
" maskPattern: -1\n" +
|
||||
" matrix: null\n" +
|
||||
">>\n";
|
||||
assertEquals(expected, qrCode.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToString2() {
|
||||
QRCode qrCode = new QRCode();
|
||||
qrCode.setMode(Mode.BYTE);
|
||||
qrCode.setECLevel(ErrorCorrectionLevel.H);
|
||||
qrCode.setVersion(Version.getVersionForNumber(1));
|
||||
qrCode.setMaskPattern(3);
|
||||
ByteMatrix matrix = new ByteMatrix(21, 21);
|
||||
for (int y = 0; y < 21; ++y) {
|
||||
for (int x = 0; x < 21; ++x) {
|
||||
matrix.set(x, y, (y + x) % 2);
|
||||
}
|
||||
}
|
||||
qrCode.setMatrix(matrix);
|
||||
String expected = "<<\n" +
|
||||
" mode: BYTE\n" +
|
||||
" ecLevel: H\n" +
|
||||
" version: 1\n" +
|
||||
" maskPattern: 3\n" +
|
||||
" matrix:\n" +
|
||||
" 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0\n" +
|
||||
" 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1\n" +
|
||||
" 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0\n" +
|
||||
" 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1\n" +
|
||||
" 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0\n" +
|
||||
" 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1\n" +
|
||||
" 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0\n" +
|
||||
" 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1\n" +
|
||||
" 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0\n" +
|
||||
" 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1\n" +
|
||||
" 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0\n" +
|
||||
" 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1\n" +
|
||||
" 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0\n" +
|
||||
" 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1\n" +
|
||||
" 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0\n" +
|
||||
" 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1\n" +
|
||||
" 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0\n" +
|
||||
" 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1\n" +
|
||||
" 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0\n" +
|
||||
" 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1\n" +
|
||||
" 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0\n" +
|
||||
">>\n";
|
||||
assertEquals(expected, qrCode.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsValidMaskPattern() {
|
||||
assertFalse(QRCode.isValidMaskPattern(-1));
|
||||
assertTrue(QRCode.isValidMaskPattern(0));
|
||||
assertTrue(QRCode.isValidMaskPattern(7));
|
||||
assertFalse(QRCode.isValidMaskPattern(8));
|
||||
}
|
||||
|
||||
}
|
||||
0
src/qrcode/mod.rs
Normal file
0
src/qrcode/mod.rs
Normal file
Reference in New Issue
Block a user