mirror of
https://github.com/zxing/zxing.git
synced 2025-03-05 20:48:51 -08:00
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:
parent
10a90bfecf
commit
416193ff9a
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue