Huge progress on the Encoder. I'm down to StringPiece errors (that class hasn't been replaced yet) and a few nasty methods, which call into Reed Solomon (not done yet).

git-svn-id: https://zxing.googlecode.com/svn/trunk@704 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
dswitkin 2008-11-14 18:43:54 +00:00
parent f80cd1ff51
commit fabdd40edf
2 changed files with 301 additions and 315 deletions

View file

@ -17,7 +17,6 @@
package com.google.zxing.qrcode.encoder; package com.google.zxing.qrcode.encoder;
// class GF_Poly; // class GF_Poly;
// #include "util/array/array2d-inl.h"
// #include "strings/stringpiece.h" // #include "strings/stringpiece.h"
// #include "util/reedsolomon/galois_field.h" // #include "util/reedsolomon/galois_field.h"
// #include "util/reedsolomon/galois_poly.h" // #include "util/reedsolomon/galois_poly.h"
@ -29,7 +28,7 @@ package com.google.zxing.qrcode.encoder;
public final class Encoder { public final class Encoder {
// The original table is defined in the table 5 of JISX0510:2004 (p.19). // The original table is defined in the table 5 of JISX0510:2004 (p.19).
static final int kAlphanumericTable[] = { private static final int kAlphanumericTable[] = {
-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, // 0x00-0x0f
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0x10-0x1f -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 36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43, // 0x20-0x2f
@ -38,242 +37,249 @@ public final class Encoder {
25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, // 0x50-0x5f 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, // 0x50-0x5f
}; };
class RSBlockInfo { private static final class RSBlockInfo {
int num_bytes; int num_bytes;
class { int block_info[][];
int num_ec_bytes;
int num_rs_blocks; public RSBlockInfo(int num_bytes, int[][] block_info) {
} block_info[4]; this.num_bytes = num_bytes;
this.block_info = block_info;
}
}
// 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[] = {
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
new RSBlockInfo( 100, new int[][]{ { 20, 1}, { 36, 2}, { 52, 2}, { 64, 4}}), // Version 4
new RSBlockInfo( 134, new int[][]{ { 26, 1}, { 48, 2}, { 72, 4}, { 88, 4}}), // Version 5
new RSBlockInfo( 172, new int[][]{ { 36, 2}, { 64, 4}, { 96, 4}, { 112, 4}}), // Version 6
new RSBlockInfo( 196, new int[][]{ { 40, 2}, { 72, 4}, { 108, 6}, { 130, 5}}), // Version 7
new RSBlockInfo( 242, new int[][]{ { 48, 2}, { 88, 4}, { 132, 6}, { 156, 6}}), // Version 8
new RSBlockInfo( 292, new int[][]{ { 60, 2}, { 110, 5}, { 160, 8}, { 192, 8}}), // Version 9
new RSBlockInfo( 346, new int[][]{ { 72, 4}, { 130, 5}, { 192, 8}, { 224, 8}}), // Version 10
new RSBlockInfo( 404, new int[][]{ { 80, 4}, { 150, 5}, { 224, 8}, { 264, 11}}), // Version 11
new RSBlockInfo( 466, new int[][]{ { 96, 4}, { 176, 8}, { 260, 10}, { 308, 11}}), // Version 12
new RSBlockInfo( 532, new int[][]{ {104, 4}, { 198, 9}, { 288, 12}, { 352, 16}}), // Version 13
new RSBlockInfo( 581, new int[][]{ {120, 4}, { 216, 9}, { 320, 16}, { 384, 16}}), // Version 14
new RSBlockInfo( 655, new int[][]{ {132, 6}, { 240, 10}, { 360, 12}, { 432, 18}}), // Version 15
new RSBlockInfo( 733, new int[][]{ {144, 6}, { 280, 10}, { 408, 17}, { 480, 16}}), // Version 16
new RSBlockInfo( 815, new int[][]{ {168, 6}, { 308, 11}, { 448, 16}, { 532, 19}}), // Version 17
new RSBlockInfo( 901, new int[][]{ {180, 6}, { 338, 13}, { 504, 18}, { 588, 21}}), // Version 18
new RSBlockInfo( 991, new int[][]{ {196, 7}, { 364, 14}, { 546, 21}, { 650, 25}}), // Version 19
new RSBlockInfo(1085, new int[][]{ {224, 8}, { 416, 16}, { 600, 20}, { 700, 25}}), // Version 20
new RSBlockInfo(1156, new int[][]{ {224, 8}, { 442, 17}, { 644, 23}, { 750, 25}}), // Version 21
new RSBlockInfo(1258, new int[][]{ {252, 9}, { 476, 17}, { 690, 23}, { 816, 34}}), // Version 22
new RSBlockInfo(1364, new int[][]{ {270, 9}, { 504, 18}, { 750, 25}, { 900, 30}}), // Version 23
new RSBlockInfo(1474, new int[][]{ {300, 10}, { 560, 20}, { 810, 27}, { 960, 32}}), // Version 24
new RSBlockInfo(1588, new int[][]{ {312, 12}, { 588, 21}, { 870, 29}, {1050, 35}}), // Version 25
new RSBlockInfo(1706, new int[][]{ {336, 12}, { 644, 23}, { 952, 34}, {1110, 37}}), // Version 26
new RSBlockInfo(1828, new int[][]{ {360, 12}, { 700, 25}, {1020, 34}, {1200, 40}}), // Version 27
new RSBlockInfo(1921, new int[][]{ {390, 13}, { 728, 26}, {1050, 35}, {1260, 42}}), // Version 28
new RSBlockInfo(2051, new int[][]{ {420, 14}, { 784, 28}, {1140, 38}, {1350, 45}}), // Version 29
new RSBlockInfo(2185, new int[][]{ {450, 15}, { 812, 29}, {1200, 40}, {1440, 48}}), // Version 30
new RSBlockInfo(2323, new int[][]{ {480, 16}, { 868, 31}, {1290, 43}, {1530, 51}}), // Version 31
new RSBlockInfo(2465, new int[][]{ {510, 17}, { 924, 33}, {1350, 45}, {1620, 54}}), // Version 32
new RSBlockInfo(2611, new int[][]{ {540, 18}, { 980, 35}, {1440, 48}, {1710, 57}}), // Version 33
new RSBlockInfo(2761, new int[][]{ {570, 19}, {1036, 37}, {1530, 51}, {1800, 60}}), // Version 34
new RSBlockInfo(2876, new int[][]{ {570, 19}, {1064, 38}, {1590, 53}, {1890, 63}}), // Version 35
new RSBlockInfo(3034, new int[][]{ {600, 20}, {1120, 40}, {1680, 56}, {1980, 66}}), // Version 36
new RSBlockInfo(3196, new int[][]{ {630, 21}, {1204, 43}, {1770, 59}, {2100, 70}}), // Version 37
new RSBlockInfo(3362, new int[][]{ {660, 22}, {1260, 45}, {1860, 62}, {2220, 74}}), // Version 38
new RSBlockInfo(3532, new int[][]{ {720, 24}, {1316, 47}, {1950, 65}, {2310, 77}}), // Version 39
new RSBlockInfo(3706, new int[][]{ {750, 25}, {1372, 49}, {2040, 68}, {2430, 81}}), // Version 40
}; };
static final RSBlockInfo kRSBlockTable[] = { private static final int kMaxNumECBytes = 68; // See the table in Appendix A.
// The table is from table 12 of JISX0510:2004 (p. 30)
// The "block_info" parts are ordered by L, M, Q, H. private static final class ECPolyInfo {
// The table was doublechecked by komatsu.
{ 26, { { 7, 1}, { 10, 1}, { 13, 1}, { 17, 1}}}, // Version 1
{ 44, { { 10, 1}, { 16, 1}, { 22, 1}, { 28, 1}}}, // Version 2
{ 70, { { 15, 1}, { 26, 1}, { 36, 2}, { 44, 2}}}, // Version 3
{ 100, { { 20, 1}, { 36, 2}, { 52, 2}, { 64, 4}}}, // Version 4
{ 134, { { 26, 1}, { 48, 2}, { 72, 4}, { 88, 4}}}, // Version 5
{ 172, { { 36, 2}, { 64, 4}, { 96, 4}, { 112, 4}}}, // Version 6
{ 196, { { 40, 2}, { 72, 4}, { 108, 6}, { 130, 5}}}, // Version 7
{ 242, { { 48, 2}, { 88, 4}, { 132, 6}, { 156, 6}}}, // Version 8
{ 292, { { 60, 2}, { 110, 5}, { 160, 8}, { 192, 8}}}, // Version 9
{ 346, { { 72, 4}, { 130, 5}, { 192, 8}, { 224, 8}}}, // Version 10
{ 404, { { 80, 4}, { 150, 5}, { 224, 8}, { 264, 11}}}, // Version 11
{ 466, { { 96, 4}, { 176, 8}, { 260, 10}, { 308, 11}}}, // Version 12
{ 532, { {104, 4}, { 198, 9}, { 288, 12}, { 352, 16}}}, // Version 13
{ 581, { {120, 4}, { 216, 9}, { 320, 16}, { 384, 16}}}, // Version 14
{ 655, { {132, 6}, { 240, 10}, { 360, 12}, { 432, 18}}}, // Version 15
{ 733, { {144, 6}, { 280, 10}, { 408, 17}, { 480, 16}}}, // Version 16
{ 815, { {168, 6}, { 308, 11}, { 448, 16}, { 532, 19}}}, // Version 17
{ 901, { {180, 6}, { 338, 13}, { 504, 18}, { 588, 21}}}, // Version 18
{ 991, { {196, 7}, { 364, 14}, { 546, 21}, { 650, 25}}}, // Version 19
{1085, { {224, 8}, { 416, 16}, { 600, 20}, { 700, 25}}}, // Version 20
{1156, { {224, 8}, { 442, 17}, { 644, 23}, { 750, 25}}}, // Version 21
{1258, { {252, 9}, { 476, 17}, { 690, 23}, { 816, 34}}}, // Version 22
{1364, { {270, 9}, { 504, 18}, { 750, 25}, { 900, 30}}}, // Version 23
{1474, { {300, 10}, { 560, 20}, { 810, 27}, { 960, 32}}}, // Version 24
{1588, { {312, 12}, { 588, 21}, { 870, 29}, {1050, 35}}}, // Version 25
{1706, { {336, 12}, { 644, 23}, { 952, 34}, {1110, 37}}}, // Version 26
{1828, { {360, 12}, { 700, 25}, {1020, 34}, {1200, 40}}}, // Version 27
{1921, { {390, 13}, { 728, 26}, {1050, 35}, {1260, 42}}}, // Version 28
{2051, { {420, 14}, { 784, 28}, {1140, 38}, {1350, 45}}}, // Version 29
{2185, { {450, 15}, { 812, 29}, {1200, 40}, {1440, 48}}}, // Version 30
{2323, { {480, 16}, { 868, 31}, {1290, 43}, {1530, 51}}}, // Version 31
{2465, { {510, 17}, { 924, 33}, {1350, 45}, {1620, 54}}}, // Version 32
{2611, { {540, 18}, { 980, 35}, {1440, 48}, {1710, 57}}}, // Version 33
{2761, { {570, 19}, {1036, 37}, {1530, 51}, {1800, 60}}}, // Version 34
{2876, { {570, 19}, {1064, 38}, {1590, 53}, {1890, 63}}}, // Version 35
{3034, { {600, 20}, {1120, 40}, {1680, 56}, {1980, 66}}}, // Version 36
{3196, { {630, 21}, {1204, 43}, {1770, 59}, {2100, 70}}}, // Version 37
{3362, { {660, 22}, {1260, 45}, {1860, 62}, {2220, 74}}}, // Version 38
{3532, { {720, 24}, {1316, 47}, {1950, 65}, {2310, 77}}}, // Version 39
{3706, { {750, 25}, {1372, 49}, {2040, 68}, {2430, 81}}}, // Version 40
};
static final int kMaxNumECBytes = 68; // See the table in Appendix A.
class ECPolyInfo {
int ec_length; int ec_length;
int coeffs[kMaxNumECBytes + 1]; int coeffs[];
};
// The numbers were generated using the logic found in public ECPolyInfo(int ec_length, int[] coefficients) {
// http://www.d-project.com/qrcode/. We use generated numbers instead this.ec_length = ec_length;
// of the logic itself (don't want to copy it). The numbers are this.coeffs = coefficients;
// supposed to be identical to the ones in the table is from the table }
// in Appendix A of JISX0510:2004 (p. 30). However, there are some
// cases the spec seems to be wrong. }
static final ECPolyInfo kECPolynomials[] = {
{ 7, // The numbers were generated using the logic found in http://www.d-project.com/qrcode/. We use
{ 0, 87, 229, 146, 149, 238, 102, 21 }}, // generated numbers instead of the logic itself (don't want to copy it). The numbers are supposed
// The spec lacks the coefficient for x^5 (a^46 x^5). // to be identical to the ones in the table in Appendix A of JISX0510:2004 (p. 30). However, there
// Tested a QR code of Version 1-M (uses 10 error correction bytes) // are some cases the spec seems to be wrong.
// with a cell phone and it worked. private static final ECPolyInfo kECPolynomials[] = {
{ 10, new ECPolyInfo( 7,
{ 0, 251, 67, 46, 61, 118, 70, 64, 94, 32, 45 }}, new int[]{ 0, 87, 229, 146, 149, 238, 102, 21 }),
{ 13, // The spec lacks the coefficient for x^5 (a^46 x^5). Tested a QR code of Version 1-M (uses 10
{ 0, 74, 152, 176, 100, 86, 100, 106, 104, 130, 218, 206, // error correction bytes) with a cell phone and it worked.
140, 78 }}, new ECPolyInfo( 10,
{ 15, new int[]{ 0, 251, 67, 46, 61, 118, 70, 64, 94, 32, 45 }),
{ 0, 8, 183, 61, 91, 202, 37, 51, 58, 58, 237, 140, new ECPolyInfo( 13,
124, 5, 99, 105 }}, new int[]{ 0, 74, 152, 176, 100, 86, 100, 106, 104, 130, 218, 206,
{ 16, 140, 78 }),
{ 0, 120, 104, 107, 109, 102, 161, 76, 3, 91, 191, 147, new ECPolyInfo( 15,
169, 182, 194, 225, 120 }}, new int[]{ 0, 8, 183, 61, 91, 202, 37, 51, 58, 58, 237, 140,
{ 17, 124, 5, 99, 105 }),
{ 0, 43, 139, 206, 78, 43, 239, 123, 206, 214, 147, 24, new ECPolyInfo( 16,
99, 150, 39, 243, 163, 136 }}, new int[]{ 0, 120, 104, 107, 109, 102, 161, 76, 3, 91, 191, 147,
{ 18, 169, 182, 194, 225, 120 }),
{ 0, 215, 234, 158, 94, 184, 97, 118, 170, 79, 187, 152, new ECPolyInfo( 17,
148, 252, 179, 5, 98, 96, 153 }}, new int[]{ 0, 43, 139, 206, 78, 43, 239, 123, 206, 214, 147, 24,
{ 20, 99, 150, 39, 243, 163, 136 }),
{ 0, 17, 60, 79, 50, 61, 163, 26, 187, 202, 180, 221, new ECPolyInfo( 18,
225, 83, 239, 156, 164, 212, 212, 188, 190 }}, new int[]{ 0, 215, 234, 158, 94, 184, 97, 118, 170, 79, 187, 152,
{ 22, 148, 252, 179, 5, 98, 96, 153 }),
{ 0, 210, 171, 247, 242, 93, 230, 14, 109, 221, 53, 200, new ECPolyInfo( 20,
74, 8, 172, 98, 80, 219, 134, 160, 105, 165, 231 }}, new int[]{ 0, 17, 60, 79, 50, 61, 163, 26, 187, 202, 180, 221,
{ 24, 225, 83, 239, 156, 164, 212, 212, 188, 190 }),
{ 0, 229, 121, 135, 48, 211, 117, 251, 126, 159, 180, 169, new ECPolyInfo( 22,
152, 192, 226, 228, 218, 111, 0, 117, 232, 87, 96, 227, new int[]{ 0, 210, 171, 247, 242, 93, 230, 14, 109, 221, 53, 200,
21 }}, 74, 8, 172, 98, 80, 219, 134, 160, 105, 165, 231 }),
{ 26, new ECPolyInfo( 24,
{ 0, 173, 125, 158, 2, 103, 182, 118, 17, 145, 201, 111, new int[]{ 0, 229, 121, 135, 48, 211, 117, 251, 126, 159, 180, 169,
28, 165, 53, 161, 21, 245, 142, 13, 102, 48, 227, 153, 152, 192, 226, 228, 218, 111, 0, 117, 232, 87, 96, 227,
145, 218, 70 }}, 21 }),
{ 28, new ECPolyInfo( 26,
{ 0, 168, 223, 200, 104, 224, 234, 108, 180, 110, 190, 195, new int[]{ 0, 173, 125, 158, 2, 103, 182, 118, 17, 145, 201, 111,
147, 205, 27, 232, 201, 21, 43, 245, 87, 42, 195, 212, 28, 165, 53, 161, 21, 245, 142, 13, 102, 48, 227, 153,
119, 242, 37, 9, 123 }}, 145, 218, 70 }),
{ 30, new ECPolyInfo( 28,
{ 0, 41, 173, 145, 152, 216, 31, 179, 182, 50, 48, 110, new int[]{ 0, 168, 223, 200, 104, 224, 234, 108, 180, 110, 190, 195,
86, 239, 96, 222, 125, 42, 173, 226, 193, 224, 130, 156, 147, 205, 27, 232, 201, 21, 43, 245, 87, 42, 195, 212,
37, 251, 216, 238, 40, 192, 180 }}, 119, 242, 37, 9, 123 }),
// In the spec, the coefficient for x^10 is a^60 but we use the new ECPolyInfo( 30,
// generated number a^69 instead (probably it's typo in the spec). new int[]{ 0, 41, 173, 145, 152, 216, 31, 179, 182, 50, 48, 110,
// 86, 239, 96, 222, 125, 42, 173, 226, 193, 224, 130, 156,
// Anyway, there seems to be no way that error correction bytes 37, 251, 216, 238, 40, 192, 180 }),
// bigger than 30 can be used in RS blocks, according to the table // In the spec, the coefficient for x^10 is a^60 but we use the generated number a^69 instead
// 12. It's weird why the spec has numbers for error correction // (probably it's typo in the spec).
// bytes of 32 and bigger in this table here. //
{ 32, // Anyway, there seems to be no way that error correction bytes bigger than 30 can be used in RS
{ 0, 10, 6, 106, 190, 249, 167, 4, 67, 209, 138, 138, // blocks, according to table 12. It's weird why the spec has numbers for error correction bytes
32, 242, 123, 89, 27, 120, 185, 80, 156, 38, 69, 171, // of 32 and bigger in this table here.
60, 28, 222, 80, 52, 254, 185, 220, 241 }}, new ECPolyInfo( 32,
{ 34, new int[]{ 0, 10, 6, 106, 190, 249, 167, 4, 67, 209, 138, 138,
{ 0, 111, 77, 146, 94, 26, 21, 108, 19, 105, 94, 113, 32, 242, 123, 89, 27, 120, 185, 80, 156, 38, 69, 171,
193, 86, 140, 163, 125, 58, 158, 229, 239, 218, 103, 56, 60, 28, 222, 80, 52, 254, 185, 220, 241 }),
70, 114, 61, 183, 129, 167, 13, 98, 62, 129, 51 }}, new ECPolyInfo( 34,
{ 36, new int[]{ 0, 111, 77, 146, 94, 26, 21, 108, 19, 105, 94, 113,
{ 0, 200, 183, 98, 16, 172, 31, 246, 234, 60, 152, 115, 193, 86, 140, 163, 125, 58, 158, 229, 239, 218, 103, 56,
0, 167, 152, 113, 248, 238, 107, 18, 63, 218, 37, 87, 70, 114, 61, 183, 129, 167, 13, 98, 62, 129, 51 }),
210, 105, 177, 120, 74, 121, 196, 117, 251, 113, 233, 30, new ECPolyInfo( 36,
120 }}, new int[]{ 0, 200, 183, 98, 16, 172, 31, 246, 234, 60, 152, 115,
// The spec doesn't have a row for 38 but just in case. 0, 167, 152, 113, 248, 238, 107, 18, 63, 218, 37, 87,
{ 38, 210, 105, 177, 120, 74, 121, 196, 117, 251, 113, 233, 30,
{ 0, 159, 34, 38, 228, 230, 59, 243, 95, 49, 218, 176, 120 }),
164, 20, 65, 45, 111, 39, 81, 49, 118, 113, 222, 193, // The spec doesn't have a row for 38 but just in case.
250, 242, 168, 217, 41, 164, 247, 177, 30, 238, 18, 120, new ECPolyInfo( 38,
153, 60, 193 }}, new int[]{ 0, 159, 34, 38, 228, 230, 59, 243, 95, 49, 218, 176,
{ 40, 164, 20, 65, 45, 111, 39, 81, 49, 118, 113, 222, 193,
{ 0, 59, 116, 79, 161, 252, 98, 128, 205, 128, 161, 247, 250, 242, 168, 217, 41, 164, 247, 177, 30, 238, 18, 120,
57, 163, 56, 235, 106, 53, 26, 187, 174, 226, 104, 170, 153, 60, 193 }),
7, 175, 35, 181, 114, 88, 41, 47, 163, 125, 134, 72, new ECPolyInfo( 40,
20, 232, 53, 35, 15 }}, new int[]{ 0, 59, 116, 79, 161, 252, 98, 128, 205, 128, 161, 247,
{ 42, 57, 163, 56, 235, 106, 53, 26, 187, 174, 226, 104, 170,
{ 0, 250, 103, 221, 230, 25, 18, 137, 231, 0, 3, 58, 7, 175, 35, 181, 114, 88, 41, 47, 163, 125, 134, 72,
242, 221, 191, 110, 84, 230, 8, 188, 106, 96, 147, 15, 20, 232, 53, 35, 15 }),
131, 139, 34, 101, 223, 39, 101, 213, 199, 237, 254, 201, new ECPolyInfo( 42,
123, 171, 162, 194, 117, 50, 96 }}, new int[]{ 0, 250, 103, 221, 230, 25, 18, 137, 231, 0, 3, 58,
{ 44, 242, 221, 191, 110, 84, 230, 8, 188, 106, 96, 147, 15,
{ 0, 190, 7, 61, 121, 71, 246, 69, 55, 168, 188, 89, 131, 139, 34, 101, 223, 39, 101, 213, 199, 237, 254, 201,
243, 191, 25, 72, 123, 9, 145, 14, 247, 1, 238, 44, 123, 171, 162, 194, 117, 50, 96 }),
78, 143, 62, 224, 126, 118, 114, 68, 163, 52, 194, 217, new ECPolyInfo( 44,
147, 204, 169, 37, 130, 113, 102, 73, 181 }}, new int[]{ 0, 190, 7, 61, 121, 71, 246, 69, 55, 168, 188, 89,
{ 46, 243, 191, 25, 72, 123, 9, 145, 14, 247, 1, 238, 44,
{ 0, 112, 94, 88, 112, 253, 224, 202, 115, 187, 99, 89, 78, 143, 62, 224, 126, 118, 114, 68, 163, 52, 194, 217,
5, 54, 113, 129, 44, 58, 16, 135, 216, 169, 211, 36, 147, 204, 169, 37, 130, 113, 102, 73, 181 }),
1, 4, 96, 60, 241, 73, 104, 234, 8, 249, 245, 119, new ECPolyInfo( 46,
174, 52, 25, 157, 224, 43, 202, 223, 19, 82, 15 }}, new int[]{ 0, 112, 94, 88, 112, 253, 224, 202, 115, 187, 99, 89,
{ 48, 5, 54, 113, 129, 44, 58, 16, 135, 216, 169, 211, 36,
{ 0, 228, 25, 196, 130, 211, 146, 60, 24, 251, 90, 39, 1, 4, 96, 60, 241, 73, 104, 234, 8, 249, 245, 119,
102, 240, 61, 178, 63, 46, 123, 115, 18, 221, 111, 135, 174, 52, 25, 157, 224, 43, 202, 223, 19, 82, 15 }),
160, 182, 205, 107, 206, 95, 150, 120, 184, 91, 21, 247, new ECPolyInfo( 48,
156, 140, 238, 191, 11, 94, 227, 84, 50, 163, 39, 34, new int[]{ 0, 228, 25, 196, 130, 211, 146, 60, 24, 251, 90, 39,
108 }}, 102, 240, 61, 178, 63, 46, 123, 115, 18, 221, 111, 135,
{ 50, 160, 182, 205, 107, 206, 95, 150, 120, 184, 91, 21, 247,
{ 0, 232, 125, 157, 161, 164, 9, 118, 46, 209, 99, 203, 156, 140, 238, 191, 11, 94, 227, 84, 50, 163, 39, 34,
193, 35, 3, 209, 111, 195, 242, 203, 225, 46, 13, 32, 108 }),
160, 126, 209, 130, 160, 242, 215, 242, 75, 77, 42, 189, new ECPolyInfo( 50,
32, 113, 65, 124, 69, 228, 114, 235, 175, 124, 170, 215, new int[]{ 0, 232, 125, 157, 161, 164, 9, 118, 46, 209, 99, 203,
232, 133, 205 }}, 193, 35, 3, 209, 111, 195, 242, 203, 225, 46, 13, 32,
{ 52, 160, 126, 209, 130, 160, 242, 215, 242, 75, 77, 42, 189,
{ 0, 116, 50, 86, 186, 50, 220, 251, 89, 192, 46, 86, 32, 113, 65, 124, 69, 228, 114, 235, 175, 124, 170, 215,
127, 124, 19, 184, 233, 151, 215, 22, 14, 59, 145, 37, 232, 133, 205 }),
242, 203, 134, 254, 89, 190, 94, 59, 65, 124, 113, 100, new ECPolyInfo( 52,
233, 235, 121, 22, 76, 86, 97, 39, 242, 200, 220, 101, new int[]{ 0, 116, 50, 86, 186, 50, 220, 251, 89, 192, 46, 86,
33, 239, 254, 116, 51 }}, 127, 124, 19, 184, 233, 151, 215, 22, 14, 59, 145, 37,
{ 54, 242, 203, 134, 254, 89, 190, 94, 59, 65, 124, 113, 100,
{ 0, 183, 26, 201, 87, 210, 221, 113, 21, 46, 65, 45, 233, 235, 121, 22, 76, 86, 97, 39, 242, 200, 220, 101,
50, 238, 184, 249, 225, 102, 58, 209, 218, 109, 165, 26, 33, 239, 254, 116, 51 }),
95, 184, 192, 52, 245, 35, 254, 238, 175, 172, 79, 123, new ECPolyInfo( 54,
25, 122, 43, 120, 108, 215, 80, 128, 201, 235, 8, 153, new int[]{ 0, 183, 26, 201, 87, 210, 221, 113, 21, 46, 65, 45,
59, 101, 31, 198, 76, 31, 156 }}, 50, 238, 184, 249, 225, 102, 58, 209, 218, 109, 165, 26,
{ 56, 95, 184, 192, 52, 245, 35, 254, 238, 175, 172, 79, 123,
{ 0, 106, 120, 107, 157, 164, 216, 112, 116, 2, 91, 248, 25, 122, 43, 120, 108, 215, 80, 128, 201, 235, 8, 153,
163, 36, 201, 202, 229, 6, 144, 254, 155, 135, 208, 170, 59, 101, 31, 198, 76, 31, 156 }),
209, 12, 139, 127, 142, 182, 249, 177, 174, 190, 28, 10, new ECPolyInfo( 56,
85, 239, 184, 101, 124, 152, 206, 96, 23, 163, 61, 27, new int[]{ 0, 106, 120, 107, 157, 164, 216, 112, 116, 2, 91, 248,
196, 247, 151, 154, 202, 207, 20, 61, 10 }}, 163, 36, 201, 202, 229, 6, 144, 254, 155, 135, 208, 170,
{ 58, 209, 12, 139, 127, 142, 182, 249, 177, 174, 190, 28, 10,
{ 0, 82, 116, 26, 247, 66, 27, 62, 107, 252, 182, 200, 85, 239, 184, 101, 124, 152, 206, 96, 23, 163, 61, 27,
185, 235, 55, 251, 242, 210, 144, 154, 237, 176, 141, 192, 196, 247, 151, 154, 202, 207, 20, 61, 10 }),
248, 152, 249, 206, 85, 253, 142, 65, 165, 125, 23, 24, new ECPolyInfo( 58,
30, 122, 240, 214, 6, 129, 218, 29, 145, 127, 134, 206, new int[]{ 0, 82, 116, 26, 247, 66, 27, 62, 107, 252, 182, 200,
245, 117, 29, 41, 63, 159, 142, 233, 125, 148, 123 }}, 185, 235, 55, 251, 242, 210, 144, 154, 237, 176, 141, 192,
{ 60, 248, 152, 249, 206, 85, 253, 142, 65, 165, 125, 23, 24,
{ 0, 107, 140, 26, 12, 9, 141, 243, 197, 226, 197, 219, 30, 122, 240, 214, 6, 129, 218, 29, 145, 127, 134, 206,
45, 211, 101, 219, 120, 28, 181, 127, 6, 100, 247, 2, 245, 117, 29, 41, 63, 159, 142, 233, 125, 148, 123 }),
205, 198, 57, 115, 219, 101, 109, 160, 82, 37, 38, 238, new ECPolyInfo( 60,
49, 160, 209, 121, 86, 11, 124, 30, 181, 84, 25, 194, new int[]{ 0, 107, 140, 26, 12, 9, 141, 243, 197, 226, 197, 219,
87, 65, 102, 190, 220, 70, 27, 209, 16, 89, 7, 33, 45, 211, 101, 219, 120, 28, 181, 127, 6, 100, 247, 2,
240 }}, 205, 198, 57, 115, 219, 101, 109, 160, 82, 37, 38, 238,
// The spec lacks the coefficient for x^5 (a^127 x^5). 49, 160, 209, 121, 86, 11, 124, 30, 181, 84, 25, 194,
// Anyway the number will not be used. See the comment for 32. 87, 65, 102, 190, 220, 70, 27, 209, 16, 89, 7, 33,
{ 62, 240 }),
{ 0, 65, 202, 113, 98, 71, 223, 248, 118, 214, 94, 0, // The spec lacks the coefficient for x^5 (a^127 x^5). Anyway the number will not be used. See
122, 37, 23, 2, 228, 58, 121, 7, 105, 135, 78, 243, // the comment for 32.
118, 70, 76, 223, 89, 72, 50, 70, 111, 194, 17, 212, new ECPolyInfo( 62,
126, 181, 35, 221, 117, 235, 11, 229, 149, 147, 123, 213, new int[]{ 0, 65, 202, 113, 98, 71, 223, 248, 118, 214, 94, 0,
40, 115, 6, 200, 100, 26, 246, 182, 218, 127, 215, 36, 122, 37, 23, 2, 228, 58, 121, 7, 105, 135, 78, 243,
186, 110, 106 }}, 118, 70, 76, 223, 89, 72, 50, 70, 111, 194, 17, 212,
{ 64, 126, 181, 35, 221, 117, 235, 11, 229, 149, 147, 123, 213,
{ 0, 45, 51, 175, 9, 7, 158, 159, 49, 68, 119, 92, 40, 115, 6, 200, 100, 26, 246, 182, 218, 127, 215, 36,
123, 177, 204, 187, 254, 200, 78, 141, 149, 119, 26, 127, 186, 110, 106 }),
53, 160, 93, 199, 212, 29, 24, 145, 156, 208, 150, 218, new ECPolyInfo( 64,
209, 4, 216, 91, 47, 184, 146, 47, 140, 195, 195, 125, new int[]{ 0, 45, 51, 175, 9, 7, 158, 159, 49, 68, 119, 92,
242, 238, 63, 99, 108, 140, 230, 242, 31, 204, 11, 178, 123, 177, 204, 187, 254, 200, 78, 141, 149, 119, 26, 127,
243, 217, 156, 213, 231 }}, 53, 160, 93, 199, 212, 29, 24, 145, 156, 208, 150, 218,
{ 66, 209, 4, 216, 91, 47, 184, 146, 47, 140, 195, 195, 125,
{ 0, 5, 118, 222, 180, 136, 136, 162, 51, 46, 117, 13, 242, 238, 63, 99, 108, 140, 230, 242, 31, 204, 11, 178,
215, 81, 17, 139, 247, 197, 171, 95, 173, 65, 137, 178, 243, 217, 156, 213, 231 }),
68, 111, 95, 101, 41, 72, 214, 169, 197, 95, 7, 44, new ECPolyInfo( 66,
154, 77, 111, 236, 40, 121, 143, 63, 87, 80, 253, 240, new int[]{ 0, 5, 118, 222, 180, 136, 136, 162, 51, 46, 117, 13,
126, 217, 77, 34, 232, 106, 50, 168, 82, 76, 146, 67, 215, 81, 17, 139, 247, 197, 171, 95, 173, 65, 137, 178,
106, 171, 25, 132, 93, 45, 105 }}, 68, 111, 95, 101, 41, 72, 214, 169, 197, 95, 7, 44,
{ 68, 154, 77, 111, 236, 40, 121, 143, 63, 87, 80, 253, 240,
{ 0, 247, 159, 223, 33, 224, 93, 77, 70, 90, 160, 32, 126, 217, 77, 34, 232, 106, 50, 168, 82, 76, 146, 67,
254, 43, 150, 84, 101, 190, 205, 133, 52, 60, 202, 165, 106, 171, 25, 132, 93, 45, 105 }),
220, 203, 151, 93, 84, 15, 84, 253, 173, 160, 89, 227, new ECPolyInfo( 68,
52, 199, 97, 95, 231, 52, 177, 41, 125, 137, 241, 166, new int[]{ 0, 247, 159, 223, 33, 224, 93, 77, 70, 90, 160, 32,
225, 118, 2, 54, 32, 82, 215, 175, 198, 43, 238, 235, 254, 43, 150, 84, 101, 190, 205, 133, 52, 60, 202, 165,
27, 101, 184, 127, 3, 5, 8, 163, 238 }}, 220, 203, 151, 93, 84, 15, 84, 253, 173, 160, 89, 227,
}; 52, 199, 97, 95, 231, 52, 177, 41, 125, 137, 241, 166,
225, 118, 2, 54, 32, 82, 215, 175, 198, 43, 238, 235,
27, 101, 184, 127, 3, 5, 8, 163, 238 }),
};
private static final int kFieldSize = 8; private static final int kFieldSize = 8;
private static GF_Poly *g_ec_polynomials[kMaxNumECBytes + 1]; private static GF_Poly[] g_ec_polynomials = new GF_Poly[kMaxNumECBytes + 1];
public:
// Encode "bytes" with the error correction level "ec_level". The // Encode "bytes" with the error correction level "ec_level". The
// encoding mode will be chosen internally by ChooseMode(). // encoding mode will be chosen internally by ChooseMode().
// On success, store the result in "qr_code" and return true. On // On success, store the result in "qr_code" and return true. On
@ -285,15 +291,15 @@ public final class Encoder {
// Note that there is no way to encode bytes in MODE_KANJI. We might // Note that there is no way to encode bytes in MODE_KANJI. We might
// want to add EncodeWithMode() with which clients can specify the // want to add EncodeWithMode() with which clients can specify the
// encoding mode. For now, we don't need the functionality. // encoding mode. For now, we don't need the functionality.
static boolean Encode(final StringPiece& bytes, int ec_level, QRCode *qr_code) { public static boolean Encode(final StringPiece bytes, int ec_level, QRCode qr_code) {
// Step 1: Choose the mode (encoding). // 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. // Step 2: Append "bytes" into "data_bits" in appropriate encoding.
BitVector data_bits; BitVector data_bits = new BitVector();
if (!AppendBytes(bytes, mode, &data_bits)) { if (!AppendBytes(bytes, mode, data_bits)) {
return false; return false;
} }
// Step 3: Initialize QR code that can contain "data_bits". // Step 3: Initialize QR code that can contain "data_bits".
final int num_input_bytes = data_bits.num_bytes(); final int num_input_bytes = data_bits.num_bytes();
if (!InitQRCode(num_input_bytes, ec_level, mode, qr_code)) { if (!InitQRCode(num_input_bytes, ec_level, mode, qr_code)) {
@ -301,28 +307,28 @@ public final class Encoder {
} }
// Step 4: Build another bit vector that contains header and data. // Step 4: Build another bit vector that contains header and data.
BitVector header_and_data_bits; BitVector header_and_data_bits = new BitVector();
if (!AppendModeInfo(qr_code.mode(), &header_and_data_bits)) { if (!AppendModeInfo(qr_code.mode(), header_and_data_bits)) {
return false; return false;
} }
if (!AppendLengthInfo(bytes.size(), qr_code.version(), qr_code.mode(), if (!AppendLengthInfo(bytes.size(), qr_code.version(), qr_code.mode(),
&header_and_data_bits)) { header_and_data_bits)) {
return false; return false;
} }
header_and_data_bits.AppendBitVector(data_bits); header_and_data_bits.AppendBitVector(data_bits);
// Step 5: Terminate the bits properly. // Step 5: Terminate the bits properly.
if (!TerminateBits(qr_code.num_data_bytes(), &header_and_data_bits)) { if (!TerminateBits(qr_code.num_data_bytes(), header_and_data_bits)) {
return false; return false;
} }
// Step 6: Interleave data bits with error correction code. // Step 6: Interleave data bits with error correction code.
BitVector final_bits; BitVector final_bits = new BitVector();
InterleaveWithECBytes(header_and_data_bits, InterleaveWithECBytes(header_and_data_bits,
qr_code.num_total_bytes(), qr_code.num_total_bytes(),
qr_code.num_data_bytes(), qr_code.num_data_bytes(),
qr_code.num_rs_blocks(), qr_code.num_rs_blocks(),
&final_bits); final_bits);
// Step 7: Choose the mask pattern and set to "qr_code". // Step 7: Choose the mask pattern and set to "qr_code".
Matrix matrix = new Matrix(qr_code.matrix_width(), qr_code.matrix_width()); Matrix matrix = new Matrix(qr_code.matrix_width(), qr_code.matrix_width());
@ -332,15 +338,14 @@ public final class Encoder {
matrix)); matrix));
if (qr_code.mask_pattern() == -1) { if (qr_code.mask_pattern() == -1) {
// There was an error. // There was an error.
delete matrix;
return false; return false;
} }
// Step 8. Build the matrix and set it to "qr_code". // Step 8. Build the matrix and set it to "qr_code".
MatrixUtil.BuildMatrix(final_bits, MatrixUtil.BuildMatrix(final_bits,
qr_code.ec_level(), qr_code.ec_level(),
qr_code.version(), qr_code.version(),
qr_code.mask_pattern(), matrix); qr_code.mask_pattern(), matrix);
qr_code.set_matrix(matrix); qr_code.set_matrix(matrix);
// Step 9. Make sure we have a valid QR Code. // Step 9. Make sure we have a valid QR Code.
if (!qr_code.IsValid()) { if (!qr_code.IsValid()) {
@ -350,14 +355,10 @@ public final class Encoder {
return true; return true;
} }
// The functions below are public but not intended to be used // Return the code point of the table used in alphanumeric mode. Return -1 if there is no
// outside the library. We make them public for ease of unit // corresponding code in the table.
// testing with gUnit. private static int GetAlphanumericCode(int code) {
if (code < kAlphanumericTable.length) {
// 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 < arraysize(kAlphanumericTable)) {
return kAlphanumericTable[code]; return kAlphanumericTable[code];
} }
return -1; return -1;
@ -370,7 +371,7 @@ public final class Encoder {
// distinguish Shift_JIS from other encodings such as ISO-8859-1, from // distinguish Shift_JIS from other encodings such as ISO-8859-1, from
// data bytes alone. For example "\xE0\xE0" can be interpreted as one // data bytes alone. For example "\xE0\xE0" can be interpreted as one
// character in Shift_JIS, but also two characters in ISO-8859-1. // character in Shift_JIS, but also two characters in ISO-8859-1.
static int ChooseMode(final StringPiece &bytes) { public static int ChooseMode(final StringPiece bytes) {
boolean has_numeric = false; boolean has_numeric = false;
boolean has_alphanumeric = false; boolean has_alphanumeric = false;
boolean has_other = false; boolean has_other = false;
@ -396,7 +397,7 @@ public final class Encoder {
return QRCode.MODE_8BIT_BYTE; 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 ec_level, int version,
Matrix matrix) { Matrix matrix) {
if (!QRCode.IsValidMatrixWidth(matrix.width())) { if (!QRCode.IsValidMatrixWidth(matrix.width())) {
Debug.LOG_ERROR("Invalid matrix width: " + matrix.width()); Debug.LOG_ERROR("Invalid matrix width: " + matrix.width());
@ -406,7 +407,7 @@ public final class Encoder {
int min_penalty = Integer.MAX_VALUE; // Lower penalty is better. int min_penalty = Integer.MAX_VALUE; // Lower penalty is better.
int best_mask_pattern = -1; int best_mask_pattern = -1;
// We try all mask patterns to choose the best one. // We try all mask patterns to choose the best one.
for (int i = 0; i < kNumMaskPatterns; ++i) { for (int i = 0; i < QRCode.kNumMaskPatterns; ++i) {
final int mask_pattern = i; final int mask_pattern = i;
if (!MatrixUtil.BuildMatrix(bits, ec_level, version, if (!MatrixUtil.BuildMatrix(bits, ec_level, version,
mask_pattern, matrix)) { mask_pattern, matrix)) {
@ -422,10 +423,9 @@ public final class Encoder {
return best_mask_pattern; return best_mask_pattern;
} }
// Initialize "qr_code" according to "num_input_bytes", "ec_level", // Initialize "qr_code" according to "num_input_bytes", "ec_level", and "mode". On success, modify
// and "mode". On success, modify "qr_code" and return true. On // "qr_code" and return true. On error, return false.
// error, return false. private static boolean InitQRCode(int num_input_bytes, int ec_level, int mode, QRCode qr_code) {
static boolean InitQRCode(int num_input_bytes, int ec_level, int mode, QRCode *qr_code) {
qr_code.set_ec_level(ec_level); qr_code.set_ec_level(ec_level);
qr_code.set_mode(mode); qr_code.set_mode(mode);
@ -435,14 +435,14 @@ public final class Encoder {
} }
// In the following comments, we use numbers of Version 7-H. // In the following comments, we use numbers of Version 7-H.
for (int i = 0; i < arraysize(kRSBlockTable); ++i) { for (int i = 0; i < kRSBlockTable.length; ++i) {
final RSBlockInfo &row = kRSBlockTable[i]; final RSBlockInfo row = kRSBlockTable[i];
// num_bytes = 196 // num_bytes = 196
final int num_bytes = row.num_bytes; final int num_bytes = row.num_bytes;
// num_ec_bytes = 130 // num_ec_bytes = 130
final int num_ec_bytes = row.block_info[ec_level].num_ec_bytes; final int num_ec_bytes = row.block_info[ec_level][0];
// num_rs_blocks = 5 // num_rs_blocks = 5
final int num_rs_blocks = row.block_info[ec_level].num_rs_blocks; final int num_rs_blocks = row.block_info[ec_level][1];
// num_data_bytes = 196 - 130 = 66 // num_data_bytes = 196 - 130 = 66
final int num_data_bytes = num_bytes - num_ec_bytes; final int num_data_bytes = num_bytes - num_ec_bytes;
// We want to choose the smallest version which can contain data // We want to choose the smallest version which can contain data
@ -466,16 +466,14 @@ public final class Encoder {
return false; return false;
} }
// Terminate bits as described in 8.4.8 and 8.4.9 of JISX0510:2004 // Terminate bits as described in 8.4.8 and 8.4.9 of JISX0510:2004 (p.24).
// (p.24). static boolean TerminateBits(int num_data_bytes, BitVector bits) {
static boolean TerminateBits(int num_data_bytes, BitVector *bits) {
final int capacity = num_data_bytes * 8; final int capacity = num_data_bytes * 8;
if (bits.size() > capacity) { if (bits.size() > capacity) {
Debug.LOG_ERROR("data bits cannot fit in the QR Code" + bits.size() + " > " + capacity); Debug.LOG_ERROR("data bits cannot fit in the QR Code" + bits.size() + " > " + capacity);
return false; return false;
} }
// Append termination bits. // Append termination bits. See 8.4.8 of JISX0510:2004 (p.24) for details.
// See 8.4.8 of JISX0510:2004 (p.24) for details.
for (int i = 0; i < 4 && bits.size() < capacity; ++i) { for (int i = 0; i < 4 && bits.size() < capacity; ++i) {
bits.AppendBit(0); bits.AppendBit(0);
} }
@ -489,8 +487,7 @@ public final class Encoder {
} }
// Should be 8-bit aligned here. // Should be 8-bit aligned here.
Debug.DCHECK_EQ(0, bits.size() % 8); Debug.DCHECK_EQ(0, bits.size() % 8);
// If we have more space, we'll fill the space with padding patterns // If we have more space, we'll fill the space with padding patterns defined in 8.4.9 (p.24).
// defined in 8.4.9 (p.24).
final int num_padding_bytes = num_data_bytes - bits.num_bytes(); final int num_padding_bytes = num_data_bytes - bits.num_bytes();
for (int i = 0; i < num_padding_bytes; ++i) { for (int i = 0; i < num_padding_bytes; ++i) {
if (i % 2 == 0) { if (i % 2 == 0) {
@ -503,17 +500,12 @@ public final class Encoder {
return bits.size() == capacity; return bits.size() == capacity;
} }
// Get number of data bytes and number of error correction bytes for // Get number of data bytes and number of error correction bytes for block id "block_id". Store
// block id "block_id". Store the result in // the result in "num_data_bytes_in_block", and "num_ec_bytes_in_block". See table 12 in 8.5.1 of
// "num_data_bytes_in_block", and "num_ec_bytes_in_block". // JISX0510:2004 (p.30)
// See table 12 in 8.5.1 of JISX0510:2004 (p.30) static void GetNumDataBytesAndNumECBytesForBlockID(int num_total_bytes, int num_data_bytes,
static void GetNumDataBytesAndNumECBytesForBlockID( int num_rs_blocks, int block_id, Integer num_data_bytes_in_block,
int num_total_bytes, Integer num_ec_bytes_in_block) {
int num_data_bytes,
int num_rs_blocks,
int block_id,
int *num_data_bytes_in_block,
int *num_ec_bytes_in_block) {
Debug.DCHECK_LT(block_id, num_rs_blocks); Debug.DCHECK_LT(block_id, num_rs_blocks);
// num_rs_blocks_in_group2 = 196 % 5 = 1 // num_rs_blocks_in_group2 = 196 % 5 = 1
final int num_rs_blocks_in_group2 = num_total_bytes % num_rs_blocks; final int num_rs_blocks_in_group2 = num_total_bytes % num_rs_blocks;
@ -546,11 +538,11 @@ public final class Encoder {
num_rs_blocks_in_group2)); num_rs_blocks_in_group2));
if (block_id < num_rs_blocks_in_group1) { if (block_id < num_rs_blocks_in_group1) {
*num_data_bytes_in_block = num_data_bytes_in_group1; num_data_bytes_in_block = num_data_bytes_in_group1;
*num_ec_bytes_in_block = num_ec_bytes_in_group1; num_ec_bytes_in_block = num_ec_bytes_in_group1;
} else { } else {
*num_data_bytes_in_block = num_data_bytes_in_group2; num_data_bytes_in_block = num_data_bytes_in_group2;
*num_ec_bytes_in_block = num_ec_bytes_in_group2; num_ec_bytes_in_block = num_ec_bytes_in_group2;
} }
} }
@ -559,11 +551,11 @@ public final class Encoder {
// return false. // return false.
// The interleave rule is complicated. See 8.6 of JISX0510:2004 // The interleave rule is complicated. See 8.6 of JISX0510:2004
// (p.37) for details. // (p.37) for details.
static boolean InterleaveWithECBytes(final BitVector &bits, static boolean InterleaveWithECBytes(final BitVector bits,
int num_total_bytes, int num_total_bytes,
int num_data_bytes, int num_data_bytes,
int num_rc_blocks, int num_rc_blocks,
BitVector *result) { BitVector result) {
// "bits" must have "num_data_bytes" bytes of data. // "bits" must have "num_data_bytes" bytes of data.
Debug.DCHECK(bits.num_bytes() == num_data_bytes); Debug.DCHECK(bits.num_bytes() == num_data_bytes);
@ -572,6 +564,7 @@ public final class Encoder {
// blocks and error correction bytes blocks into "blocks". // blocks and error correction bytes blocks into "blocks".
typedef pair<StringPiece, String> BlockPair; typedef pair<StringPiece, String> BlockPair;
int data_bytes_offset = 0; int data_bytes_offset = 0;
// JAVAPORT: This is not a String, it's really a byte[]
final String &encoded_bytes = bits.ToString(); final String &encoded_bytes = bits.ToString();
int max_num_data_bytes = 0; // StringPiece's size is "int". int max_num_data_bytes = 0; // StringPiece's size is "int".
size_t max_num_ec_bytes = 0; // STL String's size is "size_t". size_t max_num_ec_bytes = 0; // STL String's size is "size_t".
@ -629,7 +622,7 @@ public final class Encoder {
// Append mode info. On success, store the result in "bits" and // Append mode info. On success, store the result in "bits" and
// return true. On error, return false. // return true. On error, return false.
static boolean AppendModeInfo(int mode, BitVector *bits) { static boolean AppendModeInfo(int mode, BitVector bits) {
final int code = QRCode.GetModeCode(mode); final int code = QRCode.GetModeCode(mode);
if (code == -1) { if (code == -1) {
Debug.LOG_ERROR("Invalid mode: " + mode); Debug.LOG_ERROR("Invalid mode: " + mode);
@ -642,7 +635,7 @@ public final class Encoder {
// Append length info. On success, store the result in "bits" and // Append length info. On success, store the result in "bits" and
// return true. On error, return false. // return true. On error, return false.
static boolean AppendLengthInfo(int num_bytes, int version, int mode, BitVector *bits) { static boolean AppendLengthInfo(int num_bytes, int version, int mode, BitVector bits) {
int num_letters = num_bytes; int num_letters = num_bytes;
// In Kanji mode, a letter is represented in two bytes. // In Kanji mode, a letter is represented in two bytes.
if (mode == QRCode.MODE_KANJI) { if (mode == QRCode.MODE_KANJI) {
@ -665,7 +658,7 @@ public final class Encoder {
// Append "bytes" in "mode" mode (encoding) into "bits". On success, store the result in "bits" // Append "bytes" in "mode" mode (encoding) into "bits". On success, store the result in "bits"
// and return true. On error, return false. // and return true. On error, return false.
static boolean AppendBytes(final StringPiece &bytes, int mode, BitVector *bits) { static boolean AppendBytes(final StringPiece bytes, int mode, BitVector bits) {
switch (mode) { switch (mode) {
case QRCode.MODE_NUMERIC: case QRCode.MODE_NUMERIC:
return AppendNumericBytes(bytes, bits); return AppendNumericBytes(bytes, bits);
@ -684,7 +677,7 @@ public final class Encoder {
// Append "bytes" to "bits" using QRCode.MODE_NUMERIC mode. On success, store the result in "bits" // Append "bytes" to "bits" using QRCode.MODE_NUMERIC mode. On success, store the result in "bits"
// and return true. On error, return false. // and return true. On error, return false.
static boolean AppendNumericBytes(final StringPiece &bytes, BitVector *bits) { static boolean AppendNumericBytes(final StringPiece bytes, BitVector bits) {
// Validate all the bytes first. // Validate all the bytes first.
for (int i = 0; i < bytes.size(); ++i) { for (int i = 0; i < bytes.size(); ++i) {
if (!isdigit(bytes[i])) { if (!isdigit(bytes[i])) {
@ -716,8 +709,7 @@ public final class Encoder {
// Append "bytes" to "bits" using QRCode.MODE_ALPHANUMERIC mode. // Append "bytes" to "bits" using QRCode.MODE_ALPHANUMERIC mode.
// On success, store the result in "bits" and return true. On error, // On success, store the result in "bits" and return true. On error,
// return false. // return false.
static boolean AppendAlphanumericBytes(final StringPiece &bytes, static boolean AppendAlphanumericBytes(final StringPiece bytes, BitVector bits) {
BitVector *bits) {
for (int i = 0; i < bytes.size();) { for (int i = 0; i < bytes.size();) {
final int code1 = GetAlphanumericCode(bytes[i]); final int code1 = GetAlphanumericCode(bytes[i]);
if (code1 == -1) { if (code1 == -1) {
@ -743,7 +735,7 @@ public final class Encoder {
// Append "bytes" to "bits" using QRCode.MODE_8BIT_BYTE mode. // Append "bytes" to "bits" using QRCode.MODE_8BIT_BYTE mode.
// On success, store the result in "bits" and return true. On error, // On success, store the result in "bits" and return true. On error,
// return false. // return false.
static boolean Append8BitBytes(final StringPiece &bytes, BitVector *bits) { static boolean Append8BitBytes(final StringPiece bytes, BitVector bits) {
for (int i = 0; i < bytes.size(); ++i) { for (int i = 0; i < bytes.size(); ++i) {
bits.AppendBits(bytes[i], 8); bits.AppendBits(bytes[i], 8);
} }
@ -754,7 +746,7 @@ public final class Encoder {
// On success, store the result in "bits" and return true. On error, // On success, store the result in "bits" and return true. On error,
// return false. // return false.
// See 8.4.5 of JISX0510:2004 (p.21) for how to encode Kanji bytes. // See 8.4.5 of JISX0510:2004 (p.21) for how to encode Kanji bytes.
static boolean AppendKanjiBytes(final StringPiece &bytes, BitVector *bits) { static boolean AppendKanjiBytes(final StringPiece bytes, BitVector bits) {
if (bytes.size() % 2 != 0) { if (bytes.size() % 2 != 0) {
Debug.LOG_ERROR("Invalid byte sequence: " + bytes); Debug.LOG_ERROR("Invalid byte sequence: " + bytes);
return false; return false;
@ -818,11 +810,11 @@ public final class Encoder {
// {119,66,83,120,119,22,197,83,249,41,143,134,85,53,125,99,79} // {119,66,83,120,119,22,197,83,249,41,143,134,85,53,125,99,79}
// - Log()'ed output (in reverse order) // - Log()'ed output (in reverse order)
// {0,43,139,206,78,43,239,123,206,214,147,24,99,150,39,243,163,136} // {0,43,139,206,78,43,239,123,206,214,147,24,99,150,39,243,163,136}
static final GF_Poly &GetECPoly(int ec_length) { private static final GF_Poly GetECPoly(int ec_length) {
Debug.DCHECK_GE(kMaxNumECBytes, ec_length); Debug.DCHECK_GE(kMaxNumECBytes, ec_length);
final GF_Poly *ec_poly = g_ec_polynomials[ec_length]; final GF_Poly ec_poly = g_ec_polynomials[ec_length];
Debug.DCHECK(ec_poly); Debug.DCHECK(ec_poly);
return *ec_poly; return ec_poly;
} }
// Generate error correction bytes of "ec_length". // Generate error correction bytes of "ec_length".
@ -830,9 +822,7 @@ public final class Encoder {
// Example: // Example:
// - Input: {32,65,205,69,41,220,46,128,236}, ec_length = 17 // - Input: {32,65,205,69,41,220,46,128,236}, ec_length = 17
// - Output: {42,159,74,221,244,169,239,150,138,70,237,85,224,96,74,219,61} // - Output: {42,159,74,221,244,169,239,150,138,70,237,85,224,96,74,219,61}
static void GenerateECBytes(final StringPiece &data_bytes, private static void GenerateECBytes(final StringPiece data_bytes, int ec_length, String ec_bytes) {
int ec_length,
String *ec_bytes) {
// First, fill the vector with "ec_length" copies of 0. // First, fill the vector with "ec_length" copies of 0.
// They are low-order zero coefficients. // They are low-order zero coefficients.
vector<GF_Element> *coeffs = new vector<GF_Element>(ec_length, 0); vector<GF_Element> *coeffs = new vector<GF_Element>(ec_length, 0);
@ -860,16 +850,12 @@ public final class Encoder {
ec_bytes.push_back(remainder.coeff(i)); ec_bytes.push_back(remainder.coeff(i));
} }
Debug.DCHECK_EQ(ec_length, ec_bytes.size()); Debug.DCHECK_EQ(ec_length, ec_bytes.size());
// Deallocate quotient and reminder.
delete divrem.first;
delete divrem.second;
} }
// Check if "byte1" and "byte2" can compose a valid Kanji letter // Check if "byte1" and "byte2" can compose a valid Kanji letter
// (2-byte Shift_JIS letter). // (2-byte Shift_JIS letter).
// The numbers are from http://ja.wikipedia.org/wiki/Shift_JIS. // The numbers are from http://ja.wikipedia.org/wiki/Shift_JIS.
static boolean IsValidKanji(final char byte1, final char byte2) { private static boolean IsValidKanji(final char byte1, final char byte2) {
return (byte2 != 0x7f && return (byte2 != 0x7f &&
((byte1 >= 0x81 && byte1 <= 0x9f && ((byte1 >= 0x81 && byte1 <= 0x9f &&
byte2 >= 0x40 && byte2 <= 0xfc) || byte2 >= 0x40 && byte2 <= 0xfc) ||
@ -878,7 +864,7 @@ public final class Encoder {
} }
// Check if "bytes" is a valid Kanji sequence. // Check if "bytes" is a valid Kanji sequence.
static boolean IsValidKanjiSequence(final StringPiece &bytes) { private static boolean IsValidKanjiSequence(final StringPiece bytes) {
if (bytes.size() % 2 != 0) { if (bytes.size() % 2 != 0) {
return false; return false;
} }

View file

@ -21,8 +21,8 @@ package com.google.zxing.qrcode.encoder;
* *
* JAVAPORT: I'm not happy about the argument ordering throughout the file, as I always like to have * JAVAPORT: I'm not happy about the argument ordering throughout the file, as I always like to have
* the horizontal component first, but this is for compatibility with the C++ code. The original * the horizontal component first, but this is for compatibility with the C++ code. The original
* code was a 2D array of ints, but since it only ever gets assigned zeros and ones, I'm going to * code was a 2D array of ints, but since it only ever gets assigned -1, 0, and 1, I'm going to use
* use less memory and go with bytes. * less memory and go with bytes.
* *
* @author dswitkin@google.com (Daniel Switkin) * @author dswitkin@google.com (Daniel Switkin)
*/ */