diff --git a/core/src/com/google/zxing/common/reedsolomon/ReedSolomonEncoder.java b/core/src/com/google/zxing/common/reedsolomon/ReedSolomonEncoder.java index c638b044b..e1b06d3a9 100644 --- a/core/src/com/google/zxing/common/reedsolomon/ReedSolomonEncoder.java +++ b/core/src/com/google/zxing/common/reedsolomon/ReedSolomonEncoder.java @@ -52,13 +52,21 @@ public final class ReedSolomonEncoder { public void encode(int[] toEncode, int ecBytes) { int dataBytes = toEncode.length - ecBytes; + if (dataBytes < 0) { + throw new IllegalArgumentException("Too few data bytes provided: " + dataBytes); + } GF256Poly generator = buildGenerator(ecBytes); int[] infoCoefficients = new int[dataBytes]; System.arraycopy(toEncode, 0, infoCoefficients, 0, dataBytes); GF256Poly info = new GF256Poly(field, infoCoefficients); info = info.multiplyByMonomial(ecBytes, 1); GF256Poly remainder = info.divide(generator)[1]; - System.arraycopy(remainder.getCoefficients(), 0, toEncode, dataBytes, ecBytes); + int[] coefficients = remainder.getCoefficients(); + if (coefficients.length < ecBytes) { + throw new RuntimeException("Coefficients array is smaller than EC array (" + + coefficients.length + " < " + ecBytes + ")"); + } + System.arraycopy(coefficients, 0, toEncode, dataBytes, ecBytes); } } diff --git a/core/src/com/google/zxing/qrcode/encoder/ByteArray.java b/core/src/com/google/zxing/qrcode/encoder/ByteArray.java index 8bfe06899..1b8fc5141 100644 --- a/core/src/com/google/zxing/qrcode/encoder/ByteArray.java +++ b/core/src/com/google/zxing/qrcode/encoder/ByteArray.java @@ -33,6 +33,11 @@ public final class ByteArray { size = 0; } + public ByteArray(int size) { + bytes = new byte[size]; + this.size = size; + } + public ByteArray(String string) { bytes = string.getBytes(); size = bytes.length; @@ -83,12 +88,12 @@ public final class ByteArray { } } - // This could probably be generalized to take a byte[] instead of a BitVector. - public void set(BitVector bits, int offset, int count) { + // Copy count bytes from array source starting at offset. + public void set(byte[] source, int offset, int count) { bytes = new byte[count]; size = count; for (int x = 0; x < count; x++) { - bytes[x] = (byte) bits.at(x + offset); + bytes[x] = source[offset + x]; } } diff --git a/core/src/com/google/zxing/qrcode/encoder/Encoder.java b/core/src/com/google/zxing/qrcode/encoder/Encoder.java index 8935c1819..8b4fce425 100644 --- a/core/src/com/google/zxing/qrcode/encoder/Encoder.java +++ b/core/src/com/google/zxing/qrcode/encoder/Encoder.java @@ -16,9 +16,9 @@ package com.google.zxing.qrcode.encoder; -import com.google.zxing.common.reedsolomon.ReedSolomonEncoder; -import com.google.zxing.common.reedsolomon.GF256; import com.google.zxing.common.ByteMatrix; +import com.google.zxing.common.reedsolomon.GF256; +import com.google.zxing.common.reedsolomon.ReedSolomonEncoder; import java.util.Vector; @@ -579,12 +579,10 @@ private static final ECPolyInfo kECPolynomials[] = { num_data_bytes_in_block, num_ec_bytes_in_block); ByteArray data_bytes = new ByteArray(); - ByteArray ec_bytes = new ByteArray(); + data_bytes.set(bits.getArray(), data_bytes_offset, num_data_bytes_in_block[0]); + ByteArray ec_bytes = GenerateECBytes(data_bytes, num_ec_bytes_in_block[0]); blocks.addElement(new BlockPair(data_bytes, ec_bytes)); - data_bytes.set(bits, data_bytes_offset, num_data_bytes_in_block[0]); - GenerateECBytes(data_bytes, num_ec_bytes_in_block[0], ec_bytes); - max_num_data_bytes = Math.max(max_num_data_bytes, data_bytes.size()); max_num_ec_bytes = Math.max(max_num_ec_bytes, ec_bytes.size()); data_bytes_offset += num_data_bytes_in_block[0]; @@ -617,16 +615,19 @@ private static final ECPolyInfo kECPolynomials[] = { return false; } - static void GenerateECBytes(ByteArray data_bytes, int num_ec_bytes_in_block, ByteArray ec_bytes) { + static ByteArray GenerateECBytes(ByteArray data_bytes, int num_ec_bytes_in_block) { int numDataBytes = data_bytes.size(); - int[] toEncode = new int[numDataBytes + ec_bytes.size()]; + int[] toEncode = new int[numDataBytes + num_ec_bytes_in_block]; for (int i = 0; i < numDataBytes; i++) { toEncode[i] = data_bytes.at(i); } new ReedSolomonEncoder(GF256.QR_CODE_FIELD).encode(toEncode, num_ec_bytes_in_block); - for (int i = 0; i < ec_bytes.size(); i++) { + + ByteArray ec_bytes = new ByteArray(num_ec_bytes_in_block); + for (int i = 0; i < num_ec_bytes_in_block; i++) { ec_bytes.set(i, toEncode[numDataBytes + i]); } + return ec_bytes; } // Append mode info. On success, store the result in "bits" and return true. On error, return diff --git a/core/test/src/com/google/zxing/qrcode/encoder/EncoderTestCase.java b/core/test/src/com/google/zxing/qrcode/encoder/EncoderTestCase.java index f6a9aedb6..5a1107b3a 100644 --- a/core/test/src/com/google/zxing/qrcode/encoder/EncoderTestCase.java +++ b/core/test/src/com/google/zxing/qrcode/encoder/EncoderTestCase.java @@ -512,9 +512,8 @@ public final class EncoderTestCase extends TestCase { // http://www.swetake.com/qr/qr9.html public void testGenerateECBytes() { { - ByteArray ec_bytes = new ByteArray(); final byte[] data_bytes = {32, 65, (byte)205, 69, 41, (byte)220, 46, (byte)128, (byte)236}; - Encoder.GenerateECBytes(new ByteArray(data_bytes), 17, ec_bytes); + ByteArray ec_bytes = Encoder.GenerateECBytes(new ByteArray(data_bytes), 17); final byte[] expected = { 42, (byte)159, 74, (byte)221, (byte)244, (byte)169, (byte)239, (byte)150, (byte)138, 70, (byte)237, 85, (byte)224, 96, 74, (byte)219, 61 @@ -522,10 +521,9 @@ public final class EncoderTestCase extends TestCase { assertEquals(new ByteArray(expected), ec_bytes); } { - ByteArray ec_bytes = new ByteArray(); final byte[] data_bytes = {67, 70, 22, 38, 54, 70, 86, 102, 118, (byte)134, (byte)150, (byte)166, (byte)182, (byte)198, (byte)214}; - Encoder.GenerateECBytes(new ByteArray(data_bytes), 18, ec_bytes); + ByteArray ec_bytes = Encoder.GenerateECBytes(new ByteArray(data_bytes), 18); final byte[] expected = { (byte)175, 80, (byte)155, 64, (byte)178, 45, (byte)214, (byte)233, 65, (byte)209, 12, (byte)155, 117, 31, (byte)140, (byte)214, 27, (byte)187 @@ -534,9 +532,8 @@ public final class EncoderTestCase extends TestCase { } { // High-order zero cofficient case. - ByteArray ec_bytes = new ByteArray(); final byte[] data_bytes = {32, 49, (byte)205, 69, 42, 20, 0, (byte)236, 17}; - Encoder.GenerateECBytes(new ByteArray(data_bytes), 17, ec_bytes); + ByteArray ec_bytes = Encoder.GenerateECBytes(new ByteArray(data_bytes), 17); final byte[] expected = { 0, 3, (byte)130, (byte)179, (byte)194, 0, 55, (byte)211, 110, 79, 98, 72, (byte)170, 96, (byte)211, (byte)137, (byte)213