mirror of
https://github.com/zxing/zxing.git
synced 2025-03-05 20:48:51 -08:00
Made several good fixes to and because of the unit tests. Turns out the EC array was never being set to the right size. I've now established that the Reed Solomon code is generating one fewer coefficient than the layer above it asked for.
git-svn-id: https://zxing.googlecode.com/svn/trunk@726 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
parent
b5dbec4469
commit
c95fe48a76
|
@ -52,13 +52,21 @@ public final class ReedSolomonEncoder {
|
||||||
|
|
||||||
public void encode(int[] toEncode, int ecBytes) {
|
public void encode(int[] toEncode, int ecBytes) {
|
||||||
int dataBytes = toEncode.length - ecBytes;
|
int dataBytes = toEncode.length - ecBytes;
|
||||||
|
if (dataBytes < 0) {
|
||||||
|
throw new IllegalArgumentException("Too few data bytes provided: " + dataBytes);
|
||||||
|
}
|
||||||
GF256Poly generator = buildGenerator(ecBytes);
|
GF256Poly generator = buildGenerator(ecBytes);
|
||||||
int[] infoCoefficients = new int[dataBytes];
|
int[] infoCoefficients = new int[dataBytes];
|
||||||
System.arraycopy(toEncode, 0, infoCoefficients, 0, dataBytes);
|
System.arraycopy(toEncode, 0, infoCoefficients, 0, dataBytes);
|
||||||
GF256Poly info = new GF256Poly(field, infoCoefficients);
|
GF256Poly info = new GF256Poly(field, infoCoefficients);
|
||||||
info = info.multiplyByMonomial(ecBytes, 1);
|
info = info.multiplyByMonomial(ecBytes, 1);
|
||||||
GF256Poly remainder = info.divide(generator)[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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,11 @@ public final class ByteArray {
|
||||||
size = 0;
|
size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ByteArray(int size) {
|
||||||
|
bytes = new byte[size];
|
||||||
|
this.size = size;
|
||||||
|
}
|
||||||
|
|
||||||
public ByteArray(String string) {
|
public ByteArray(String string) {
|
||||||
bytes = string.getBytes();
|
bytes = string.getBytes();
|
||||||
size = bytes.length;
|
size = bytes.length;
|
||||||
|
@ -83,12 +88,12 @@ public final class ByteArray {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This could probably be generalized to take a byte[] instead of a BitVector.
|
// Copy count bytes from array source starting at offset.
|
||||||
public void set(BitVector bits, int offset, int count) {
|
public void set(byte[] source, int offset, int count) {
|
||||||
bytes = new byte[count];
|
bytes = new byte[count];
|
||||||
size = count;
|
size = count;
|
||||||
for (int x = 0; x < count; x++) {
|
for (int x = 0; x < count; x++) {
|
||||||
bytes[x] = (byte) bits.at(x + offset);
|
bytes[x] = source[offset + x];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,9 +16,9 @@
|
||||||
|
|
||||||
package com.google.zxing.qrcode.encoder;
|
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.ByteMatrix;
|
||||||
|
import com.google.zxing.common.reedsolomon.GF256;
|
||||||
|
import com.google.zxing.common.reedsolomon.ReedSolomonEncoder;
|
||||||
|
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
|
|
||||||
|
@ -579,12 +579,10 @@ private static final ECPolyInfo kECPolynomials[] = {
|
||||||
num_data_bytes_in_block, num_ec_bytes_in_block);
|
num_data_bytes_in_block, num_ec_bytes_in_block);
|
||||||
|
|
||||||
ByteArray data_bytes = new ByteArray();
|
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));
|
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_data_bytes = Math.max(max_num_data_bytes, data_bytes.size());
|
||||||
max_num_ec_bytes = Math.max(max_num_ec_bytes, ec_bytes.size());
|
max_num_ec_bytes = Math.max(max_num_ec_bytes, ec_bytes.size());
|
||||||
data_bytes_offset += num_data_bytes_in_block[0];
|
data_bytes_offset += num_data_bytes_in_block[0];
|
||||||
|
@ -617,16 +615,19 @@ private static final ECPolyInfo kECPolynomials[] = {
|
||||||
return false;
|
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 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++) {
|
for (int i = 0; i < numDataBytes; i++) {
|
||||||
toEncode[i] = data_bytes.at(i);
|
toEncode[i] = data_bytes.at(i);
|
||||||
}
|
}
|
||||||
new ReedSolomonEncoder(GF256.QR_CODE_FIELD).encode(toEncode, num_ec_bytes_in_block);
|
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]);
|
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
|
// Append mode info. On success, store the result in "bits" and return true. On error, return
|
||||||
|
|
|
@ -512,9 +512,8 @@ public final class EncoderTestCase extends TestCase {
|
||||||
// http://www.swetake.com/qr/qr9.html
|
// http://www.swetake.com/qr/qr9.html
|
||||||
public void testGenerateECBytes() {
|
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};
|
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 = {
|
final byte[] expected = {
|
||||||
42, (byte)159, 74, (byte)221, (byte)244, (byte)169, (byte)239, (byte)150, (byte)138, 70,
|
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
|
(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);
|
assertEquals(new ByteArray(expected), ec_bytes);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
ByteArray ec_bytes = new ByteArray();
|
|
||||||
final byte[] data_bytes = {67, 70, 22, 38, 54, 70, 86, 102, 118,
|
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};
|
(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 = {
|
final byte[] expected = {
|
||||||
(byte)175, 80, (byte)155, 64, (byte)178, 45, (byte)214, (byte)233, 65, (byte)209, 12,
|
(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
|
(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.
|
// 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};
|
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 = {
|
final byte[] expected = {
|
||||||
0, 3, (byte)130, (byte)179, (byte)194, 0, 55, (byte)211, 110, 79, 98, 72, (byte)170, 96,
|
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
|
(byte)211, (byte)137, (byte)213
|
||||||
|
|
Loading…
Reference in a new issue