Big rename of variables and method to have more standard Java names

git-svn-id: https://zxing.googlecode.com/svn/trunk@769 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
srowen 2008-12-02 00:31:10 +00:00
parent 10a90bfecf
commit 416193ff9a
10 changed files with 794 additions and 793 deletions

View file

@ -67,14 +67,14 @@ public final class QRCodeWriter implements Writer {
}
QRCode code = new QRCode();
Encoder.Encode(new ByteArray(contents), errorCorrectionLevel, code);
Encoder.encode(new ByteArray(contents), errorCorrectionLevel, code);
return renderResult(code, width, height);
}
// Note that the input matrix uses 0 == white, 1 == black, while the output matrix uses
// 0 == black, 255 == white (i.e. an 8 bit greyscale bitmap).
private ByteMatrix renderResult(QRCode code, final int width, final int height) {
ByteMatrix input = code.matrix();
ByteMatrix input = code.getMatrix();
int inputWidth = input.width();
int inputHeight = input.height();
int qrWidth = inputWidth + (QUIET_ZONE_SIZE * 2);

View file

@ -61,39 +61,39 @@ public final class BitVector {
if (!(bit == 0 || bit == 1)) {
throw new IllegalArgumentException("Bad bit");
}
final int num_bits_in_last_byte = sizeInBits & 0x7;
final int numBitsInLastByte = sizeInBits & 0x7;
// We'll expand array if we don't have bits in the last byte.
if (num_bits_in_last_byte == 0) {
if (numBitsInLastByte == 0) {
appendByte(0);
sizeInBits -= 8;
}
// Modify the last byte.
array[sizeInBits >> 3] |= (bit << (7 - num_bits_in_last_byte));
array[sizeInBits >> 3] |= (bit << (7 - numBitsInLastByte));
++sizeInBits;
}
// Append "num_bits" bits in "value" to the bit vector.
// REQUIRES: 0<= num_bits <= 32.
// Append "numBits" bits in "value" to the bit vector.
// REQUIRES: 0<= numBits <= 32.
//
// Examples:
// - appendBits(0x00, 1) adds 0.
// - appendBits(0x00, 4) adds 0000.
// - appendBits(0xff, 8) adds 11111111.
public void appendBits(final int value, final int num_bits) {
if (num_bits < 0 || num_bits > 32) {
public void appendBits(final int value, final int numBits) {
if (numBits < 0 || numBits > 32) {
throw new IllegalArgumentException("Num bits must be between 0 and 32");
}
int num_bits_left = num_bits;
while (num_bits_left > 0) {
int numBitsLeft = numBits;
while (numBitsLeft > 0) {
// Optimization for byte-oriented appending.
if ((sizeInBits & 0x7) == 0 && num_bits_left >= 8) {
final int newByte = (value >> (num_bits_left - 8)) & 0xff;
if ((sizeInBits & 0x7) == 0 && numBitsLeft >= 8) {
final int newByte = (value >> (numBitsLeft - 8)) & 0xff;
appendByte(newByte);
num_bits_left -= 8;
numBitsLeft -= 8;
} else {
final int bit = (value >> (num_bits_left - 1)) & 1;
final int bit = (value >> (numBitsLeft - 1)) & 1;
appendBit(bit);
--num_bits_left;
--numBitsLeft;
}
}
}

View file

@ -31,7 +31,7 @@ import java.util.Vector;
public final class Encoder {
// The original table is defined in the table 5 of JISX0510:2004 (p.19).
private static final int kAlphanumericTable[] = {
private static final int[] ALPHANUMERIC_TABLE = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0x00-0x0f
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0x10-0x1f
36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43, // 0x20-0x2f
@ -42,20 +42,20 @@ public final class Encoder {
private static final class RSBlockInfo {
final int num_bytes;
final int[][] block_info;
final int numBytes;
final int[][] blockInfo;
public RSBlockInfo(int num_bytes, int[][] block_info) {
this.num_bytes = num_bytes;
this.block_info = block_info;
public RSBlockInfo(int numBytes, int[][] blockInfo) {
this.numBytes = numBytes;
this.blockInfo = blockInfo;
}
}
// The table is from table 12 of JISX0510:2004 (p. 30). The "block_info" parts are ordered by
// L, M, Q, H. Within each block_info, the 0th element is num_ec_bytes, and the 1st element is
// num_rs_blocks. The table was doublechecked by komatsu.
private static final RSBlockInfo kRSBlockTable[] = {
// The table is from table 12 of JISX0510:2004 (p. 30). The "blockInfo" parts are ordered by
// L, M, Q, H. Within each blockInfo, the 0th element is getNumECBytes, and the 1st element is
// getNumRSBlocks. The table was doublechecked by komatsu.
private static final RSBlockInfo[] RS_BLOCK_TABLE = {
new RSBlockInfo( 26, new int[][]{ { 7, 1}, { 10, 1}, { 13, 1}, { 17, 1}}), // Version 1
new RSBlockInfo( 44, new int[][]{ { 10, 1}, { 16, 1}, { 22, 1}, { 28, 1}}), // Version 2
new RSBlockInfo( 70, new int[][]{ { 15, 1}, { 26, 1}, { 36, 2}, { 44, 2}}), // Version 3
@ -118,59 +118,59 @@ public final class Encoder {
}
// Encode "bytes" with the error correction level "ec_level". The encoding mode will be chosen
// internally by ChooseMode(). On success, store the result in "qr_code" and return true. On
// Encode "bytes" with the error correction level "getECLevel". The encoding mode will be chosen
// internally by chooseMode(). On success, store the result in "qrCode" and return true. On
// error, return false. We recommend you to use QRCode.EC_LEVEL_L (the lowest level) for
// "ec_level" since our primary use is to show QR code on desktop screens. We don't need very
// "getECLevel" since our primary use is to show QR code on desktop screens. We don't need very
// strong error correction for this purpose.
//
// Note that there is no way to encode bytes in MODE_KANJI. We might want to add EncodeWithMode()
// with which clients can specify the encoding mode. For now, we don't need the functionality.
public static void Encode(final ByteArray bytes, int ec_level, QRCode qr_code) throws WriterException {
public static void encode(final ByteArray bytes, int ecLevel, QRCode qrCode) throws WriterException {
// Step 1: Choose the mode (encoding).
final int mode = ChooseMode(bytes);
final int mode = chooseMode(bytes);
// Step 2: Append "bytes" into "data_bits" in appropriate encoding.
BitVector data_bits = new BitVector();
AppendBytes(bytes, mode, data_bits);
// Step 3: Initialize QR code that can contain "data_bits".
final int num_input_bytes = data_bits.sizeInBytes();
InitQRCode(num_input_bytes, ec_level, mode, qr_code);
// Step 2: Append "bytes" into "dataBits" in appropriate encoding.
BitVector dataBits = new BitVector();
appendBytes(bytes, mode, dataBits);
// Step 3: Initialize QR code that can contain "dataBits".
final int numInputBytes = dataBits.sizeInBytes();
initQRCode(numInputBytes, ecLevel, mode, qrCode);
// Step 4: Build another bit vector that contains header and data.
BitVector header_and_data_bits = new BitVector();
AppendModeInfo(qr_code.mode(), header_and_data_bits);
AppendLengthInfo(bytes.size(), qr_code.version(), qr_code.mode(), header_and_data_bits);
header_and_data_bits.appendBitVector(data_bits);
BitVector headerAndDataBits = new BitVector();
appendModeInfo(qrCode.getMode(), headerAndDataBits);
appendLengthInfo(bytes.size(), qrCode.getVersion(), qrCode.getMode(), headerAndDataBits);
headerAndDataBits.appendBitVector(dataBits);
// Step 5: Terminate the bits properly.
TerminateBits(qr_code.num_data_bytes(), header_and_data_bits);
terminateBits(qrCode.getNumDataBytes(), headerAndDataBits);
// Step 6: Interleave data bits with error correction code.
BitVector final_bits = new BitVector();
InterleaveWithECBytes(header_and_data_bits, qr_code.num_total_bytes(), qr_code.num_data_bytes(),
qr_code.num_rs_blocks(), final_bits);
BitVector finalBits = new BitVector();
interleaveWithECBytes(headerAndDataBits, qrCode.getNumTotalBytes(), qrCode.getNumDataBytes(),
qrCode.getNumRSBlocks(), finalBits);
// Step 7: Choose the mask pattern and set to "qr_code".
ByteMatrix matrix = new ByteMatrix(qr_code.matrix_width(), qr_code.matrix_width());
qr_code.set_mask_pattern(ChooseMaskPattern(final_bits, qr_code.ec_level(), qr_code.version(),
// Step 7: Choose the mask pattern and set to "qrCode".
ByteMatrix matrix = new ByteMatrix(qrCode.getMatrixWidth(), qrCode.getMatrixWidth());
qrCode.setMaskPattern(chooseMaskPattern(finalBits, qrCode.getECLevel(), qrCode.getVersion(),
matrix));
// Step 8. Build the matrix and set it to "qr_code".
MatrixUtil.BuildMatrix(final_bits, qr_code.ec_level(), qr_code.version(),
qr_code.mask_pattern(), matrix);
qr_code.set_matrix(matrix);
// Step 8. Build the matrix and set it to "qrCode".
MatrixUtil.buildMatrix(finalBits, qrCode.getECLevel(), qrCode.getVersion(),
qrCode.getMaskPattern(), matrix);
qrCode.setMatrix(matrix);
// Step 9. Make sure we have a valid QR Code.
if (!qr_code.IsValid()) {
throw new WriterException("Invalid QR code: " + qr_code.toString());
if (!qrCode.isValid()) {
throw new WriterException("Invalid QR code: " + qrCode.toString());
}
}
// Return the code point of the table used in alphanumeric mode. Return -1 if there is no
// corresponding code in the table.
static int GetAlphanumericCode(int code) {
if (code < kAlphanumericTable.length) {
return kAlphanumericTable[code];
static int getAlphanumericCode(int code) {
if (code < ALPHANUMERIC_TABLE.length) {
return ALPHANUMERIC_TABLE[code];
}
return -1;
}
@ -183,25 +183,25 @@ public final class Encoder {
// interpreted as one character in Shift_JIS, but also two characters in ISO-8859-1.
//
// JAVAPORT: This MODE_KANJI limitation sounds like a problem for us.
public static int ChooseMode(final ByteArray bytes) throws WriterException {
boolean has_numeric = false;
boolean has_alphanumeric = false;
boolean has_other = false;
public static int chooseMode(final ByteArray bytes) throws WriterException {
boolean hasNumeric = false;
boolean hasAlphanumeric = false;
boolean hasOther = false;
for (int i = 0; i < bytes.size(); ++i) {
final int oneByte = bytes.at(i);
if (oneByte >= '0' && oneByte <= '9') {
has_numeric = true;
} else if (GetAlphanumericCode(oneByte) != -1) {
has_alphanumeric = true;
hasNumeric = true;
} else if (getAlphanumericCode(oneByte) != -1) {
hasAlphanumeric = true;
} else {
has_other = true;
hasOther = true;
}
}
if (has_other) {
if (hasOther) {
return QRCode.MODE_8BIT_BYTE;
} else if (has_alphanumeric) {
} else if (hasAlphanumeric) {
return QRCode.MODE_ALPHANUMERIC;
} else if (has_numeric) {
} else if (hasNumeric) {
return QRCode.MODE_NUMERIC;
}
// "bytes" must be empty to reach here.
@ -211,61 +211,60 @@ public final class Encoder {
return QRCode.MODE_8BIT_BYTE;
}
private static int ChooseMaskPattern(final BitVector bits, int ec_level, int version,
private static int chooseMaskPattern(final BitVector bits, int ecLevel, int version,
ByteMatrix matrix) throws WriterException {
if (!QRCode.IsValidMatrixWidth(matrix.width())) {
if (!QRCode.isValidMatrixWidth(matrix.width())) {
throw new WriterException("Invalid matrix width: " + matrix.width());
}
int min_penalty = Integer.MAX_VALUE; // Lower penalty is better.
int best_mask_pattern = -1;
int minPenalty = Integer.MAX_VALUE; // Lower penalty is better.
int bestMaskPattern = -1;
// We try all mask patterns to choose the best one.
for (int i = 0; i < QRCode.kNumMaskPatterns; ++i) {
final int mask_pattern = i;
MatrixUtil.BuildMatrix(bits, ec_level, version, mask_pattern, matrix);
final int penalty = MaskUtil.CalculateMaskPenalty(matrix);
if (penalty < min_penalty) {
min_penalty = penalty;
best_mask_pattern = mask_pattern;
for (int maskPattern = 0; maskPattern < QRCode.NUM_MASK_PATTERNS; maskPattern++) {
MatrixUtil.buildMatrix(bits, ecLevel, version, maskPattern, matrix);
final int penalty = MaskUtil.calculateMaskPenalty(matrix);
if (penalty < minPenalty) {
minPenalty = penalty;
bestMaskPattern = maskPattern;
}
}
return best_mask_pattern;
return bestMaskPattern;
}
// Initialize "qr_code" according to "num_input_bytes", "ec_level", and "mode". On success, modify
// "qr_code" and return true. On error, return false.
private static void InitQRCode(int num_input_bytes, int ec_level, int mode, QRCode qr_code) throws WriterException {
qr_code.set_ec_level(ec_level);
qr_code.set_mode(mode);
// Initialize "qrCode" according to "numInputBytes", "getECLevel", and "mode". On success, modify
// "qrCode" and return true. On error, return false.
private static void initQRCode(int numInputBytes, int ecLevel, int mode, QRCode qrCode) throws WriterException {
qrCode.setECLevel(ecLevel);
qrCode.setMode(mode);
if (!QRCode.IsValidECLevel(ec_level)) {
throw new WriterException("Invalid EC level: " + ec_level);
if (!QRCode.isValidECLevel(ecLevel)) {
throw new WriterException("Invalid EC level: " + ecLevel);
}
// In the following comments, we use numbers of Version 7-H.
for (int i = 0; i < kRSBlockTable.length; ++i) {
final RSBlockInfo row = kRSBlockTable[i];
// num_bytes = 196
final int num_bytes = row.num_bytes;
// num_ec_bytes = 130
final int num_ec_bytes = row.block_info[ec_level][0];
// num_rs_blocks = 5
final int num_rs_blocks = row.block_info[ec_level][1];
// num_data_bytes = 196 - 130 = 66
final int num_data_bytes = num_bytes - num_ec_bytes;
// We want to choose the smallest version which can contain data of "num_input_bytes" + some
for (int i = 0; i < RS_BLOCK_TABLE.length; ++i) {
final RSBlockInfo row = RS_BLOCK_TABLE[i];
// numBytes = 196
final int numBytes = row.numBytes;
// getNumECBytes = 130
final int numEcBytes = row.blockInfo[ecLevel][0];
// getNumRSBlocks = 5
final int numRSBlocks = row.blockInfo[ecLevel][1];
// getNumDataBytes = 196 - 130 = 66
final int numDataBytes = numBytes - numEcBytes;
// We want to choose the smallest version which can contain data of "numInputBytes" + some
// extra bits for the header (mode info and length info). The header can be three bytes
// (precisely 4 + 16 bits) at most. Hence we do +3 here.
if (num_data_bytes >= num_input_bytes + 3) {
if (numDataBytes >= numInputBytes + 3) {
// Yay, we found the proper rs block info!
qr_code.set_version(i + 1);
qr_code.set_num_total_bytes(num_bytes);
qr_code.set_num_data_bytes(num_data_bytes);
qr_code.set_num_rs_blocks(num_rs_blocks);
// num_ec_bytes = 196 - 66 = 130
qr_code.set_num_ec_bytes(num_bytes - num_data_bytes);
// num_matrix_width = 21 + 6 * 4 = 45
qr_code.set_matrix_width(21 + i * 4);
qrCode.setVersion(i + 1);
qrCode.setNumTotalBytes(numBytes);
qrCode.setNumDataBytes(numDataBytes);
qrCode.setNumRSBlocks(numRSBlocks);
// getNumECBytes = 196 - 66 = 130
qrCode.setNumECBytes(numBytes - numDataBytes);
// matrix width = 21 + 6 * 4 = 45
qrCode.setMatrixWidth(21 + i * 4);
return;
}
}
@ -273,8 +272,8 @@ public final class Encoder {
}
// Terminate bits as described in 8.4.8 and 8.4.9 of JISX0510:2004 (p.24).
static void TerminateBits(int num_data_bytes, BitVector bits) throws WriterException {
final int capacity = num_data_bytes * 8;
static void terminateBits(int numDataBytes, BitVector bits) throws WriterException {
final int capacity = numDataBytes * 8;
if (bits.size() > capacity) {
throw new WriterException("data bits cannot fit in the QR Code" + bits.size() + " > " + capacity);
}
@ -282,11 +281,11 @@ public final class Encoder {
for (int i = 0; i < 4 && bits.size() < capacity; ++i) {
bits.appendBit(0);
}
final int num_bits_in_last_byte = bits.size() % 8;
final int numBitsInLastByte = bits.size() % 8;
// If the last byte isn't 8-bit aligned, we'll add padding bits.
if (num_bits_in_last_byte > 0) {
final int num_padding_bits = 8 - num_bits_in_last_byte;
for (int i = 0; i < num_padding_bits; ++i) {
if (numBitsInLastByte > 0) {
final int numPaddingBits = 8 - numBitsInLastByte;
for (int i = 0; i < numPaddingBits; ++i) {
bits.appendBit(0);
}
}
@ -295,8 +294,8 @@ public final class Encoder {
throw new WriterException("Number of bits is not a multiple of 8");
}
// If we have more space, we'll fill the space with padding patterns defined in 8.4.9 (p.24).
final int num_padding_bytes = num_data_bytes - bits.sizeInBytes();
for (int i = 0; i < num_padding_bytes; ++i) {
final int numPaddingBytes = numDataBytes - bits.sizeInBytes();
for (int i = 0; i < numPaddingBytes; ++i) {
if (i % 2 == 0) {
bits.appendBits(0xec, 8);
} else {
@ -308,190 +307,188 @@ public final class Encoder {
}
}
// Get number of data bytes and number of error correction bytes for block id "block_id". Store
// the result in "num_data_bytes_in_block", and "num_ec_bytes_in_block". See table 12 in 8.5.1 of
// Get number of data bytes and number of error correction bytes for block id "blockID". Store
// the result in "numDataBytesInBlock", and "numECBytesInBlock". See table 12 in 8.5.1 of
// JISX0510:2004 (p.30)
static void GetNumDataBytesAndNumECBytesForBlockID(int num_total_bytes, int num_data_bytes,
int num_rs_blocks, int block_id, int[] num_data_bytes_in_block,
int[] num_ec_bytes_in_block) throws WriterException {
if (block_id >= num_rs_blocks) {
static void getNumDataBytesAndNumECBytesForBlockID(int numTotalBytes, int numDataBytes,
int numRSBlocks, int blockID, int[] numDataBytesInBlock,
int[] numECBytesInBlock) throws WriterException {
if (blockID >= numRSBlocks) {
throw new WriterException("Block ID too large");
}
// num_rs_blocks_in_group2 = 196 % 5 = 1
final int num_rs_blocks_in_group2 = num_total_bytes % num_rs_blocks;
// num_rs_blocks_in_group1 = 5 - 1 = 4
final int num_rs_blocks_in_group1 = num_rs_blocks - num_rs_blocks_in_group2;
// num_total_bytes_in_group1 = 196 / 5 = 39
final int num_total_bytes_in_group1 = num_total_bytes / num_rs_blocks;
// num_total_bytes_in_group2 = 39 + 1 = 40
final int num_total_bytes_in_group2 = num_total_bytes_in_group1 + 1;
// num_data_bytes_in_group1 = 66 / 5 = 13
final int num_data_bytes_in_group1 = num_data_bytes / num_rs_blocks;
// num_data_bytes_in_group2 = 13 + 1 = 14
final int num_data_bytes_in_group2 = num_data_bytes_in_group1 + 1;
// num_ec_bytes_in_group1 = 39 - 13 = 26
final int num_ec_bytes_in_group1 = num_total_bytes_in_group1 -
num_data_bytes_in_group1;
// num_ec_bytes_in_group2 = 40 - 14 = 26
final int num_ec_bytes_in_group2 = num_total_bytes_in_group2 -
num_data_bytes_in_group2;
// numRsBlocksInGroup2 = 196 % 5 = 1
final int numRsBlocksInGroup2 = numTotalBytes % numRSBlocks;
// numRsBlocksInGroup1 = 5 - 1 = 4
final int numRsBlocksInGroup1 = numRSBlocks - numRsBlocksInGroup2;
// numTotalBytesInGroup1 = 196 / 5 = 39
final int numTotalBytesInGroup1 = numTotalBytes / numRSBlocks;
// numTotalBytesInGroup2 = 39 + 1 = 40
final int numTotalBytesInGroup2 = numTotalBytesInGroup1 + 1;
// numDataBytesInGroup1 = 66 / 5 = 13
final int numDataBytesInGroup1 = numDataBytes / numRSBlocks;
// numDataBytesInGroup2 = 13 + 1 = 14
final int numDataBytesInGroup2 = numDataBytesInGroup1 + 1;
// numEcBytesInGroup1 = 39 - 13 = 26
final int numEcBytesInGroup1 = numTotalBytesInGroup1 - numDataBytesInGroup1;
// numEcBytesInGroup2 = 40 - 14 = 26
final int numEcBytesInGroup2 = numTotalBytesInGroup2 - numDataBytesInGroup2;
// Sanity checks.
// 26 = 26
if (num_ec_bytes_in_group1 != num_ec_bytes_in_group2) {
if (numEcBytesInGroup1 != numEcBytesInGroup2) {
throw new WriterException("EC bytes mismatch");
}
// 5 = 4 + 1.
if (num_rs_blocks != num_rs_blocks_in_group1 + num_rs_blocks_in_group2) {
if (numRSBlocks != numRsBlocksInGroup1 + numRsBlocksInGroup2) {
throw new WriterException("RS blocks mismatch");
}
// 196 = (13 + 26) * 4 + (14 + 26) * 1
if (num_total_bytes !=
((num_data_bytes_in_group1 + num_ec_bytes_in_group1) *
num_rs_blocks_in_group1) +
((num_data_bytes_in_group2 + num_ec_bytes_in_group2) *
num_rs_blocks_in_group2)) {
if (numTotalBytes !=
((numDataBytesInGroup1 + numEcBytesInGroup1) *
numRsBlocksInGroup1) +
((numDataBytesInGroup2 + numEcBytesInGroup2) *
numRsBlocksInGroup2)) {
throw new WriterException("Total bytes mismatch");
}
if (block_id < num_rs_blocks_in_group1) {
num_data_bytes_in_block[0] = num_data_bytes_in_group1;
num_ec_bytes_in_block[0] = num_ec_bytes_in_group1;
if (blockID < numRsBlocksInGroup1) {
numDataBytesInBlock[0] = numDataBytesInGroup1;
numECBytesInBlock[0] = numEcBytesInGroup1;
} else {
num_data_bytes_in_block[0] = num_data_bytes_in_group2;
num_ec_bytes_in_block[0] = num_ec_bytes_in_group2;
numDataBytesInBlock[0] = numDataBytesInGroup2;
numECBytesInBlock[0] = numEcBytesInGroup2;
}
}
// Interleave "bits" with corresponding error correction bytes. On success, store the result in
// "result" and return true. On error, return false. The interleave rule is complicated. See 8.6
// of JISX0510:2004 (p.37) for details.
static void InterleaveWithECBytes(final BitVector bits, int num_total_bytes,
int num_data_bytes, int num_rs_blocks, BitVector result) throws WriterException {
static void interleaveWithECBytes(final BitVector bits, int numTotalBytes,
int numDataBytes, int numRSBlocks, BitVector result) throws WriterException {
// "bits" must have "num_data_bytes" bytes of data.
if (bits.sizeInBytes() != num_data_bytes) {
// "bits" must have "getNumDataBytes" bytes of data.
if (bits.sizeInBytes() != numDataBytes) {
throw new WriterException("Number of bits and data bytes does not match");
}
// Step 1. Divide data bytes into blocks and generate error correction bytes for them. We'll
// store the divided data bytes blocks and error correction bytes blocks into "blocks".
int data_bytes_offset = 0;
int max_num_data_bytes = 0;
int max_num_ec_bytes = 0;
int dataBytesOffset = 0;
int maxNumDataBytes = 0;
int maxNumEcBytes = 0;
// Since, we know the number of reedsolmon blocks, we can initialize the vector with the number.
Vector blocks = new Vector(num_rs_blocks);
Vector blocks = new Vector(numRSBlocks);
for (int i = 0; i < num_rs_blocks; ++i) {
int[] num_data_bytes_in_block = new int[1];
int[] num_ec_bytes_in_block = new int[1];
GetNumDataBytesAndNumECBytesForBlockID(
num_total_bytes, num_data_bytes, num_rs_blocks, i,
num_data_bytes_in_block, num_ec_bytes_in_block);
for (int i = 0; i < numRSBlocks; ++i) {
int[] numDataBytesInBlock = new int[1];
int[] numEcBytesInBlock = new int[1];
getNumDataBytesAndNumECBytesForBlockID(
numTotalBytes, numDataBytes, numRSBlocks, i,
numDataBytesInBlock, numEcBytesInBlock);
ByteArray data_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));
ByteArray dataBytes = new ByteArray();
dataBytes.set(bits.getArray(), dataBytesOffset, numDataBytesInBlock[0]);
ByteArray ecBytes = generateECBytes(dataBytes, numEcBytesInBlock[0]);
blocks.addElement(new BlockPair(dataBytes, ecBytes));
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];
maxNumDataBytes = Math.max(maxNumDataBytes, dataBytes.size());
maxNumEcBytes = Math.max(maxNumEcBytes, ecBytes.size());
dataBytesOffset += numDataBytesInBlock[0];
}
if (num_data_bytes != data_bytes_offset) {
if (numDataBytes != dataBytesOffset) {
throw new WriterException("Data bytes does not match offset");
}
// First, place data blocks.
for (int i = 0; i < max_num_data_bytes; ++i) {
for (int i = 0; i < maxNumDataBytes; ++i) {
for (int j = 0; j < blocks.size(); ++j) {
final ByteArray data_bytes = ((BlockPair) blocks.elementAt(j)).getDataBytes();
if (i < data_bytes.size()) {
result.appendBits(data_bytes.at(i), 8);
final ByteArray dataBytes = ((BlockPair) blocks.elementAt(j)).getDataBytes();
if (i < dataBytes.size()) {
result.appendBits(dataBytes.at(i), 8);
}
}
}
// Then, place error correction blocks.
for (int i = 0; i < max_num_ec_bytes; ++i) {
for (int i = 0; i < maxNumEcBytes; ++i) {
for (int j = 0; j < blocks.size(); ++j) {
final ByteArray ec_bytes = ((BlockPair) blocks.elementAt(j)).getErrorCorrectionBytes();
if (i < ec_bytes.size()) {
result.appendBits(ec_bytes.at(i), 8);
final ByteArray ecBytes = ((BlockPair) blocks.elementAt(j)).getErrorCorrectionBytes();
if (i < ecBytes.size()) {
result.appendBits(ecBytes.at(i), 8);
}
}
}
if (num_total_bytes != result.sizeInBytes()) { // Should be same.
throw new WriterException("Interleaving error: " + num_total_bytes + " and " + result.sizeInBytes() +
if (numTotalBytes != result.sizeInBytes()) { // Should be same.
throw new WriterException("Interleaving error: " + numTotalBytes + " and " + result.sizeInBytes() +
" differ.");
}
}
static ByteArray GenerateECBytes(ByteArray data_bytes, int num_ec_bytes_in_block) {
int numDataBytes = data_bytes.size();
int[] toEncode = new int[numDataBytes + num_ec_bytes_in_block];
static ByteArray generateECBytes(ByteArray dataBytes, int numEcBytesInBlock) {
int numDataBytes = dataBytes.size();
int[] toEncode = new int[numDataBytes + numEcBytesInBlock];
for (int i = 0; i < numDataBytes; i++) {
toEncode[i] = data_bytes.at(i);
toEncode[i] = dataBytes.at(i);
}
new ReedSolomonEncoder(GF256.QR_CODE_FIELD).encode(toEncode, num_ec_bytes_in_block);
new ReedSolomonEncoder(GF256.QR_CODE_FIELD).encode(toEncode, numEcBytesInBlock);
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]);
ByteArray ecBytes = new ByteArray(numEcBytesInBlock);
for (int i = 0; i < numEcBytesInBlock; i++) {
ecBytes.set(i, toEncode[numDataBytes + i]);
}
return ec_bytes;
return ecBytes;
}
// Append mode info. On success, store the result in "bits" and return true. On error, return
// false.
static void AppendModeInfo(int mode, BitVector bits) throws WriterException {
final int code = QRCode.GetModeCode(mode);
static void appendModeInfo(int mode, BitVector bits) throws WriterException {
final int code = QRCode.getModeCode(mode);
bits.appendBits(code, 4);
}
// Append length info. On success, store the result in "bits" and return true. On error, return
// false.
static void AppendLengthInfo(int num_bytes, int version, int mode, BitVector bits) throws WriterException {
int num_letters = num_bytes;
static void appendLengthInfo(int numBytes, int version, int mode, BitVector bits) throws WriterException {
int numLetters = numBytes;
// In Kanji mode, a letter is represented in two bytes.
if (mode == QRCode.MODE_KANJI) {
if (num_letters % 2 != 0) {
if (numLetters % 2 != 0) {
throw new WriterException("Number of letters must be even");
}
num_letters /= 2;
numLetters /= 2;
}
final int num_bits = QRCode.GetNumBitsForLength(version, mode);
if (num_letters > ((1 << num_bits) - 1)) {
throw new WriterException(num_letters + "is bigger than" + ((1 << num_bits) - 1));
final int numBits = QRCode.getNumBitsForLength(version, mode);
if (numLetters > ((1 << numBits) - 1)) {
throw new WriterException(numLetters + "is bigger than" + ((1 << numBits) - 1));
}
bits.appendBits(num_letters, num_bits);
bits.appendBits(numLetters, numBits);
}
// Append "bytes" in "mode" mode (encoding) into "bits". On success, store the result in "bits"
// and return true. On error, return false.
static void AppendBytes(final ByteArray bytes, int mode, BitVector bits) throws WriterException {
static void appendBytes(final ByteArray bytes, int mode, BitVector bits) throws WriterException {
switch (mode) {
case QRCode.MODE_NUMERIC:
AppendNumericBytes(bytes, bits);
appendNumericBytes(bytes, bits);
break;
case QRCode.MODE_ALPHANUMERIC:
AppendAlphanumericBytes(bytes, bits);
appendAlphanumericBytes(bytes, bits);
break;
case QRCode.MODE_8BIT_BYTE:
Append8BitBytes(bytes, bits);
append8BitBytes(bytes, bits);
break;
case QRCode.MODE_KANJI:
AppendKanjiBytes(bytes, bits);
appendKanjiBytes(bytes, bits);
break;
default:
throw new WriterException("Invalid mode: " + mode);
throw new WriterException("Invalid mode: " + mode);
}
}
// Append "bytes" to "bits" using QRCode.MODE_NUMERIC mode. On success, store the result in "bits"
// and return true. On error, return false.
static void AppendNumericBytes(final ByteArray bytes, BitVector bits) throws WriterException {
static void appendNumericBytes(final ByteArray bytes, BitVector bits) throws WriterException {
// Validate all the bytes first.
for (int i = 0; i < bytes.size(); ++i) {
int oneByte = bytes.at(i);
@ -522,14 +519,14 @@ public final class Encoder {
// Append "bytes" to "bits" using QRCode.MODE_ALPHANUMERIC mode. On success, store the result in
// "bits" and return true. On error, return false.
static void AppendAlphanumericBytes(final ByteArray bytes, BitVector bits) throws WriterException {
static void appendAlphanumericBytes(final ByteArray bytes, BitVector bits) throws WriterException {
for (int i = 0; i < bytes.size();) {
final int code1 = GetAlphanumericCode(bytes.at(i));
final int code1 = getAlphanumericCode(bytes.at(i));
if (code1 == -1) {
throw new WriterException();
}
if (i + 1 < bytes.size()) {
final int code2 = GetAlphanumericCode(bytes.at(i + 1));
final int code2 = getAlphanumericCode(bytes.at(i + 1));
if (code2 == -1) {
throw new WriterException();
}
@ -546,7 +543,7 @@ public final class Encoder {
// Append "bytes" to "bits" using QRCode.MODE_8BIT_BYTE mode. On success, store the result in
// "bits" and return true. On error, return false.
static void Append8BitBytes(final ByteArray bytes, BitVector bits) {
static void append8BitBytes(final ByteArray bytes, BitVector bits) {
for (int i = 0; i < bytes.size(); ++i) {
bits.appendBits(bytes.at(i), 8);
}
@ -555,12 +552,12 @@ public final class Encoder {
// Append "bytes" to "bits" using QRCode.MODE_KANJI mode. On success, store the result in "bits"
// and return true. On error, return false. See 8.4.5 of JISX0510:2004 (p.21) for how to encode
// Kanji bytes.
static void AppendKanjiBytes(final ByteArray bytes, BitVector bits) throws WriterException {
static void appendKanjiBytes(final ByteArray bytes, BitVector bits) throws WriterException {
if (bytes.size() % 2 != 0) {
throw new WriterException("Number of bytes must be even");
}
for (int i = 0; i < bytes.size(); i += 2) {
if (!IsValidKanji(bytes.at(i), bytes.at(i + 1))) {
if (!isValidKanji(bytes.at(i), bytes.at(i + 1))) {
throw new WriterException("Invalid Kanji at " + i);
}
final int code = (bytes.at(i) << 8) | bytes.at(i + 1);
@ -580,7 +577,7 @@ public final class Encoder {
// Check if "byte1" and "byte2" can compose a valid Kanji letter (2-byte Shift_JIS letter). The
// numbers are from http://ja.wikipedia.org/wiki/Shift_JIS.
static boolean IsValidKanji(final int byte1, final int byte2) {
static boolean isValidKanji(final int byte1, final int byte2) {
return (byte2 != 0x7f &&
((byte1 >= 0x81 && byte1 <= 0x9f &&
byte2 >= 0x40 && byte2 <= 0xfc) ||
@ -589,13 +586,13 @@ public final class Encoder {
}
// Check if "bytes" is a valid Kanji sequence. Used by the unit tests.
static boolean IsValidKanjiSequence(final ByteArray bytes) {
static boolean isValidKanjiSequence(final ByteArray bytes) {
if (bytes.size() % 2 != 0) {
return false;
}
int i = 0;
for (; i < bytes.size(); i += 2) {
if (!IsValidKanji(bytes.at(i), bytes.at(i + 1))) {
if (!isValidKanji(bytes.at(i), bytes.at(i + 1))) {
break;
}
}

View file

@ -24,28 +24,30 @@ import com.google.zxing.common.ByteMatrix;
*/
public final class MaskUtil {
private MaskUtil() {
// do nothing
}
// The mask penalty calculation is complicated. See Table 21 of JISX0510:2004 (p.45) for details.
// Basically it applies four rules and summate all penalties.
public static int CalculateMaskPenalty(final ByteMatrix matrix) {
public static int calculateMaskPenalty(final ByteMatrix matrix) {
int penalty = 0;
penalty += ApplyMaskPenaltyRule1(matrix);
penalty += ApplyMaskPenaltyRule2(matrix);
penalty += ApplyMaskPenaltyRule3(matrix);
penalty += ApplyMaskPenaltyRule4(matrix);
penalty += applyMaskPenaltyRule1(matrix);
penalty += applyMaskPenaltyRule2(matrix);
penalty += applyMaskPenaltyRule3(matrix);
penalty += applyMaskPenaltyRule4(matrix);
return penalty;
}
// Apply mask penalty rule 1 and return the penalty. Find repetitive cells with the same color and
// give penalty to them. Example: 00000 or 11111.
public static int ApplyMaskPenaltyRule1(final ByteMatrix matrix) {
final int penalty = (ApplyMaskPenaltyRule1Internal(matrix, true) +
ApplyMaskPenaltyRule1Internal(matrix, false));
return penalty;
public static int applyMaskPenaltyRule1(final ByteMatrix matrix) {
return applyMaskPenaltyRule1Internal(matrix, true) + applyMaskPenaltyRule1Internal(matrix, false);
}
// Apply mask penalty rule 2 and return the penalty. Find 2x2 blocks with the same color and give
// penalty to them.
public static int ApplyMaskPenaltyRule2(final ByteMatrix matrix) {
public static int applyMaskPenaltyRule2(final ByteMatrix matrix) {
int penalty = 0;
byte[][] array = matrix.getArray();
int width = matrix.width();
@ -64,7 +66,7 @@ public final class MaskUtil {
// Apply mask penalty rule 3 and return the penalty. Find consecutive cells of 00001011101 or
// 10111010000, and give penalty to them. If we find patterns like 000010111010000, we give
// penalties twice (i.e. 40 * 2).
public static int ApplyMaskPenaltyRule3(final ByteMatrix matrix) {
public static int applyMaskPenaltyRule3(final ByteMatrix matrix) {
int penalty = 0;
byte[][] array = matrix.getArray();
int width = matrix.width();
@ -126,31 +128,30 @@ public final class MaskUtil {
// - 55% => 10
// - 55% => 20
// - 100% => 100
public static int ApplyMaskPenaltyRule4(final ByteMatrix matrix) {
int num_dark_cells = 0;
public static int applyMaskPenaltyRule4(final ByteMatrix matrix) {
int numDarkCells = 0;
byte[][] array = matrix.getArray();
int width = matrix.width();
int height = matrix.height();
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) {
if (array[y][x] == 1) {
num_dark_cells += 1;
numDarkCells += 1;
}
}
}
final int num_total_cells = matrix.height() * matrix.width();
double dark_ratio = (double) num_dark_cells / num_total_cells;
final int penalty = Math.abs((int) (dark_ratio * 100 - 50)) / 5 * 10;
return penalty;
final int numTotalCells = matrix.height() * matrix.width();
double darkRatio = (double) numDarkCells / numTotalCells;
return Math.abs((int) (darkRatio * 100 - 50)) / 5 * 10;
}
// Return the mask bit for "mask_pattern" at "x" and "y". See 8.8 of JISX0510:2004 for mask
// Return the mask bit for "getMaskPattern" at "x" and "y". See 8.8 of JISX0510:2004 for mask
// pattern conditions.
public static int GetDataMaskBit(final int mask_pattern, final int x, final int y) {
if (!QRCode.IsValidMaskPattern(mask_pattern)) {
public static int getDataMaskBit(final int maskPattern, final int x, final int y) {
if (!QRCode.isValidMaskPattern(maskPattern)) {
throw new IllegalArgumentException("Invalid mask pattern");
}
switch (mask_pattern) {
switch (maskPattern) {
case 0:
return ((y + x) % 2 == 0) ? 1 : 0;
case 1:
@ -168,15 +169,15 @@ public final class MaskUtil {
case 7:
return ((((y * x) % 3) + ((y + x) % 2)) % 2 == 0) ? 1 : 0;
}
throw new IllegalArgumentException("invalid mask pattern: " + mask_pattern);
throw new IllegalArgumentException("invalid mask pattern: " + maskPattern);
}
// Helper function for ApplyMaskPenaltyRule1. We need this for doing this calculation in both
// Helper function for applyMaskPenaltyRule1. We need this for doing this calculation in both
// vertical and horizontal orders respectively.
private static int ApplyMaskPenaltyRule1Internal(final ByteMatrix matrix, boolean is_horizontal) {
private static int applyMaskPenaltyRule1Internal(final ByteMatrix matrix, boolean isHorizontal) {
int penalty = 0;
int num_same_bit_cells = 0;
int prev_bit = -1;
int numSameBitCells = 0;
int prevBit = -1;
// Horizontal mode:
// for (int i = 0; i < matrix.height(); ++i) {
// for (int j = 0; j < matrix.width(); ++j) {
@ -185,29 +186,29 @@ public final class MaskUtil {
// for (int i = 0; i < matrix.width(); ++i) {
// for (int j = 0; j < matrix.height(); ++j) {
// int bit = matrix.get(j, i);
final int i_limit = is_horizontal ? matrix.height() : matrix.width();
final int j_limit = is_horizontal ? matrix.width() : matrix.height();
final int iLimit = isHorizontal ? matrix.height() : matrix.width();
final int jLimit = isHorizontal ? matrix.width() : matrix.height();
byte[][] array = matrix.getArray();
for (int i = 0; i < i_limit; ++i) {
for (int j = 0; j < j_limit; ++j) {
final int bit = is_horizontal ? array[i][j] : array[j][i];
if (bit == prev_bit) {
num_same_bit_cells += 1;
for (int i = 0; i < iLimit; ++i) {
for (int j = 0; j < jLimit; ++j) {
final int bit = isHorizontal ? array[i][j] : array[j][i];
if (bit == prevBit) {
numSameBitCells += 1;
// Found five repetitive cells with the same color (bit).
// We'll give penalty of 3.
if (num_same_bit_cells == 5) {
if (numSameBitCells == 5) {
penalty += 3;
} else if (num_same_bit_cells > 5) {
} else if (numSameBitCells > 5) {
// After five repetitive cells, we'll add the penalty one
// by one.
penalty += 1;
}
} else {
num_same_bit_cells = 1; // Include the cell itself.
prev_bit = bit;
numSameBitCells = 1; // Include the cell itself.
prevBit = bit;
}
}
num_same_bit_cells = 0; // Clear at each row/column.
numSameBitCells = 0; // Clear at each row/column.
}
return penalty;
}

View file

@ -25,7 +25,11 @@ import com.google.zxing.WriterException;
*/
public final class MatrixUtil {
private static final int kPositionDetectionPattern[][] = {
private MatrixUtil() {
// do nothing
}
private static final int[][] POSITION_DETECTION_PATTERN = {
{1, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 1, 1, 0, 1},
@ -35,15 +39,15 @@ public final class MatrixUtil {
{1, 1, 1, 1, 1, 1, 1},
};
private static final int kHorizontalSeparationPattern[][] = {
private static final int[][] HORIZONTAL_SEPARATION_PATTERN = {
{0, 0, 0, 0, 0, 0, 0, 0},
};
private static final int kVerticalSeparationPattern[][] = {
private static final int[][] VERTICAL_SEPARATION_PATTERN = {
{0}, {0}, {0}, {0}, {0}, {0}, {0},
};
private static final int kPositionAdjustmentPattern[][] = {
private static final int[][] POSITION_ADJUSTMENT_PATTERN = {
{1, 1, 1, 1, 1},
{1, 0, 0, 0, 1},
{1, 0, 1, 0, 1},
@ -52,7 +56,7 @@ public final class MatrixUtil {
};
// From Appendix E. Table 1, JIS0510X:2004 (p 71). The table was double-checked by komatsu.
private static final int kPositionAdjustmentPatternCoordinateTable[][] = {
private static final int[][] POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE = {
{-1, -1, -1, -1, -1, -1, -1}, // Version 1
{ 6, 18, -1, -1, -1, -1, -1}, // Version 2
{ 6, 22, -1, -1, -1, -1, -1}, // Version 3
@ -96,7 +100,7 @@ public final class MatrixUtil {
};
// Type info cells at the left top corner.
private static final int[][] kTypeInfoCoordinates = {
private static final int[][] TYPE_INFO_COORDINATES = {
{8, 0},
{8, 1},
{8, 2},
@ -115,32 +119,32 @@ public final class MatrixUtil {
};
// From Appendix D in JISX0510:2004 (p. 67)
private static final int kVersionInfoPoly = 0x1f25; // 1 1111 0010 0101
private static final int VERSION_INFO_POLY = 0x1f25; // 1 1111 0010 0101
// From Appendix C in JISX0510:2004 (p.65).
private static final int kTypeInfoPoly = 0x537;
private static final int kTypeInfoMaskPattern = 0x5412;
private static final int TYPE_INFO_POLY = 0x537;
private static final int TYPE_INFO_MASK_PATTERN = 0x5412;
// Set all cells to -1. -1 means that the cell is empty (not set yet).
//
// JAVAPORT: We shouldn't need to do this at all. The code should be rewritten to begin encoding
// with the ByteMatrix initialized all to zero.
public static void ClearMatrix(ByteMatrix matrix) {
public static void clearMatrix(ByteMatrix matrix) {
matrix.clear((byte) -1);
}
// Build 2D matrix of QR Code from "data_bits" with "ec_level", "version" and "mask_pattern". On
// Build 2D matrix of QR Code from "dataBits" with "getECLevel", "version" and "getMaskPattern". On
// success, store the result in "matrix" and return true. On error, return false.
public static void BuildMatrix(final BitVector data_bits, int ec_level, int version,
int mask_pattern, ByteMatrix matrix) throws WriterException {
MatrixUtil.ClearMatrix(matrix);
EmbedBasicPatterns(version, matrix);
public static void buildMatrix(final BitVector dataBits, int ecLevel, int version,
int maskPattern, ByteMatrix matrix) throws WriterException {
MatrixUtil.clearMatrix(matrix);
embedBasicPatterns(version, matrix);
// Type information appear with any version.
EmbedTypeInfo(ec_level, mask_pattern, matrix);
embedTypeInfo(ecLevel, maskPattern, matrix);
// Version info appear if version >= 7.
MaybeEmbedVersionInfo(version, matrix);
maybeEmbedVersionInfo(version, matrix);
// Data should be embedded at end.
EmbedDataBits(data_bits, mask_pattern, matrix);
embedDataBits(dataBits, maskPattern, matrix);
}
// Embed basic patterns. On success, modify the matrix and return true. On error, return false.
@ -149,31 +153,31 @@ public final class MatrixUtil {
// - Timing patterns
// - Dark dot at the left bottom corner
// - Position adjustment patterns, if need be
public static void EmbedBasicPatterns(int version, ByteMatrix matrix) throws WriterException {
public static void embedBasicPatterns(int version, ByteMatrix matrix) throws WriterException {
// Let's get started with embedding big squares at corners.
EmbedPositionDetectionPatternsAndSeparators(matrix);
embedPositionDetectionPatternsAndSeparators(matrix);
// Then, embed the dark dot at the left bottom corner.
EmbedDarkDotAtLeftBottomCorner(matrix);
embedDarkDotAtLeftBottomCorner(matrix);
// Position adjustment patterns appear if version >= 2.
MaybeEmbedPositionAdjustmentPatterns(version, matrix);
maybeEmbedPositionAdjustmentPatterns(version, matrix);
// Timing patterns should be embedded after position adj. patterns.
EmbedTimingPatterns(matrix);
embedTimingPatterns(matrix);
}
// Embed type information. On success, modify the matrix.
public static void EmbedTypeInfo(int ec_level, int mask_pattern, ByteMatrix matrix) throws WriterException {
BitVector type_info_bits = new BitVector();
MakeTypeInfoBits(ec_level, mask_pattern, type_info_bits);
public static void embedTypeInfo(int ecLevel, int maskPattern, ByteMatrix matrix) throws WriterException {
BitVector typeInfoBits = new BitVector();
makeTypeInfoBits(ecLevel, maskPattern, typeInfoBits);
for (int i = 0; i < type_info_bits.size(); ++i) {
for (int i = 0; i < typeInfoBits.size(); ++i) {
// Place bits in LSB to MSB order. LSB (least significant bit) is the last value in
// "type_info_bits".
final int bit = type_info_bits.at(type_info_bits.size() - 1 - i);
// "typeInfoBits".
final int bit = typeInfoBits.at(typeInfoBits.size() - 1 - i);
// Type info bits at the left top corner. See 8.9 of JISX0510:2004 (p.46).
final int x1 = kTypeInfoCoordinates[i][0];
final int y1 = kTypeInfoCoordinates[i][1];
final int x1 = TYPE_INFO_COORDINATES[i][0];
final int y1 = TYPE_INFO_COORDINATES[i][1];
matrix.set(y1, x1, bit);
if (i < 8) {
@ -193,19 +197,19 @@ public final class MatrixUtil {
// Embed version information if need be. On success, modify the matrix and return true. On error,
// return false. See 8.10 of JISX0510:2004 (p.47) for how to embed version information. Return
// true on success, otherwise return false.
public static void MaybeEmbedVersionInfo(int version, ByteMatrix matrix) throws WriterException {
public static void maybeEmbedVersionInfo(int version, ByteMatrix matrix) throws WriterException {
if (version < 7) { // Version info is necessary if version >= 7.
return; // Don't need version info.
}
BitVector version_info_bits = new BitVector();
MakeVersionInfoBits(version, version_info_bits);
BitVector versionInfoBits = new BitVector();
makeVersionInfoBits(version, versionInfoBits);
int bit_index = 6 * 3 - 1; // It will decrease from 17 to 0.
int bitIndex = 6 * 3 - 1; // It will decrease from 17 to 0.
for (int i = 0; i < 6; ++i) {
for (int j = 0; j < 3; ++j) {
// Place bits in LSB (least significant bit) to MSB order.
final int bit = version_info_bits.at(bit_index);
bit_index--;
final int bit = versionInfoBits.at(bitIndex);
bitIndex--;
// Left bottom corner.
matrix.set(matrix.height() - 11 + j, i, bit);
// Right bottom corner.
@ -214,12 +218,12 @@ public final class MatrixUtil {
}
}
// Embed "data_bits" using "mask_pattern". On success, modify the matrix and return true. On
// error, return false. For debugging purposes, it skips masking process if "mask_pattern" is -1.
// Embed "dataBits" using "getMaskPattern". On success, modify the matrix and return true. On
// error, return false. For debugging purposes, it skips masking process if "getMaskPattern" is -1.
// See 8.7 of JISX0510:2004 (p.38) for how to embed data bits.
public static void EmbedDataBits(final BitVector data_bits, int mask_pattern, ByteMatrix matrix)
public static void embedDataBits(final BitVector dataBits, int maskPattern, ByteMatrix matrix)
throws WriterException {
int bit_index = 0;
int bitIndex = 0;
int direction = -1;
// Start from the right bottom cell.
int x = matrix.width() - 1;
@ -233,13 +237,13 @@ public final class MatrixUtil {
for (int i = 0; i < 2; ++i) {
final int xx = x - i;
// Skip the cell if it's not empty.
if (!IsEmpty(matrix.get(y, xx))) {
if (!isEmpty(matrix.get(y, xx))) {
continue;
}
int bit;
if (bit_index < data_bits.size()) {
bit = data_bits.at(bit_index);
++bit_index;
if (bitIndex < dataBits.size()) {
bit = dataBits.at(bitIndex);
++bitIndex;
} else {
// Padding bit. If there is no bit left, we'll fill the left cells with 0, as described
// in 8.4.9 of JISX0510:2004 (p. 24).
@ -247,8 +251,8 @@ public final class MatrixUtil {
}
// Skip masking if mask_pattern is -1.
if (mask_pattern != -1) {
final int mask = MaskUtil.GetDataMaskBit(mask_pattern, xx, y);
if (maskPattern != -1) {
final int mask = MaskUtil.getDataMaskBit(maskPattern, xx, y);
bit ^= mask;
}
matrix.set(y, xx, bit);
@ -260,23 +264,23 @@ public final class MatrixUtil {
x -= 2; // Move to the left.
}
// All bits should be consumed.
if (bit_index != data_bits.size()) {
throw new WriterException("Not all bits consumed: " + bit_index + "/" + data_bits.size());
if (bitIndex != dataBits.size()) {
throw new WriterException("Not all bits consumed: " + bitIndex + "/" + dataBits.size());
}
}
// Return the position of the most significant bit set (to one) in the "value". The most
// significant bit is position 32. If there is no bit set, return 0. Examples:
// - FindMSBSet(0) => 0
// - FindMSBSet(1) => 1
// - FindMSBSet(255) => 8
public static int FindMSBSet(int value) {
int num_digits = 0;
// - findMSBSet(0) => 0
// - findMSBSet(1) => 1
// - findMSBSet(255) => 8
public static int findMSBSet(int value) {
int numDigits = 0;
while (value != 0) {
value >>>= 1;
++num_digits;
++numDigits;
}
return num_digits;
return numDigits;
}
// Calculate BCH (Bose-Chaudhuri-Hocquenghem) code for "value" using polynomial "poly". The BCH
@ -304,14 +308,14 @@ public final class MatrixUtil {
//
// Since all coefficients in the polynomials are 1 or 0, we can do the calculation by bit
// operations. We don't care if cofficients are positive or negative.
public static int CalculateBCHCode(int value, int poly) {
// If poly is "1 1111 0010 0101" (version info poly), msb_set_in_poly is 13. We'll subtract 1
public static int calculateBCHCode(int value, int poly) {
// If poly is "1 1111 0010 0101" (version info poly), msbSetInPoly is 13. We'll subtract 1
// from 13 to make it 12.
final int msb_set_in_poly = FindMSBSet(poly);
value <<= msb_set_in_poly - 1;
final int msbSetInPoly = findMSBSet(poly);
value <<= msbSetInPoly - 1;
// Do the division business using exclusive-or operations.
while (FindMSBSet(value) >= msb_set_in_poly) {
value ^= poly << (FindMSBSet(value) - msb_set_in_poly);
while (findMSBSet(value) >= msbSetInPoly) {
value ^= poly << (findMSBSet(value) - msbSetInPoly);
}
// Now the "value" is the remainder (i.e. the BCH code)
return value;
@ -320,20 +324,20 @@ public final class MatrixUtil {
// Make bit vector of type information. On success, store the result in "bits" and return true.
// On error, return false. Encode error correction level and mask pattern. See 8.9 of
// JISX0510:2004 (p.45) for details.
public static void MakeTypeInfoBits(int ec_level, final int mask_pattern, BitVector bits) throws WriterException {
final int ec_code = QRCode.GetECLevelCode(ec_level);
if (!QRCode.IsValidMaskPattern(mask_pattern)) {
public static void makeTypeInfoBits(int ecLevel, final int maskPattern, BitVector bits) throws WriterException {
final int ecCode = QRCode.getECLevelCode(ecLevel);
if (!QRCode.isValidMaskPattern(maskPattern)) {
throw new WriterException("Invalid mask pattern");
}
final int type_info = (ec_code << 3) | mask_pattern;
bits.appendBits(type_info, 5);
final int typeInfo = (ecCode << 3) | maskPattern;
bits.appendBits(typeInfo, 5);
final int bch_code = MatrixUtil.CalculateBCHCode(type_info, kTypeInfoPoly);
bits.appendBits(bch_code, 10);
final int bchCode = MatrixUtil.calculateBCHCode(typeInfo, TYPE_INFO_POLY);
bits.appendBits(bchCode, 10);
BitVector mask_bits = new BitVector();
mask_bits.appendBits(kTypeInfoMaskPattern, 15);
bits.xor(mask_bits);
BitVector maskBits = new BitVector();
maskBits.appendBits(TYPE_INFO_MASK_PATTERN, 15);
bits.xor(maskBits);
if (bits.size() != 15) { // Just in case.
throw new WriterException("should not happen but we got: " + bits.size());
@ -342,10 +346,10 @@ public final class MatrixUtil {
// Make bit vector of version information. On success, store the result in "bits" and return true.
// On error, return false. See 8.10 of JISX0510:2004 (p.45) for details.
public static void MakeVersionInfoBits(int version, BitVector bits) throws WriterException {
public static void makeVersionInfoBits(int version, BitVector bits) throws WriterException {
bits.appendBits(version, 6);
final int bch_code = MatrixUtil.CalculateBCHCode(version, kVersionInfoPoly);
bits.appendBits(bch_code, 12);
final int bchCode = MatrixUtil.calculateBCHCode(version, VERSION_INFO_POLY);
bits.appendBits(bchCode, 12);
if (bits.size() != 18) { // Just in case.
throw new WriterException("should not happen but we got: " + bits.size());
@ -353,162 +357,162 @@ public final class MatrixUtil {
}
// Check if "value" is empty.
private static boolean IsEmpty(final int value) {
private static boolean isEmpty(final int value) {
return value == -1;
}
// Check if "value" is valid.
private static boolean IsValidValue(final int value) {
private static boolean isValidValue(final int value) {
return (value == -1 || // Empty.
value == 0 || // Light (white).
value == 1); // Dark (black).
}
private static void EmbedTimingPatterns(ByteMatrix matrix) throws WriterException {
private static void embedTimingPatterns(ByteMatrix matrix) throws WriterException {
// -8 is for skipping position detection patterns (size 7), and two horizontal/vertical
// separation patterns (size 1). Thus, 8 = 7 + 1.
for (int i = 8; i < matrix.width() - 8; ++i) {
final int bit = (i + 1) % 2;
// Horizontal line.
if (!IsValidValue(matrix.get(6, i))) {
if (!isValidValue(matrix.get(6, i))) {
throw new WriterException();
}
if (IsEmpty(matrix.get(6, i))) {
if (isEmpty(matrix.get(6, i))) {
matrix.set(6, i, bit);
}
// Vertical line.
if (!IsValidValue(matrix.get(i, 6))) {
if (!isValidValue(matrix.get(i, 6))) {
throw new WriterException();
}
if (IsEmpty(matrix.get(i, 6))) {
if (isEmpty(matrix.get(i, 6))) {
matrix.set(i, 6, bit);
}
}
}
// Embed the lonely dark dot at left bottom corner. JISX0510:2004 (p.46)
private static void EmbedDarkDotAtLeftBottomCorner(ByteMatrix matrix) throws WriterException {
private static void embedDarkDotAtLeftBottomCorner(ByteMatrix matrix) throws WriterException {
if (matrix.get(matrix.height() - 8, 8) == 0) {
throw new WriterException();
}
matrix.set(matrix.height() - 8, 8, 1);
}
private static void EmbedHorizontalSeparationPattern(final int x_start, final int y_start,
private static void embedHorizontalSeparationPattern(final int xStart, final int yStart,
ByteMatrix matrix) throws WriterException {
// We know the width and height.
if (kHorizontalSeparationPattern[0].length != 8 || kHorizontalSeparationPattern.length != 1) {
if (HORIZONTAL_SEPARATION_PATTERN[0].length != 8 || HORIZONTAL_SEPARATION_PATTERN.length != 1) {
throw new WriterException("Bad horizontal separation pattern");
}
for (int x = 0; x < 8; ++x) {
if (!IsEmpty(matrix.get(y_start, x_start + x))) {
if (!isEmpty(matrix.get(yStart, xStart + x))) {
throw new WriterException();
}
matrix.set(y_start, x_start + x, kHorizontalSeparationPattern[0][x]);
matrix.set(yStart, xStart + x, HORIZONTAL_SEPARATION_PATTERN[0][x]);
}
}
private static void EmbedVerticalSeparationPattern(final int x_start, final int y_start,
private static void embedVerticalSeparationPattern(final int xStart, final int yStart,
ByteMatrix matrix) throws WriterException {
// We know the width and height.
if (kVerticalSeparationPattern[0].length != 1 || kVerticalSeparationPattern.length != 7) {
if (VERTICAL_SEPARATION_PATTERN[0].length != 1 || VERTICAL_SEPARATION_PATTERN.length != 7) {
throw new WriterException("Bad vertical separation pattern");
}
for (int y = 0; y < 7; ++y) {
if (!IsEmpty(matrix.get(y_start + y, x_start))) {
if (!isEmpty(matrix.get(yStart + y, xStart))) {
throw new WriterException();
}
matrix.set(y_start + y, x_start, kVerticalSeparationPattern[y][0]);
matrix.set(yStart + y, xStart, VERTICAL_SEPARATION_PATTERN[y][0]);
}
}
// Note that we cannot unify the function with EmbedPositionDetectionPattern() despite they are
// Note that we cannot unify the function with embedPositionDetectionPattern() despite they are
// almost identical, since we cannot write a function that takes 2D arrays in different sizes in
// C/C++. We should live with the fact.
private static void EmbedPositionAdjustmentPattern(final int x_start, final int y_start,
private static void embedPositionAdjustmentPattern(final int xStart, final int yStart,
ByteMatrix matrix) throws WriterException {
// We know the width and height.
if (kPositionAdjustmentPattern[0].length != 5 || kPositionAdjustmentPattern.length != 5) {
if (POSITION_ADJUSTMENT_PATTERN[0].length != 5 || POSITION_ADJUSTMENT_PATTERN.length != 5) {
throw new WriterException("Bad position adjustment");
}
for (int y = 0; y < 5; ++y) {
for (int x = 0; x < 5; ++x) {
if (!IsEmpty(matrix.get(y_start + y, x_start + x))) {
if (!isEmpty(matrix.get(yStart + y, xStart + x))) {
throw new WriterException();
}
matrix.set(y_start + y, x_start + x, kPositionAdjustmentPattern[y][x]);
matrix.set(yStart + y, xStart + x, POSITION_ADJUSTMENT_PATTERN[y][x]);
}
}
}
private static void EmbedPositionDetectionPattern(final int x_start, final int y_start,
private static void embedPositionDetectionPattern(final int xStart, final int yStart,
ByteMatrix matrix) throws WriterException {
// We know the width and height.
if (kPositionDetectionPattern[0].length != 7 || kPositionDetectionPattern.length != 7) {
if (POSITION_DETECTION_PATTERN[0].length != 7 || POSITION_DETECTION_PATTERN.length != 7) {
throw new WriterException("Bad position detection pattern");
}
for (int y = 0; y < 7; ++y) {
for (int x = 0; x < 7; ++x) {
if (!IsEmpty(matrix.get(y_start + y, x_start + x))) {
if (!isEmpty(matrix.get(yStart + y, xStart + x))) {
throw new WriterException();
}
matrix.set(y_start + y, x_start + x, kPositionDetectionPattern[y][x]);
matrix.set(yStart + y, xStart + x, POSITION_DETECTION_PATTERN[y][x]);
}
}
}
// Embed position detection patterns and surrounding vertical/horizontal separators.
private static void EmbedPositionDetectionPatternsAndSeparators(ByteMatrix matrix) throws WriterException {
private static void embedPositionDetectionPatternsAndSeparators(ByteMatrix matrix) throws WriterException {
// Embed three big squares at corners.
final int pdp_width = kPositionDetectionPattern[0].length;
final int pdpWidth = POSITION_DETECTION_PATTERN[0].length;
// Left top corner.
EmbedPositionDetectionPattern(0, 0, matrix);
embedPositionDetectionPattern(0, 0, matrix);
// Right top corner.
EmbedPositionDetectionPattern(matrix.width() - pdp_width, 0, matrix);
embedPositionDetectionPattern(matrix.width() - pdpWidth, 0, matrix);
// Left bottom corner.
EmbedPositionDetectionPattern(0, matrix.width() - pdp_width, matrix);
embedPositionDetectionPattern(0, matrix.width() - pdpWidth, matrix);
// Embed horizontal separation patterns around the squares.
final int hsp_width = kHorizontalSeparationPattern[0].length;
final int hspWidth = HORIZONTAL_SEPARATION_PATTERN[0].length;
// Left top corner.
EmbedHorizontalSeparationPattern(0, hsp_width - 1, matrix);
embedHorizontalSeparationPattern(0, hspWidth - 1, matrix);
// Right top corner.
EmbedHorizontalSeparationPattern(matrix.width() - hsp_width,
hsp_width - 1, matrix);
embedHorizontalSeparationPattern(matrix.width() - hspWidth,
hspWidth - 1, matrix);
// Left bottom corner.
EmbedHorizontalSeparationPattern(0, matrix.width() - hsp_width, matrix);
embedHorizontalSeparationPattern(0, matrix.width() - hspWidth, matrix);
// Embed vertical separation patterns around the squares.
final int vsp_size = kVerticalSeparationPattern.length;
final int vspSize = VERTICAL_SEPARATION_PATTERN.length;
// Left top corner.
EmbedVerticalSeparationPattern(vsp_size, 0, matrix);
embedVerticalSeparationPattern(vspSize, 0, matrix);
// Right top corner.
EmbedVerticalSeparationPattern(matrix.height() - vsp_size - 1, 0, matrix);
embedVerticalSeparationPattern(matrix.height() - vspSize - 1, 0, matrix);
// Left bottom corner.
EmbedVerticalSeparationPattern(vsp_size, matrix.height() - vsp_size,
embedVerticalSeparationPattern(vspSize, matrix.height() - vspSize,
matrix);
}
// Embed position adjustment patterns if need be.
private static void MaybeEmbedPositionAdjustmentPatterns(final int version, ByteMatrix matrix) throws WriterException {
private static void maybeEmbedPositionAdjustmentPatterns(final int version, ByteMatrix matrix) throws WriterException {
if (version < 2) { // The patterns appear if version >= 2
return;
}
final int index = version - 1;
final int[] coordinates = kPositionAdjustmentPatternCoordinateTable[index];
final int num_coordinates = kPositionAdjustmentPatternCoordinateTable[index].length;
for (int i = 0; i < num_coordinates; ++i) {
for (int j = 0; j < num_coordinates; ++j) {
final int[] coordinates = POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE[index];
final int numCoordinates = POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE[index].length;
for (int i = 0; i < numCoordinates; ++i) {
for (int j = 0; j < numCoordinates; ++j) {
final int y = coordinates[i];
final int x = coordinates[j];
if (x == -1 || y == -1) {
continue;
}
// If the cell is unset, we embed the position adjustment pattern here.
if (IsEmpty(matrix.get(y, x))) {
if (isEmpty(matrix.get(y, x))) {
// -2 is necessary since the x/y coordinates point to the center of the pattern, not the
// left top corner.
EmbedPositionAdjustmentPattern(x - 2, y - 2, matrix);
embedPositionAdjustmentPattern(x - 2, y - 2, matrix);
}
}
}

View file

@ -26,39 +26,37 @@ import com.google.zxing.WriterException;
public final class QRCode {
// Magic numbers.
private static final int kMinVersion = 1;
private static final int kMaxVersion = 40;
private static final int MIN_VERSION = 1;
private static final int MAX_VERSION = 40;
// For matrix width, see 7.3.1 of JISX0510:2004 (p.5).
private static final int kMinMatrixWidth = 21; // Version 1
private static final int kMaxMatrixWidth = 177; // Version 40 (21 + 4 * (40 -1)).
public static final int kNumMaskPatterns = 8;
private static final int MIN_MATRIX_WIDTH = 21; // Version 1
private static final int MAX_MATRIX_WIDTH = 177; // Version 40 (21 + 4 * (40 -1)).
public static final int NUM_MASK_PATTERNS = 8;
// See table 3 of JISX0510:2004 (p.16)
private static final int kNumBitsTable[][] = {
private static final int[][] NUM_BITS_TABLE = {
// NUMERIC ALPHANUMERIC 8BIT_BYTE KANJI
{ 10, 9, 8, 8 }, // Version 1-9
{ 12, 11, 16, 10 }, // Version 10-26
{ 14, 13, 16, 12 }, // Version 27-40
};
// JAVAPORT: Do not remove trailing slashes yet. There are very likely conflicts with local
// variables and parameters which will introduce insidious bugs.
private int mode_;
private int ec_level_;
private int version_;
private int matrix_width_;
private int mask_pattern_;
private int num_total_bytes_;
private int num_data_bytes_;
private int num_ec_bytes_;
private int num_rs_blocks_;
private ByteMatrix matrix_;
private int mode;
private int ecLevel;
private int version;
private int matrixWidth;
private int maskPattern;
private int numTotalBytes;
private int numDataBytes;
private int numECBytes;
private int numRSBlocks;
private ByteMatrix matrix;
// They call encoding "mode". The modes are defined in 8.3 of JISX0510:2004 (p.14). It's unlikely
// (probably we will not support complicated modes) but if you add an item to this, please also
// add it to ModeToString(), GetModeCode(), GetNumBitsForLength(), Encoder.AppendBytes(), and
// Encoder.ChooseMode().
// add it to modeToString(), getModeCode(), getNumBitsForLength(), Encoder.appendBytes(), and
// Encoder.chooseMode().
//
// JAVAPORT: These used to be C++ enums, but the code evaluates them as integers, and requires
// negative values. I don't want to take the ParsedResultType approach of a class full of statics
@ -79,7 +77,7 @@ public final class QRCode {
// The error correction levels are defined in the table 22 of JISX0510:2004 (p.45). It's very
// unlikely (we've already covered all of them!) but if you add an item to this, please also add
// it to ECLevelToString() and GetECLevelCode().
// it to ecLevelToString() and getECLevelCode().
//
// Formerly enum ECLevel
public static final int EC_LEVEL_UNDEFINED = -1;
@ -91,44 +89,44 @@ public final class QRCode {
public static final int NUM_EC_LEVELS = 4;
public QRCode() {
mode_ = MODE_UNDEFINED;
ec_level_ = EC_LEVEL_UNDEFINED;
version_ = -1;
matrix_width_ = -1;
mask_pattern_ = -1;
num_total_bytes_ = -1;
num_data_bytes_ = -1;
num_ec_bytes_ = -1;
num_rs_blocks_ = -1;
matrix_ = null;
mode = MODE_UNDEFINED;
ecLevel = EC_LEVEL_UNDEFINED;
version = -1;
matrixWidth = -1;
maskPattern = -1;
numTotalBytes = -1;
numDataBytes = -1;
numECBytes = -1;
numRSBlocks = -1;
matrix = null;
}
// Mode of the QR Code.
public int mode() { return mode_; }
public int getMode() { return mode; }
// Error correction level of the QR Code.
public int ec_level() { return ec_level_; }
public int getECLevel() { return ecLevel; }
// Version of the QR Code. The bigger size, the bigger version.
public int version() { return version_; }
public int getVersion() { return version; }
// ByteMatrix width of the QR Code.
public int matrix_width() { return matrix_width_; }
public int getMatrixWidth() { return matrixWidth; }
// Mask pattern of the QR Code.
public int mask_pattern() { return mask_pattern_; }
public int getMaskPattern() { return maskPattern; }
// Number of total bytes in the QR Code.
public int num_total_bytes() { return num_total_bytes_; }
public int getNumTotalBytes() { return numTotalBytes; }
// Number of data bytes in the QR Code.
public int num_data_bytes() { return num_data_bytes_; }
public int getNumDataBytes() { return numDataBytes; }
// Number of error correction bytes in the QR Code.
public int num_ec_bytes() { return num_ec_bytes_; }
public int getNumECBytes() { return numECBytes; }
// Number of Reedsolomon blocks in the QR Code.
public int num_rs_blocks() { return num_rs_blocks_; }
public int getNumRSBlocks() { return numRSBlocks; }
// ByteMatrix data of the QR Code.
public final ByteMatrix matrix() { return matrix_; }
public final ByteMatrix getMatrix() { return matrix; }
// Return the value of the module (cell) pointed by "x" and "y" in the matrix of the QR Code. They
// call cells in the matrix "modules". 1 represents a black cell, and 0 represents a white cell.
public int at(int x, int y) {
// The value must be zero or one.
int value = matrix_.get(y, x);
int value = matrix.get(y, x);
if (!(value == 0 || value == 1)) {
// this is really like an assert... not sure what better exception to use?
throw new RuntimeException("Bad value");
@ -138,32 +136,31 @@ public final class QRCode {
// Checks all the member variables are set properly. Returns true on success. Otherwise, returns
// false.
// JAVAPORT: Do not call EverythingIsBinary(matrix_) here as it is very expensive.
public boolean IsValid() {
public boolean isValid() {
return (
// First check if all version are not uninitialized.
mode_ != MODE_UNDEFINED &&
ec_level_ != EC_LEVEL_UNDEFINED &&
version_ != -1 &&
matrix_width_ != -1 &&
mask_pattern_ != -1 &&
num_total_bytes_ != -1 &&
num_data_bytes_ != -1 &&
num_ec_bytes_ != -1 &&
num_rs_blocks_ != -1 &&
mode != MODE_UNDEFINED &&
ecLevel != EC_LEVEL_UNDEFINED &&
version != -1 &&
matrixWidth != -1 &&
maskPattern != -1 &&
numTotalBytes != -1 &&
numDataBytes != -1 &&
numECBytes != -1 &&
numRSBlocks != -1 &&
// Then check them in other ways..
IsValidVersion(version_) &&
IsValidMode(mode_) &&
IsValidECLevel(ec_level_) &&
IsValidMatrixWidth(matrix_width_) &&
IsValidMaskPattern(mask_pattern_) &&
num_total_bytes_ == num_data_bytes_ + num_ec_bytes_ &&
isValidVersion(version) &&
isValidMode(mode) &&
isValidECLevel(ecLevel) &&
isValidMatrixWidth(matrixWidth) &&
isValidMaskPattern(maskPattern) &&
numTotalBytes == numDataBytes + numECBytes &&
// ByteMatrix stuff.
matrix_ != null &&
matrix_width_ == matrix_.width() &&
matrix != null &&
matrixWidth == matrix.width() &&
// See 7.3.1 of JISX0510:2004 (p.5).
matrix_width_ == kMinMatrixWidth + (version_ - 1) * 4 &&
matrix_.width() == matrix_.height()); // Must be square.
matrixWidth == MIN_MATRIX_WIDTH + (version - 1) * 4 &&
matrix.width() == matrix.height()); // Must be square.
}
// Return debug String.
@ -171,102 +168,102 @@ public final class QRCode {
StringBuffer result = new StringBuffer();
result.append("<<\n");
result.append(" mode: ");
result.append(ModeToString(mode_));
result.append("\n ec_level: ");
result.append(ECLevelToString(ec_level_));
result.append(modeToString(mode));
result.append("\n ecLevel: ");
result.append(ecLevelToString(ecLevel));
result.append("\n version: ");
result.append(version_);
result.append("\n matrix_width: ");
result.append(matrix_width_);
result.append("\n mask_pattern: ");
result.append(mask_pattern_);
result.append("\n num_total_bytes_: ");
result.append(num_total_bytes_);
result.append("\n num_data_bytes: ");
result.append(num_data_bytes_);
result.append("\n num_ec_bytes: ");
result.append(num_ec_bytes_);
result.append("\n num_rs_blocks: ");
result.append(num_rs_blocks_);
if (matrix_ == null) {
result.append(version);
result.append("\n matrixWidth: ");
result.append(matrixWidth);
result.append("\n maskPattern: ");
result.append(maskPattern);
result.append("\n numTotalBytes: ");
result.append(numTotalBytes);
result.append("\n numDataBytes: ");
result.append(numDataBytes);
result.append("\n numECBytes: ");
result.append(numECBytes);
result.append("\n numRSBlocks: ");
result.append(numRSBlocks);
if (matrix == null) {
result.append("\n matrix: null\n");
} else {
result.append("\n matrix:\n");
result.append(matrix_.toString());
result.append(matrix.toString());
}
result.append(">>\n");
return result.toString();
}
public void set_mode(int value) {
mode_ = value;
public void setMode(int value) {
mode = value;
}
public void set_ec_level(int value) {
ec_level_ = value;
public void setECLevel(int value) {
ecLevel = value;
}
public void set_version(int value) {
version_ = value;
public void setVersion(int value) {
version = value;
}
public void set_matrix_width(int value) {
matrix_width_ = value;
public void setMatrixWidth(int value) {
matrixWidth = value;
}
public void set_mask_pattern(int value) {
mask_pattern_ = value;
public void setMaskPattern(int value) {
maskPattern = value;
}
public void set_num_total_bytes(int value) {
num_total_bytes_ = value;
public void setNumTotalBytes(int value) {
numTotalBytes = value;
}
public void set_num_data_bytes(int value) {
num_data_bytes_ = value;
public void setNumDataBytes(int value) {
numDataBytes = value;
}
public void set_num_ec_bytes(int value) {
num_ec_bytes_ = value;
public void setNumECBytes(int value) {
numECBytes = value;
}
public void set_num_rs_blocks(int value) {
num_rs_blocks_ = value;
public void setNumRSBlocks(int value) {
numRSBlocks = value;
}
// This takes ownership of the 2D array.
public void set_matrix(ByteMatrix value) {
matrix_ = value;
public void setMatrix(ByteMatrix value) {
matrix = value;
}
// Check if "version" is valid.
public static boolean IsValidVersion(final int version) {
return version >= kMinVersion && version <= kMaxVersion;
public static boolean isValidVersion(final int version) {
return version >= MIN_VERSION && version <= MAX_VERSION;
}
// Check if "mask_pattern" is valid.
public static boolean IsValidECLevel(int ec_level) {
return ec_level >= 0 && ec_level < NUM_EC_LEVELS;
// Check if "ecLevel" is valid.
public static boolean isValidECLevel(int ecLevel) {
return ecLevel >= 0 && ecLevel < NUM_EC_LEVELS;
}
// Check if "mode" is valid.
public static boolean IsValidMode(final int mode) {
public static boolean isValidMode(final int mode) {
return mode >= 0 && mode < NUM_MODES;
}
// Check if "width" is valid.
public static boolean IsValidMatrixWidth(int width) {
return width >= kMinMatrixWidth && width <= kMaxMatrixWidth;
public static boolean isValidMatrixWidth(int width) {
return width >= MIN_MATRIX_WIDTH && width <= MAX_MATRIX_WIDTH;
}
// Check if "mask_pattern" is valid.
public static boolean IsValidMaskPattern(int mask_pattern) {
return mask_pattern >= 0 && mask_pattern < kNumMaskPatterns;
public static boolean isValidMaskPattern(int maskPattern) {
return maskPattern >= 0 && maskPattern < NUM_MASK_PATTERNS;
}
// Convert "ec_level" to String for debugging.
public static String ECLevelToString(int ec_level) {
switch (ec_level) {
// Convert "getECLevel" to String for debugging.
public static String ecLevelToString(int ecLevel) {
switch (ecLevel) {
case QRCode.EC_LEVEL_UNDEFINED:
return "UNDEFINED";
case QRCode.EC_LEVEL_L:
@ -284,7 +281,7 @@ public final class QRCode {
}
// Convert "mode" to String for debugging.
public static String ModeToString(int mode) {
public static String modeToString(int mode) {
switch (mode) {
case QRCode.MODE_UNDEFINED:
return "UNDEFINED";
@ -304,8 +301,8 @@ public final class QRCode {
// Return the code of error correction level. On error, return -1. The codes of error correction
// levels are defined in the table 22 of JISX0510:2004 (p.45).
public static int GetECLevelCode(final int ec_level) throws WriterException {
switch (ec_level) {
public static int getECLevelCode(final int ecLevel) throws WriterException {
switch (ecLevel) {
case QRCode.EC_LEVEL_L:
return 1;
case QRCode.EC_LEVEL_M:
@ -321,7 +318,7 @@ public final class QRCode {
// Return the code of mode. On error, return -1. The codes of modes are defined in the table 2 of
// JISX0510:2004 (p.16).
public static int GetModeCode(final int mode) throws WriterException {
public static int getModeCode(final int mode) throws WriterException {
switch (mode) {
case QRCode.MODE_NUMERIC:
return 1;
@ -338,19 +335,19 @@ public final class QRCode {
// Return the number of bits needed for representing the length info of QR Code with "version" and
// "mode". On error, return -1.
static int GetNumBitsForLength(int version, int mode) {
if (!IsValidVersion(version)) {
static int getNumBitsForLength(int version, int mode) {
if (!isValidVersion(version)) {
throw new IllegalArgumentException("Invalid version: " + version);
}
if (!IsValidMode(mode)) {
if (!isValidMode(mode)) {
throw new IllegalArgumentException("Invalid mode: " + mode);
}
if (version >= 1 && version <= 9) {
return kNumBitsTable[0][mode];
return NUM_BITS_TABLE[0][mode];
} else if (version >= 10 && version <= 26) {
return kNumBitsTable[1][mode];
return NUM_BITS_TABLE[1][mode];
} else if (version >= 27 && version <= 40) {
return kNumBitsTable[2][mode];
return NUM_BITS_TABLE[2][mode];
}
throw new IllegalArgumentException("Bad version: " + version);
}
@ -360,6 +357,7 @@ public final class QRCode {
// JAVAPORT: This is going to be super expensive and unnecessary, we should not call this in
// production. I'm leaving it because it may be useful for testing. It should be removed entirely
// if ByteMatrix is changed never to contain a -1.
/*
private static boolean EverythingIsBinary(final ByteMatrix matrix) {
for (int y = 0; y < matrix.height(); ++y) {
for (int x = 0; x < matrix.width(); ++x) {
@ -372,5 +370,6 @@ public final class QRCode {
}
return true;
}
*/
}

View file

@ -29,75 +29,75 @@ public final class EncoderTestCase extends TestCase {
public void testGetAlphanumericCode() throws WriterException {
// The first ten code points are numbers.
for (int i = 0; i < 10; ++i) {
assertEquals(i, Encoder.GetAlphanumericCode('0' + 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));
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(':'));
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'));
assertEquals(-1, Encoder.getAlphanumericCode('a'));
assertEquals(-1, Encoder.getAlphanumericCode('#'));
assertEquals(-1, Encoder.getAlphanumericCode('\0'));
}
public void testChooseMode() throws WriterException {
// Numeric mode.
assertEquals(QRCode.MODE_NUMERIC, Encoder.ChooseMode(new ByteArray("0")));
assertEquals(QRCode.MODE_NUMERIC, Encoder.ChooseMode(new ByteArray("0123456789")));
assertEquals(QRCode.MODE_NUMERIC, Encoder.chooseMode(new ByteArray("0")));
assertEquals(QRCode.MODE_NUMERIC, Encoder.chooseMode(new ByteArray("0123456789")));
// Alphanumeric mode.
assertEquals(QRCode.MODE_ALPHANUMERIC, Encoder.ChooseMode(new ByteArray("A")));
assertEquals(QRCode.MODE_ALPHANUMERIC, Encoder.chooseMode(new ByteArray("A")));
assertEquals(QRCode.MODE_ALPHANUMERIC,
Encoder.ChooseMode(new ByteArray("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:")));
Encoder.chooseMode(new ByteArray("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:")));
// 8-bit byte mode.
assertEquals(QRCode.MODE_8BIT_BYTE, Encoder.ChooseMode(new ByteArray("a")));
assertEquals(QRCode.MODE_8BIT_BYTE, Encoder.ChooseMode(new ByteArray("#")));
assertEquals(QRCode.MODE_8BIT_BYTE, Encoder.ChooseMode(new ByteArray("")));
assertEquals(QRCode.MODE_8BIT_BYTE, Encoder.chooseMode(new ByteArray("a")));
assertEquals(QRCode.MODE_8BIT_BYTE, Encoder.chooseMode(new ByteArray("#")));
assertEquals(QRCode.MODE_8BIT_BYTE, Encoder.chooseMode(new ByteArray("")));
// 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
byte[] dat1 = {0x8,0xa,0x8,0xa,0x8,0xa,0x8,(byte)0xa6};
assertEquals(QRCode.MODE_8BIT_BYTE, Encoder.ChooseMode(new ByteArray(dat1)));
assertEquals(QRCode.MODE_8BIT_BYTE, Encoder.chooseMode(new ByteArray(dat1)));
// Nihon in Kanji in Shift_JIS.
byte[] dat2 = {0x9,0xf,0x9,0x7b};
assertEquals(QRCode.MODE_8BIT_BYTE, Encoder.ChooseMode(new ByteArray(dat2)));
assertEquals(QRCode.MODE_8BIT_BYTE, Encoder.chooseMode(new ByteArray(dat2)));
// Sou-Utsu-Byou in Kanji in Shift_JIS.
byte[] dat3 = {0xe,0x4,0x9,0x5,0x9,0x61};
assertEquals(QRCode.MODE_8BIT_BYTE, Encoder.ChooseMode(new ByteArray(dat3)));
assertEquals(QRCode.MODE_8BIT_BYTE, Encoder.chooseMode(new ByteArray(dat3)));
}
public void testEncode() throws WriterException {
QRCode qr_code = new QRCode();
Encoder.Encode(new ByteArray("ABCDEF"), QRCode.EC_LEVEL_H, qr_code);
QRCode qrCode = new QRCode();
Encoder.encode(new ByteArray("ABCDEF"), QRCode.EC_LEVEL_H, qrCode);
// The following is a valid QR Code that can be read by cell phones.
String expected =
"<<\n" +
" mode: ALPHANUMERIC\n" +
" ec_level: H\n" +
" ecLevel: H\n" +
" version: 1\n" +
" matrix_width: 21\n" +
" mask_pattern: 0\n" +
" num_total_bytes_: 26\n" +
" num_data_bytes: 9\n" +
" num_ec_bytes: 17\n" +
" num_rs_blocks: 1\n" +
" matrixWidth: 21\n" +
" maskPattern: 0\n" +
" numTotalBytes: 26\n" +
" numDataBytes: 9\n" +
" numECBytes: 17\n" +
" numRSBlocks: 1\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" +
@ -121,19 +121,19 @@ public final class EncoderTestCase extends TestCase {
" 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, qr_code.toString());
assertEquals(expected, qrCode.toString());
}
public void testAppendModeInfo() throws WriterException {
BitVector bits = new BitVector();
Encoder.AppendModeInfo(QRCode.MODE_NUMERIC, bits);
Encoder.appendModeInfo(QRCode.MODE_NUMERIC, bits);
assertEquals("0001", bits.toString());
}
public void testAppendLengthInfo() throws WriterException {
{
BitVector bits = new BitVector();
Encoder.AppendLengthInfo(1, // 1 letter (1/1).
Encoder.appendLengthInfo(1, // 1 letter (1/1).
1, // version 1.
QRCode.MODE_NUMERIC,
bits);
@ -141,7 +141,7 @@ public final class EncoderTestCase extends TestCase {
}
{
BitVector bits = new BitVector();
Encoder.AppendLengthInfo(2, // 2 letters (2/1).
Encoder.appendLengthInfo(2, // 2 letters (2/1).
10, // version 10.
QRCode.MODE_ALPHANUMERIC,
bits);
@ -149,7 +149,7 @@ public final class EncoderTestCase extends TestCase {
}
{
BitVector bits = new BitVector();
Encoder.AppendLengthInfo(255, // 255 letter (255/1).
Encoder.appendLengthInfo(255, // 255 letter (255/1).
27, // version 27.
QRCode.MODE_8BIT_BYTE,
bits);
@ -157,7 +157,7 @@ public final class EncoderTestCase extends TestCase {
}
{
BitVector bits = new BitVector();
Encoder.AppendLengthInfo(1024, // 512 letters (1024/2).
Encoder.appendLengthInfo(1024, // 512 letters (1024/2).
40, // version 40.
QRCode.MODE_KANJI,
bits);
@ -167,53 +167,53 @@ public final class EncoderTestCase extends TestCase {
public void testAppendBytes() throws WriterException {
{
// Should use AppendNumericBytes.
// Should use appendNumericBytes.
// 1 = 01 = 0001 in 4 bits.
BitVector bits = new BitVector();
Encoder.AppendBytes(new ByteArray("1"), QRCode.MODE_NUMERIC, bits);
Encoder.appendBytes(new ByteArray("1"), QRCode.MODE_NUMERIC, bits);
assertEquals("0001" , bits.toString());
// 'A' cannot be encoded in MODE_NUMERIC.
try {
Encoder.AppendBytes(new ByteArray("A"), QRCode.MODE_NUMERIC, bits);
Encoder.appendBytes(new ByteArray("A"), QRCode.MODE_NUMERIC, bits);
fail("Should have thrown exception");
} catch (WriterException we) {
// good
}
}
{
// Should use AppendAlphanumericBytes.
// Should use appendAlphanumericBytes.
// A = 10 = 0xa = 001010 in 6 bits
BitVector bits = new BitVector();
Encoder.AppendBytes(new ByteArray("A"), QRCode.MODE_ALPHANUMERIC, bits);
Encoder.appendBytes(new ByteArray("A"), QRCode.MODE_ALPHANUMERIC, bits);
assertEquals("001010" , bits.toString());
// Lower letters such as 'a' cannot be encoded in MODE_ALPHANUMERIC.
try {
Encoder.AppendBytes(new ByteArray("a"), QRCode.MODE_ALPHANUMERIC, bits);
Encoder.appendBytes(new ByteArray("a"), QRCode.MODE_ALPHANUMERIC, bits);
} catch (WriterException we) {
// good
}
}
{
// Should use Append8BitBytes.
// Should use append8BitBytes.
// 0x61, 0x62, 0x63
BitVector bits = new BitVector();
Encoder.AppendBytes(new ByteArray("abc"), QRCode.MODE_8BIT_BYTE, bits);
Encoder.appendBytes(new ByteArray("abc"), QRCode.MODE_8BIT_BYTE, bits);
assertEquals("01100001" + "01100010" + "01100011", bits.toString());
// Anything can be encoded in QRCode.MODE_8BIT_BYTE.
byte[] bytes = {0x00};
Encoder.AppendBytes(new ByteArray(bytes), QRCode.MODE_8BIT_BYTE, bits);
Encoder.appendBytes(new ByteArray(bytes), QRCode.MODE_8BIT_BYTE, bits);
}
{
// Should use AppendKanjiBytes.
// Should use appendKanjiBytes.
// 0x93, 0x5f
BitVector bits = new BitVector();
byte[] bytes = {(byte)0x93,0x5f};
Encoder.AppendBytes(new ByteArray(bytes), QRCode.MODE_KANJI, bits);
Encoder.appendBytes(new ByteArray(bytes), QRCode.MODE_KANJI, bits);
assertEquals("0110110011111", bits.toString());
// ASCII characters can not be encoded in QRCode.MODE_KANJI.
try {
Encoder.AppendBytes(new ByteArray("a"), QRCode.MODE_KANJI, bits);
Encoder.appendBytes(new ByteArray("a"), QRCode.MODE_KANJI, bits);
} catch (WriterException we) {
// good
}
@ -227,90 +227,90 @@ public final class EncoderTestCase extends TestCase {
public void testTerminateBits() throws WriterException {
{
BitVector v = new BitVector();
Encoder.TerminateBits(0, v);
Encoder.terminateBits(0, v);
assertEquals("", v.toString());
}
{
BitVector v = new BitVector();
Encoder.TerminateBits(1, v);
Encoder.terminateBits(1, v);
assertEquals("00000000", v.toString());
}
{
BitVector v = new BitVector();
v.appendBits(0, 3); // Append 000
Encoder.TerminateBits(1, v);
Encoder.terminateBits(1, v);
assertEquals("00000000", v.toString());
}
{
BitVector v = new BitVector();
v.appendBits(0, 5); // Append 00000
Encoder.TerminateBits(1, v);
Encoder.terminateBits(1, v);
assertEquals("00000000", v.toString());
}
{
BitVector v = new BitVector();
v.appendBits(0, 8); // Append 00000000
Encoder.TerminateBits(1, v);
Encoder.terminateBits(1, v);
assertEquals("00000000", v.toString());
}
{
BitVector v = new BitVector();
Encoder.TerminateBits(2, v);
Encoder.terminateBits(2, v);
assertEquals("0000000011101100", v.toString());
}
{
BitVector v = new BitVector();
v.appendBits(0, 1); // Append 0
Encoder.TerminateBits(3, v);
Encoder.terminateBits(3, v);
assertEquals("000000001110110000010001", v.toString());
}
}
public void testGetNumDataBytesAndNumECBytesForBlockID() throws WriterException {
int[] num_data_bytes = new int[1];
int[] num_ec_bytes = new int[1];
int[] numDataBytes = new int[1];
int[] numEcBytes = new int[1];
// Version 1-H.
Encoder.GetNumDataBytesAndNumECBytesForBlockID(26, 9, 1, 0, num_data_bytes, num_ec_bytes);
assertEquals(9, num_data_bytes[0]);
assertEquals(17, num_ec_bytes[0]);
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, num_data_bytes, num_ec_bytes);
assertEquals(13, num_data_bytes[0]);
assertEquals(22, num_ec_bytes[0]);
Encoder.GetNumDataBytesAndNumECBytesForBlockID(70, 26, 2, 1, num_data_bytes, num_ec_bytes);
assertEquals(13, num_data_bytes[0]);
assertEquals(22, num_ec_bytes[0]);
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, num_data_bytes, num_ec_bytes);
assertEquals(13, num_data_bytes[0]);
assertEquals(26, num_ec_bytes[0]);
Encoder.GetNumDataBytesAndNumECBytesForBlockID(196, 66, 5, 4, num_data_bytes, num_ec_bytes);
assertEquals(14, num_data_bytes[0]);
assertEquals(26, num_ec_bytes[0]);
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, num_data_bytes, num_ec_bytes);
assertEquals(15, num_data_bytes[0]);
assertEquals(30, num_ec_bytes[0]);
Encoder.GetNumDataBytesAndNumECBytesForBlockID(3706, 1276, 81, 20, num_data_bytes, num_ec_bytes);
assertEquals(16, num_data_bytes[0]);
assertEquals(30, num_ec_bytes[0]);
Encoder.GetNumDataBytesAndNumECBytesForBlockID(3706, 1276, 81, 80, num_data_bytes, num_ec_bytes);
assertEquals(16, num_data_bytes[0]);
assertEquals(30, num_ec_bytes[0]);
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]);
}
public void testInterleaveWithECBytes() throws WriterException {
{
final byte[] data_bytes = {32, 65, (byte)205, 69, 41, (byte)220, 46, (byte)128, (byte)236};
final byte[] dataBytes = {32, 65, (byte)205, 69, 41, (byte)220, 46, (byte)128, (byte)236};
BitVector in = new BitVector();
for (byte data_byte: data_bytes) {
in.appendBits(data_byte, 8);
for (byte dataByte: dataBytes) {
in.appendBits(dataByte, 8);
}
BitVector out = new BitVector();
Encoder.InterleaveWithECBytes(in, 26, 9, 1, out);
Encoder.interleaveWithECBytes(in, 26, 9, 1, out);
final byte[] expected = {
// Data bytes.
32, 65, (byte)205, 69, 41, (byte)220, 46, (byte)128, (byte)236,
@ -319,15 +319,15 @@ public final class EncoderTestCase extends TestCase {
(byte)237, 85, (byte)224, 96, 74, (byte)219, 61,
};
assertEquals(expected.length, out.sizeInBytes());
final byte[] out_array = out.getArray();
// Can't use Arrays.equals(), because out_array may be longer than out.sizeInBytes()
final byte[] outArray = out.getArray();
// Can't use Arrays.equals(), because outArray may be longer than out.sizeInBytes()
for (int x = 0; x < expected.length; x++) {
assertEquals(expected[x], out_array[x]);
assertEquals(expected[x], outArray[x]);
}
}
// Numbers are from http://www.swetake.com/qr/qr8.html
{
final byte[] data_bytes = {
final byte[] dataBytes = {
67, 70, 22, 38, 54, 70, 86, 102, 118, (byte)134, (byte)150, (byte)166, (byte)182,
(byte)198, (byte)214, (byte)230, (byte)247, 7, 23, 39, 55, 71, 87, 103, 119, (byte)135,
(byte)151, (byte)166, 22, 38, 54, 70, 86, 102, 118, (byte)134, (byte)150, (byte)166,
@ -336,11 +336,11 @@ public final class EncoderTestCase extends TestCase {
17
};
BitVector in = new BitVector();
for (byte data_byte: data_bytes) {
in.appendBits(data_byte, 8);
for (byte dataByte: dataBytes) {
in.appendBits(dataByte, 8);
}
BitVector out = new BitVector();
Encoder.InterleaveWithECBytes(in, 134, 62, 4, out);
Encoder.interleaveWithECBytes(in, 134, 62, 4, out);
final byte[] expected = {
// Data bytes.
67, (byte)230, 54, 55, 70, (byte)247, 70, 71, 22, 7, 86, 87, 38, 23, 102, 103, 54, 39,
@ -359,9 +359,9 @@ public final class EncoderTestCase extends TestCase {
(byte)187, 49, (byte)156, (byte)214,
};
assertEquals(expected.length, out.sizeInBytes());
final byte[] out_array = out.getArray();
final byte[] outArray = out.getArray();
for (int x = 0; x < expected.length; x++) {
assertEquals(expected[x], out_array[x]);
assertEquals(expected[x], outArray[x]);
}
}
}
@ -370,38 +370,38 @@ public final class EncoderTestCase extends TestCase {
{
// 1 = 01 = 0001 in 4 bits.
BitVector bits = new BitVector();
Encoder.AppendNumericBytes(new ByteArray("1"), bits);
Encoder.appendNumericBytes(new ByteArray("1"), bits);
assertEquals("0001" , bits.toString());
}
{
// 12 = 0xc = 0001100 in 7 bits.
BitVector bits = new BitVector();
Encoder.AppendNumericBytes(new ByteArray("12"), bits);
Encoder.appendNumericBytes(new ByteArray("12"), bits);
assertEquals("0001100" , bits.toString());
}
{
// 123 = 0x7b = 0001111011 in 10 bits.
BitVector bits = new BitVector();
Encoder.AppendNumericBytes(new ByteArray("123"), bits);
Encoder.appendNumericBytes(new ByteArray("123"), bits);
assertEquals("0001111011" , bits.toString());
}
{
// 1234 = "123" + "4" = 0001111011 + 0100
BitVector bits = new BitVector();
Encoder.AppendNumericBytes(new ByteArray("1234"), bits);
Encoder.appendNumericBytes(new ByteArray("1234"), bits);
assertEquals("0001111011" + "0100" , bits.toString());
}
{
// Empty.
BitVector bits = new BitVector();
Encoder.AppendNumericBytes(new ByteArray(""), bits);
Encoder.appendNumericBytes(new ByteArray(""), bits);
assertEquals("" , bits.toString());
}
{
// Invalid data.
BitVector bits = new BitVector();
try {
Encoder.AppendNumericBytes(new ByteArray("abc"), bits);
Encoder.appendNumericBytes(new ByteArray("abc"), bits);
} catch (WriterException we) {
// good
}
@ -412,32 +412,32 @@ public final class EncoderTestCase extends TestCase {
{
// A = 10 = 0xa = 001010 in 6 bits
BitVector bits = new BitVector();
Encoder.AppendAlphanumericBytes(new ByteArray("A"), bits);
Encoder.appendAlphanumericBytes(new ByteArray("A"), bits);
assertEquals("001010" , bits.toString());
}
{
// AB = 10 * 45 + 11 = 461 = 0x1cd = 00111001101 in 11 bits
BitVector bits = new BitVector();
Encoder.AppendAlphanumericBytes(new ByteArray("AB"), bits);
Encoder.appendAlphanumericBytes(new ByteArray("AB"), bits);
assertEquals("00111001101", bits.toString());
}
{
// ABC = "AB" + "C" = 00111001101 + 001100
BitVector bits = new BitVector();
Encoder.AppendAlphanumericBytes(new ByteArray("ABC"), bits);
Encoder.appendAlphanumericBytes(new ByteArray("ABC"), bits);
assertEquals("00111001101" + "001100" , bits.toString());
}
{
// Empty.
BitVector bits = new BitVector();
Encoder.AppendAlphanumericBytes(new ByteArray(""), bits);
Encoder.appendAlphanumericBytes(new ByteArray(""), bits);
assertEquals("" , bits.toString());
}
{
// Invalid data.
BitVector bits = new BitVector();
try {
Encoder.AppendAlphanumericBytes(new ByteArray("abc"), bits);
Encoder.appendAlphanumericBytes(new ByteArray("abc"), bits);
} catch (WriterException we) {
// good
}
@ -448,13 +448,13 @@ public final class EncoderTestCase extends TestCase {
{
// 0x61, 0x62, 0x63
BitVector bits = new BitVector();
Encoder.Append8BitBytes(new ByteArray("abc"), bits);
Encoder.append8BitBytes(new ByteArray("abc"), bits);
assertEquals("01100001" + "01100010" + "01100011", bits.toString());
}
{
// Empty.
BitVector bits = new BitVector();
Encoder.Append8BitBytes(new ByteArray(""), bits);
Encoder.append8BitBytes(new ByteArray(""), bits);
assertEquals("", bits.toString());
}
}
@ -464,10 +464,10 @@ public final class EncoderTestCase extends TestCase {
{
BitVector bits = new BitVector();
byte[] dat1 = {(byte)0x93,0x5f};
Encoder.AppendKanjiBytes(new ByteArray(dat1), bits);
Encoder.appendKanjiBytes(new ByteArray(dat1), bits);
assertEquals("0110110011111", bits.toString());
byte[] dat2 = {(byte)0xe4,(byte)0xaa};
Encoder.AppendKanjiBytes(new ByteArray(dat2), bits);
Encoder.appendKanjiBytes(new ByteArray(dat2), bits);
assertEquals("0110110011111" + "1101010101010", bits.toString());
}
}
@ -539,52 +539,52 @@ public final class EncoderTestCase extends TestCase {
// http://www.swetake.com/qr/qr9.html
public void testGenerateECBytes() {
{
final byte[] data_bytes = {32, 65, (byte)205, 69, 41, (byte)220, 46, (byte)128, (byte)236};
ByteArray ec_bytes = Encoder.GenerateECBytes(new ByteArray(data_bytes), 17);
final byte[] dataBytes = {32, 65, (byte)205, 69, 41, (byte)220, 46, (byte)128, (byte)236};
ByteArray ecBytes = Encoder.generateECBytes(new ByteArray(dataBytes), 17);
final int[] expected = {
42, 159, 74, 221, 244, 169, 239, 150, 138, 70, 237, 85, 224, 96, 74, 219, 61
};
assertEquals(expected.length, ec_bytes.size());
assertEquals(expected.length, ecBytes.size());
for (int x = 0; x < expected.length; x++) {
assertEquals(expected[x], ec_bytes.at(x));
assertEquals(expected[x], ecBytes.at(x));
}
}
{
final byte[] data_bytes = {67, 70, 22, 38, 54, 70, 86, 102, 118,
final byte[] dataBytes = {67, 70, 22, 38, 54, 70, 86, 102, 118,
(byte)134, (byte)150, (byte)166, (byte)182, (byte)198, (byte)214};
ByteArray ec_bytes = Encoder.GenerateECBytes(new ByteArray(data_bytes), 18);
ByteArray ecBytes = Encoder.generateECBytes(new ByteArray(dataBytes), 18);
final int[] expected = {
175, 80, 155, 64, 178, 45, 214, 233, 65, 209, 12, 155, 117, 31, 140, 214, 27, 187
};
assertEquals(expected.length, ec_bytes.size());
assertEquals(expected.length, ecBytes.size());
for (int x = 0; x < expected.length; x++) {
assertEquals(expected[x], ec_bytes.at(x));
assertEquals(expected[x], ecBytes.at(x));
}
}
{
// High-order zero cofficient case.
final byte[] data_bytes = {32, 49, (byte)205, 69, 42, 20, 0, (byte)236, 17};
ByteArray ec_bytes = Encoder.GenerateECBytes(new ByteArray(data_bytes), 17);
final byte[] dataBytes = {32, 49, (byte)205, 69, 42, 20, 0, (byte)236, 17};
ByteArray ecBytes = Encoder.generateECBytes(new ByteArray(dataBytes), 17);
final int[] expected = {
0, 3, 130, 179, 194, 0, 55, 211, 110, 79, 98, 72, 170, 96, 211, 137, 213
};
assertEquals(expected.length, ec_bytes.size());
assertEquals(expected.length, ecBytes.size());
for (int x = 0; x < expected.length; x++) {
assertEquals(expected[x], ec_bytes.at(x));
assertEquals(expected[x], ecBytes.at(x));
}
}
}
public void testIsValidKanji() {
assertTrue(Encoder.IsValidKanji(0x82, 0xa0)); // Hiragana "A".
assertTrue(Encoder.IsValidKanji(0x93, 0xfa)); // Nichi in Kanji.
assertTrue(Encoder.IsValidKanji(0x8a, 0xbf)); // Kan in Kanji.
assertTrue(Encoder.IsValidKanji(0xe7, 0x4e)); // Sou in Kanji.
assertTrue(Encoder.IsValidKanji(0xea, 0xa2)); // Haruka in Kanji.
assertTrue(Encoder.isValidKanji(0x82, 0xa0)); // Hiragana "A".
assertTrue(Encoder.isValidKanji(0x93, 0xfa)); // Nichi in Kanji.
assertTrue(Encoder.isValidKanji(0x8a, 0xbf)); // Kan in Kanji.
assertTrue(Encoder.isValidKanji(0xe7, 0x4e)); // Sou in Kanji.
assertTrue(Encoder.isValidKanji(0xea, 0xa2)); // Haruka in Kanji.
assertFalse(Encoder.IsValidKanji('0', '1'));
assertFalse(Encoder.IsValidKanji(0x82, 0x7f));
assertFalse(Encoder.IsValidKanji(0xa0, 0xa0));
assertFalse(Encoder.isValidKanji('0', '1'));
assertFalse(Encoder.isValidKanji(0x82, 0x7f));
assertFalse(Encoder.isValidKanji(0xa0, 0xa0));
}
public void testIsValidKanjiSequence() {
@ -592,24 +592,24 @@ public final class EncoderTestCase extends TestCase {
byte[] dat1 = {
(byte)0x83, 0x41, (byte)0x83, 0x43, (byte)0x83, 0x45, (byte)0x83, 0x47, (byte)0x83, 0x49
};
assertTrue(Encoder.IsValidKanjiSequence(new ByteArray(dat1)));
assertTrue(Encoder.isValidKanjiSequence(new ByteArray(dat1)));
// 012345 in multi-byte letters.
byte[] dat2 = {
(byte)0x82, 0x4f, (byte)0x82, 0x50, (byte)0x82, 0x51, (byte)0x82, 0x52, (byte)0x82, 0x53,
(byte)0x82, 0x54
};
assertTrue(Encoder.IsValidKanjiSequence(new ByteArray(dat2)));
assertTrue(Encoder.isValidKanjiSequence(new ByteArray(dat2)));
// Yoroshiku in Kanji.
byte[] dat3 = {
(byte)0x96, (byte)0xe9, (byte)0x98, 0x49, (byte)0x8e, (byte)0x80, (byte)0x8b, (byte)0xea
};
assertTrue(Encoder.IsValidKanjiSequence(new ByteArray(dat3)));
assertFalse(Encoder.IsValidKanjiSequence(new ByteArray("0123")));
assertFalse(Encoder.IsValidKanjiSequence(new ByteArray("ABC")));
assertTrue(Encoder.isValidKanjiSequence(new ByteArray(dat3)));
assertFalse(Encoder.isValidKanjiSequence(new ByteArray("0123")));
assertFalse(Encoder.isValidKanjiSequence(new ByteArray("ABC")));
}
public void testBugInBitVectorNumBytes() throws WriterException {
// There was a bug in BitVector::sizeInBytes() that caused it to return a
// 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
@ -633,16 +633,16 @@ public final class EncoderTestCase extends TestCase {
// (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 (mode info) + 14 (length info) =
// - 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).
final int arraySize = 3518;
byte[] data_bytes = new byte[arraySize];
byte[] dataBytes = new byte[arraySize];
for (int x = 0; x < arraySize; x++) {
data_bytes[x] = '0';
dataBytes[x] = '0';
}
QRCode qr_code = new QRCode();
Encoder.Encode(new ByteArray(data_bytes), QRCode.EC_LEVEL_L, qr_code);
QRCode qrCode = new QRCode();
Encoder.encode(new ByteArray(dataBytes), QRCode.EC_LEVEL_L, qrCode);
}
}

View file

@ -33,7 +33,7 @@ public final class MaskUtilTestCase extends TestCase {
matrix.set(0, 1, 0);
matrix.set(0, 2, 0);
matrix.set(0, 3, 0);
assertEquals(0, MaskUtil.ApplyMaskPenaltyRule1(matrix));
assertEquals(0, MaskUtil.applyMaskPenaltyRule1(matrix));
}
{ // Horizontal.
ByteMatrix matrix = new ByteMatrix(1, 6);
@ -43,9 +43,9 @@ public final class MaskUtilTestCase extends TestCase {
matrix.set(0, 3, 0);
matrix.set(0, 4, 0);
matrix.set(0, 5, 1);
assertEquals(3, MaskUtil.ApplyMaskPenaltyRule1(matrix));
assertEquals(3, MaskUtil.applyMaskPenaltyRule1(matrix));
matrix.set(0, 5, 0);
assertEquals(4, MaskUtil.ApplyMaskPenaltyRule1(matrix));
assertEquals(4, MaskUtil.applyMaskPenaltyRule1(matrix));
}
{ // Vertical.
ByteMatrix matrix = new ByteMatrix(6, 1);
@ -55,9 +55,9 @@ public final class MaskUtilTestCase extends TestCase {
matrix.set(3, 0, 0);
matrix.set(4, 0, 0);
matrix.set(5, 0, 1);
assertEquals(3, MaskUtil.ApplyMaskPenaltyRule1(matrix));
assertEquals(3, MaskUtil.applyMaskPenaltyRule1(matrix));
matrix.set(5, 0, 0);
assertEquals(4, MaskUtil.ApplyMaskPenaltyRule1(matrix));
assertEquals(4, MaskUtil.applyMaskPenaltyRule1(matrix));
}
}
@ -65,7 +65,7 @@ public final class MaskUtilTestCase extends TestCase {
{
ByteMatrix matrix = new ByteMatrix(1, 1);
matrix.set(0, 0, 0);
assertEquals(0, MaskUtil.ApplyMaskPenaltyRule2(matrix));
assertEquals(0, MaskUtil.applyMaskPenaltyRule2(matrix));
}
{
ByteMatrix matrix = new ByteMatrix(2, 2);
@ -73,7 +73,7 @@ public final class MaskUtilTestCase extends TestCase {
matrix.set(0, 1, 0);
matrix.set(1, 0, 0);
matrix.set(1, 1, 1);
assertEquals(0, MaskUtil.ApplyMaskPenaltyRule2(matrix));
assertEquals(0, MaskUtil.applyMaskPenaltyRule2(matrix));
}
{
ByteMatrix matrix = new ByteMatrix(2, 2);
@ -81,7 +81,7 @@ public final class MaskUtilTestCase extends TestCase {
matrix.set(0, 1, 0);
matrix.set(1, 0, 0);
matrix.set(1, 1, 0);
assertEquals(3, MaskUtil.ApplyMaskPenaltyRule2(matrix));
assertEquals(3, MaskUtil.applyMaskPenaltyRule2(matrix));
}
{
ByteMatrix matrix = new ByteMatrix(3, 3);
@ -95,7 +95,7 @@ public final class MaskUtilTestCase extends TestCase {
matrix.set(2, 1, 0);
matrix.set(2, 2, 0);
// Four instances of 2x2 blocks.
assertEquals(3 * 4, MaskUtil.ApplyMaskPenaltyRule2(matrix));
assertEquals(3 * 4, MaskUtil.applyMaskPenaltyRule2(matrix));
}
}
@ -114,7 +114,7 @@ public final class MaskUtilTestCase extends TestCase {
matrix.set(0, 8, 1);
matrix.set(0, 9, 0);
matrix.set(0, 10, 1);
assertEquals(40, MaskUtil.ApplyMaskPenaltyRule3(matrix));
assertEquals(40, MaskUtil.applyMaskPenaltyRule3(matrix));
}
{
// Horizontal 10111010000.
@ -130,7 +130,7 @@ public final class MaskUtilTestCase extends TestCase {
matrix.set(0, 8, 0);
matrix.set(0, 9, 0);
matrix.set(0, 10, 0);
assertEquals(40, MaskUtil.ApplyMaskPenaltyRule3(matrix));
assertEquals(40, MaskUtil.applyMaskPenaltyRule3(matrix));
}
{
// Vertical 00001011101.
@ -146,7 +146,7 @@ public final class MaskUtilTestCase extends TestCase {
matrix.set(8, 0, 1);
matrix.set(9, 0, 0);
matrix.set(10, 0, 1);
assertEquals(40, MaskUtil.ApplyMaskPenaltyRule3(matrix));
assertEquals(40, MaskUtil.applyMaskPenaltyRule3(matrix));
}
{
// Vertical 10111010000.
@ -162,7 +162,7 @@ public final class MaskUtilTestCase extends TestCase {
matrix.set(8, 0, 0);
matrix.set(9, 0, 0);
matrix.set(10, 0, 0);
assertEquals(40, MaskUtil.ApplyMaskPenaltyRule3(matrix));
assertEquals(40, MaskUtil.applyMaskPenaltyRule3(matrix));
}
}
@ -171,14 +171,14 @@ public final class MaskUtilTestCase extends TestCase {
// Dark cell ratio = 0%
ByteMatrix matrix = new ByteMatrix(1, 1);
matrix.set(0, 0, 0);
assertEquals(100, MaskUtil.ApplyMaskPenaltyRule4(matrix));
assertEquals(100, MaskUtil.applyMaskPenaltyRule4(matrix));
}
{
// Dark cell ratio = 5%
ByteMatrix matrix = new ByteMatrix(1, 2);
matrix.set(0, 0, 0);
matrix.set(0, 0, 1);
assertEquals(0, MaskUtil.ApplyMaskPenaltyRule4(matrix));
assertEquals(0, MaskUtil.applyMaskPenaltyRule4(matrix));
}
{
// Dark cell ratio = 66.67%
@ -189,16 +189,16 @@ public final class MaskUtilTestCase extends TestCase {
matrix.set(0, 3, 1);
matrix.set(0, 4, 1);
matrix.set(0, 5, 0);
assertEquals(30, MaskUtil.ApplyMaskPenaltyRule4(matrix));
assertEquals(30, MaskUtil.applyMaskPenaltyRule4(matrix));
}
}
private static boolean TestGetDataMaskBitInternal(int mask_pattern,
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] !=
MaskUtil.GetDataMaskBit(mask_pattern, x, y)) {
MaskUtil.getDataMaskBit(maskPattern, x, y)) {
return false;
}
}

View file

@ -42,7 +42,7 @@ public final class MatrixUtilTestCase extends TestCase {
public void testClearMatrix() {
ByteMatrix matrix = new ByteMatrix(2, 2);
MatrixUtil.ClearMatrix(matrix);
MatrixUtil.clearMatrix(matrix);
assertEquals(-1, matrix.get(0, 0));
assertEquals(-1, matrix.get(0, 1));
assertEquals(-1, matrix.get(1, 0));
@ -75,8 +75,8 @@ public final class MatrixUtilTestCase extends TestCase {
" 1 0 0 0 0 0 1 0 \n" +
" 1 1 1 1 1 1 1 0 \n";
ByteMatrix matrix = new ByteMatrix(21, 21);
MatrixUtil.ClearMatrix(matrix);
MatrixUtil.EmbedBasicPatterns(1, matrix);
MatrixUtil.clearMatrix(matrix);
MatrixUtil.embedBasicPatterns(1, matrix);
assertEquals(expected, matrix.toString());
}
{
@ -109,8 +109,8 @@ public final class MatrixUtilTestCase extends TestCase {
" 1 0 0 0 0 0 1 0 \n" +
" 1 1 1 1 1 1 1 0 \n";
ByteMatrix matrix = new ByteMatrix(25, 25);
MatrixUtil.ClearMatrix(matrix);
MatrixUtil.EmbedBasicPatterns(2, matrix);
MatrixUtil.clearMatrix(matrix);
MatrixUtil.embedBasicPatterns(2, matrix);
assertEquals(expected, matrix.toString());
}
}
@ -140,8 +140,8 @@ public final class MatrixUtilTestCase extends TestCase {
" 0 \n" +
" 1 \n";
ByteMatrix matrix = new ByteMatrix(21, 21);
MatrixUtil.ClearMatrix(matrix);
MatrixUtil.EmbedTypeInfo(QRCode.EC_LEVEL_M, 5, matrix);
MatrixUtil.clearMatrix(matrix);
MatrixUtil.embedTypeInfo(QRCode.EC_LEVEL_M, 5, matrix);
assertEquals(expected, matrix.toString());
}
@ -172,8 +172,8 @@ public final class MatrixUtilTestCase extends TestCase {
// 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(7, matrix);
MatrixUtil.clearMatrix(matrix);
MatrixUtil.maybeEmbedVersionInfo(7, matrix);
assertEquals(expected, matrix.toString());
}
@ -203,9 +203,9 @@ public final class MatrixUtilTestCase extends TestCase {
" 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n";
BitVector bits = new BitVector();
ByteMatrix matrix = new ByteMatrix(21, 21);
MatrixUtil.ClearMatrix(matrix);
MatrixUtil.EmbedBasicPatterns(1, matrix);
MatrixUtil.EmbedDataBits(bits, -1, matrix);
MatrixUtil.clearMatrix(matrix);
MatrixUtil.embedBasicPatterns(1, matrix);
MatrixUtil.embedDataBits(bits, -1, matrix);
assertEquals(expected, matrix.toString());
}
@ -241,7 +241,7 @@ public final class MatrixUtilTestCase extends TestCase {
bits.appendBits(c, 8);
}
ByteMatrix matrix = new ByteMatrix(21, 21);
MatrixUtil.BuildMatrix(bits,
MatrixUtil.buildMatrix(bits,
QRCode.EC_LEVEL_H,
1, // Version 1
3, // Mask pattern 3
@ -249,47 +249,47 @@ public final class MatrixUtilTestCase extends TestCase {
}
public void testFindMSBSet() {
assertEquals(0, MatrixUtil.FindMSBSet(0));
assertEquals(1, MatrixUtil.FindMSBSet(1));
assertEquals(8, MatrixUtil.FindMSBSet(0x80));
assertEquals(32, MatrixUtil.FindMSBSet(0x80000000));
assertEquals(0, MatrixUtil.findMSBSet(0));
assertEquals(1, MatrixUtil.findMSBSet(1));
assertEquals(8, MatrixUtil.findMSBSet(0x80));
assertEquals(32, MatrixUtil.findMSBSet(0x80000000));
}
public void testCalculateBCHCode() {
// Encoding of type information.
// From Appendix C in JISX0510:2004 (p 65)
assertEquals(0xdc, MatrixUtil.CalculateBCHCode(5, 0x537));
assertEquals(0xdc, MatrixUtil.calculateBCHCode(5, 0x537));
// From http://www.swetake.com/qr/qr6.html
assertEquals(0x1c2, MatrixUtil.CalculateBCHCode(0x13, 0x537));
assertEquals(0x1c2, MatrixUtil.calculateBCHCode(0x13, 0x537));
// From http://www.swetake.com/qr/qr11.html
assertEquals(0x214, MatrixUtil.CalculateBCHCode(0x1b, 0x537));
assertEquals(0x214, MatrixUtil.calculateBCHCode(0x1b, 0x537));
// Encofing 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));
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).
// tested them in TEST(calculateBCHCode).
public void testMakeVersionInfoBits() throws WriterException {
// From Appendix D in JISX0510:2004 (p 68)
BitVector bits = new BitVector();
MatrixUtil.MakeVersionInfoBits(7, bits);
MatrixUtil.makeVersionInfoBits(7, bits);
assertEquals("000111110010010100", bits.toString());
}
// We don't test a lot of cases in this function since we've already
// tested them in TEST(CalculateBCHCode).
// tested them in TEST(calculateBCHCode).
public void testMakeTypeInfoInfoBits() throws WriterException {
// From Appendix C in JISX0510:2004 (p 65)
BitVector bits = new BitVector();
MatrixUtil.MakeTypeInfoBits(QRCode.EC_LEVEL_M,
MatrixUtil.makeTypeInfoBits(QRCode.EC_LEVEL_M,
5, bits);
assertEquals("100000011001110", bits.toString());
}

View file

@ -26,34 +26,34 @@ import junit.framework.TestCase;
*/
public final class QRCodeTestCase extends TestCase {
public void test() {
QRCode qr_code = new QRCode();
QRCode qrCode = new QRCode();
// Initially the QR Code should be invalid.
assertFalse(qr_code.IsValid());
assertFalse(qrCode.isValid());
// First, test simple setters and getters.
// We use numbers of version 7-H.
qr_code.set_mode(QRCode.MODE_8BIT_BYTE);
qr_code.set_ec_level(QRCode.EC_LEVEL_H);
qr_code.set_version(7);
qr_code.set_matrix_width(45);
qr_code.set_mask_pattern(3);
qr_code.set_num_total_bytes(196);
qr_code.set_num_data_bytes(66);
qr_code.set_num_ec_bytes(130);
qr_code.set_num_rs_blocks(5);
qrCode.setMode(QRCode.MODE_8BIT_BYTE);
qrCode.setECLevel(QRCode.EC_LEVEL_H);
qrCode.setVersion(7);
qrCode.setMatrixWidth(45);
qrCode.setMaskPattern(3);
qrCode.setNumTotalBytes(196);
qrCode.setNumDataBytes(66);
qrCode.setNumECBytes(130);
qrCode.setNumRSBlocks(5);
assertEquals(QRCode.MODE_8BIT_BYTE, qr_code.mode());
assertEquals(QRCode.EC_LEVEL_H, qr_code.ec_level());
assertEquals(7, qr_code.version());
assertEquals(45, qr_code.matrix_width());
assertEquals(3, qr_code.mask_pattern());
assertEquals(196, qr_code.num_total_bytes());
assertEquals(66, qr_code.num_data_bytes());
assertEquals(130, qr_code.num_ec_bytes());
assertEquals(5, qr_code.num_rs_blocks());
assertEquals(QRCode.MODE_8BIT_BYTE, qrCode.getMode());
assertEquals(QRCode.EC_LEVEL_H, qrCode.getECLevel());
assertEquals(7, qrCode.getVersion());
assertEquals(45, qrCode.getMatrixWidth());
assertEquals(3, qrCode.getMaskPattern());
assertEquals(196, qrCode.getNumTotalBytes());
assertEquals(66, qrCode.getNumDataBytes());
assertEquals(130, qrCode.getNumECBytes());
assertEquals(5, qrCode.getNumRSBlocks());
// It still should be invalid.
assertFalse(qr_code.IsValid());
assertFalse(qrCode.isValid());
// Prepare the matrix.
ByteMatrix matrix = new ByteMatrix(45, 45);
@ -65,50 +65,50 @@ public final class QRCodeTestCase extends TestCase {
}
// Set the matrix.
qr_code.set_matrix(matrix);
assertEquals(matrix, qr_code.matrix());
qrCode.setMatrix(matrix);
assertEquals(matrix, qrCode.getMatrix());
// Finally, it should be valid.
assertTrue(qr_code.IsValid());
assertTrue(qrCode.isValid());
// Make sure "at()" returns the same value.
for (int y = 0; y < 45; ++y) {
for (int x = 0; x < 45; ++x) {
assertEquals((y + x) % 2, qr_code.at(x, y));
assertEquals((y + x) % 2, qrCode.at(x, y));
}
}
}
public void testToString() {
{
QRCode qr_code = new QRCode();
QRCode qrCode = new QRCode();
String expected =
"<<\n" +
" mode: UNDEFINED\n" +
" ec_level: UNDEFINED\n" +
" ecLevel: UNDEFINED\n" +
" version: -1\n" +
" matrix_width: -1\n" +
" mask_pattern: -1\n" +
" num_total_bytes_: -1\n" +
" num_data_bytes: -1\n" +
" num_ec_bytes: -1\n" +
" num_rs_blocks: -1\n" +
" matrixWidth: -1\n" +
" maskPattern: -1\n" +
" numTotalBytes: -1\n" +
" numDataBytes: -1\n" +
" numECBytes: -1\n" +
" numRSBlocks: -1\n" +
" matrix: null\n" +
">>\n";
assertEquals(expected, qr_code.toString());
assertEquals(expected, qrCode.toString());
}
{
String expected =
"<<\n" +
" mode: 8BIT_BYTE\n" +
" ec_level: H\n" +
" ecLevel: H\n" +
" version: 1\n" +
" matrix_width: 21\n" +
" mask_pattern: 3\n" +
" num_total_bytes_: 26\n" +
" num_data_bytes: 9\n" +
" num_ec_bytes: 17\n" +
" num_rs_blocks: 1\n" +
" matrixWidth: 21\n" +
" maskPattern: 3\n" +
" numTotalBytes: 26\n" +
" numDataBytes: 9\n" +
" numECBytes: 17\n" +
" numRSBlocks: 1\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" +
@ -132,90 +132,90 @@ public final class QRCodeTestCase extends TestCase {
" 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";
QRCode qr_code = new QRCode();
qr_code.set_mode(QRCode.MODE_8BIT_BYTE);
qr_code.set_ec_level(QRCode.EC_LEVEL_H);
qr_code.set_version(1);
qr_code.set_matrix_width(21);
qr_code.set_mask_pattern(3);
qr_code.set_num_total_bytes(26);
qr_code.set_num_data_bytes(9);
qr_code.set_num_ec_bytes(17);
qr_code.set_num_rs_blocks(1);
QRCode qrCode = new QRCode();
qrCode.setMode(QRCode.MODE_8BIT_BYTE);
qrCode.setECLevel(QRCode.EC_LEVEL_H);
qrCode.setVersion(1);
qrCode.setMatrixWidth(21);
qrCode.setMaskPattern(3);
qrCode.setNumTotalBytes(26);
qrCode.setNumDataBytes(9);
qrCode.setNumECBytes(17);
qrCode.setNumRSBlocks(1);
ByteMatrix matrix = new ByteMatrix(21, 21);
for (int y = 0; y < 21; ++y) {
for (int x = 0; x < 21; ++x) {
matrix.set(y, x, (y + x) % 2);
}
}
qr_code.set_matrix(matrix);
assertTrue(qr_code.IsValid());
assertEquals(expected, qr_code.toString());
qrCode.setMatrix(matrix);
assertTrue(qrCode.isValid());
assertEquals(expected, qrCode.toString());
}
}
public void testIsValidVersion() {
assertFalse(QRCode.IsValidVersion(0));
assertTrue(QRCode.IsValidVersion(1));
assertTrue(QRCode.IsValidVersion(40));
assertFalse(QRCode.IsValidVersion(0));
assertFalse(QRCode.isValidVersion(0));
assertTrue(QRCode.isValidVersion(1));
assertTrue(QRCode.isValidVersion(40));
assertFalse(QRCode.isValidVersion(0));
}
public void testIsValidECLevel() {
assertFalse(QRCode.IsValidECLevel(QRCode.EC_LEVEL_UNDEFINED));
assertTrue(QRCode.IsValidECLevel(QRCode.EC_LEVEL_L));
assertTrue(QRCode.IsValidECLevel(QRCode.EC_LEVEL_Q));
assertTrue(QRCode.IsValidECLevel(QRCode.EC_LEVEL_M));
assertTrue(QRCode.IsValidECLevel(QRCode.EC_LEVEL_H));
assertFalse(QRCode.IsValidECLevel(QRCode.NUM_EC_LEVELS));
assertFalse(QRCode.isValidECLevel(QRCode.EC_LEVEL_UNDEFINED));
assertTrue(QRCode.isValidECLevel(QRCode.EC_LEVEL_L));
assertTrue(QRCode.isValidECLevel(QRCode.EC_LEVEL_Q));
assertTrue(QRCode.isValidECLevel(QRCode.EC_LEVEL_M));
assertTrue(QRCode.isValidECLevel(QRCode.EC_LEVEL_H));
assertFalse(QRCode.isValidECLevel(QRCode.NUM_EC_LEVELS));
}
public void testIsValidMode() {
assertFalse(QRCode.IsValidMode(QRCode.MODE_UNDEFINED));
assertTrue(QRCode.IsValidMode(QRCode.MODE_NUMERIC));
assertTrue(QRCode.IsValidMode(QRCode.MODE_ALPHANUMERIC));
assertTrue(QRCode.IsValidMode(QRCode.MODE_8BIT_BYTE));
assertFalse(QRCode.IsValidMode(QRCode.NUM_MODES));
assertFalse(QRCode.isValidMode(QRCode.MODE_UNDEFINED));
assertTrue(QRCode.isValidMode(QRCode.MODE_NUMERIC));
assertTrue(QRCode.isValidMode(QRCode.MODE_ALPHANUMERIC));
assertTrue(QRCode.isValidMode(QRCode.MODE_8BIT_BYTE));
assertFalse(QRCode.isValidMode(QRCode.NUM_MODES));
}
public void testIsValidMatrixWidth() {
assertFalse(QRCode.IsValidMatrixWidth(20));
assertTrue(QRCode.IsValidMatrixWidth(21));
assertTrue(QRCode.IsValidMatrixWidth(177));
assertFalse(QRCode.IsValidMatrixWidth(178));
assertFalse(QRCode.isValidMatrixWidth(20));
assertTrue(QRCode.isValidMatrixWidth(21));
assertTrue(QRCode.isValidMatrixWidth(177));
assertFalse(QRCode.isValidMatrixWidth(178));
}
public void testIsValidMaskPattern() {
assertFalse(QRCode.IsValidMaskPattern(-1));
assertTrue(QRCode.IsValidMaskPattern(0));
assertTrue(QRCode.IsValidMaskPattern(7));
assertFalse(QRCode.IsValidMaskPattern(8));
assertFalse(QRCode.isValidMaskPattern(-1));
assertTrue(QRCode.isValidMaskPattern(0));
assertTrue(QRCode.isValidMaskPattern(7));
assertFalse(QRCode.isValidMaskPattern(8));
}
public void testModeToString() {
assertEquals("UNDEFINED", QRCode.ModeToString(QRCode.MODE_UNDEFINED));
assertEquals("NUMERIC", QRCode.ModeToString(QRCode.MODE_NUMERIC));
assertEquals("ALPHANUMERIC", QRCode.ModeToString(QRCode.MODE_ALPHANUMERIC));
assertEquals("8BIT_BYTE", QRCode.ModeToString(QRCode.MODE_8BIT_BYTE));
assertEquals("UNKNOWN", QRCode.ModeToString(QRCode.NUM_MODES));
assertEquals("UNDEFINED", QRCode.modeToString(QRCode.MODE_UNDEFINED));
assertEquals("NUMERIC", QRCode.modeToString(QRCode.MODE_NUMERIC));
assertEquals("ALPHANUMERIC", QRCode.modeToString(QRCode.MODE_ALPHANUMERIC));
assertEquals("8BIT_BYTE", QRCode.modeToString(QRCode.MODE_8BIT_BYTE));
assertEquals("UNKNOWN", QRCode.modeToString(QRCode.NUM_MODES));
}
public void testECLevelToString() {
assertEquals("UNDEFINED", QRCode.ECLevelToString(QRCode.EC_LEVEL_UNDEFINED));
assertEquals("L", QRCode.ECLevelToString(QRCode.EC_LEVEL_L));
assertEquals("M", QRCode.ECLevelToString(QRCode.EC_LEVEL_M));
assertEquals("Q", QRCode.ECLevelToString(QRCode.EC_LEVEL_Q));
assertEquals("H", QRCode.ECLevelToString(QRCode.EC_LEVEL_H));
assertEquals("UNKNOWN", QRCode.ECLevelToString(QRCode.NUM_EC_LEVELS));
assertEquals("UNDEFINED", QRCode.ecLevelToString(QRCode.EC_LEVEL_UNDEFINED));
assertEquals("L", QRCode.ecLevelToString(QRCode.EC_LEVEL_L));
assertEquals("M", QRCode.ecLevelToString(QRCode.EC_LEVEL_M));
assertEquals("Q", QRCode.ecLevelToString(QRCode.EC_LEVEL_Q));
assertEquals("H", QRCode.ecLevelToString(QRCode.EC_LEVEL_H));
assertEquals("UNKNOWN", QRCode.ecLevelToString(QRCode.NUM_EC_LEVELS));
}
public void testGetModeCode() throws WriterException {
assertEquals(1, QRCode.GetModeCode(QRCode.MODE_NUMERIC));
assertEquals(2, QRCode.GetModeCode(QRCode.MODE_ALPHANUMERIC));
assertEquals(4, QRCode.GetModeCode(QRCode.MODE_8BIT_BYTE));
assertEquals(8, QRCode.GetModeCode(QRCode.MODE_KANJI));
assertEquals(1, QRCode.getModeCode(QRCode.MODE_NUMERIC));
assertEquals(2, QRCode.getModeCode(QRCode.MODE_ALPHANUMERIC));
assertEquals(4, QRCode.getModeCode(QRCode.MODE_8BIT_BYTE));
assertEquals(8, QRCode.getModeCode(QRCode.MODE_KANJI));
try {
QRCode.GetModeCode(QRCode.MODE_UNDEFINED);
QRCode.getModeCode(QRCode.MODE_UNDEFINED);
fail("Should have thrown exception");
} catch (WriterException we) {
// good
@ -223,12 +223,12 @@ public final class QRCodeTestCase extends TestCase {
}
public void testGetECLevelCode() throws WriterException {
assertEquals(1, QRCode.GetECLevelCode(QRCode.EC_LEVEL_L));
assertEquals(0, QRCode.GetECLevelCode(QRCode.EC_LEVEL_M));
assertEquals(3, QRCode.GetECLevelCode(QRCode.EC_LEVEL_Q));
assertEquals(2, QRCode.GetECLevelCode(QRCode.EC_LEVEL_H));
assertEquals(1, QRCode.getECLevelCode(QRCode.EC_LEVEL_L));
assertEquals(0, QRCode.getECLevelCode(QRCode.EC_LEVEL_M));
assertEquals(3, QRCode.getECLevelCode(QRCode.EC_LEVEL_Q));
assertEquals(2, QRCode.getECLevelCode(QRCode.EC_LEVEL_H));
try {
QRCode.GetECLevelCode(QRCode.EC_LEVEL_UNDEFINED);
QRCode.getECLevelCode(QRCode.EC_LEVEL_UNDEFINED);
fail("Should have thrown exception");
} catch (WriterException we) {
// good