Telegram authentication requires you to open a chat on the phone. It's convenient to have a QR code for the case when you want to log in on the computer but have Telegram only on your phone and would be able to scan the QR instead of copy-pasting the link from the computer to the phone any other way. Originally we thought of generating QR on the client but found backend-generated QR a better alternative because we avoid adding one more JavaScript dependency to the frontend that way.
3051 lines
30 KiB
Go
3051 lines
30 KiB
Go
// go-qrcode
|
|
// Copyright 2014 Tom Harwood
|
|
|
|
package qrcode
|
|
|
|
import (
|
|
"log"
|
|
|
|
bitset "github.com/skip2/go-qrcode/bitset"
|
|
)
|
|
|
|
// Error detection/recovery capacity.
|
|
//
|
|
// There are several levels of error detection/recovery capacity. Higher levels
|
|
// of error recovery are able to correct more errors, with the trade-off of
|
|
// increased symbol size.
|
|
type RecoveryLevel int
|
|
|
|
const (
|
|
// Level L: 7% error recovery.
|
|
Low RecoveryLevel = iota
|
|
|
|
// Level M: 15% error recovery. Good default choice.
|
|
Medium
|
|
|
|
// Level Q: 25% error recovery.
|
|
High
|
|
|
|
// Level H: 30% error recovery.
|
|
Highest
|
|
)
|
|
|
|
// qrCodeVersion describes the data length and encoding order of a single QR
|
|
// Code version. There are 40 versions numbers x 4 recovery levels == 160
|
|
// possible qrCodeVersion structures.
|
|
type qrCodeVersion struct {
|
|
// Version number (1-40 inclusive).
|
|
version int
|
|
|
|
// Error recovery level.
|
|
level RecoveryLevel
|
|
|
|
dataEncoderType dataEncoderType
|
|
|
|
// Encoded data can be split into multiple blocks. Each block contains data
|
|
// and error recovery bytes.
|
|
//
|
|
// Larger QR Codes contain more blocks.
|
|
block []block
|
|
|
|
// Number of bits required to pad the combined data & error correction bit
|
|
// stream up to the symbol's full capacity.
|
|
numRemainderBits int
|
|
}
|
|
|
|
type block struct {
|
|
numBlocks int
|
|
|
|
// Total codewords (numCodewords == numErrorCodewords+numDataCodewords).
|
|
numCodewords int
|
|
|
|
// Number of data codewords.
|
|
numDataCodewords int
|
|
}
|
|
|
|
var (
|
|
versions = []qrCodeVersion{
|
|
{
|
|
1,
|
|
Low,
|
|
dataEncoderType1To9,
|
|
[]block{
|
|
{
|
|
1,
|
|
26,
|
|
19,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
1,
|
|
Medium,
|
|
dataEncoderType1To9,
|
|
[]block{
|
|
{
|
|
1,
|
|
26,
|
|
16,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
1,
|
|
High,
|
|
dataEncoderType1To9,
|
|
[]block{
|
|
{
|
|
1,
|
|
26,
|
|
13,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
1,
|
|
Highest,
|
|
dataEncoderType1To9,
|
|
[]block{
|
|
{
|
|
1,
|
|
26,
|
|
9,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
2,
|
|
Low,
|
|
dataEncoderType1To9,
|
|
[]block{
|
|
{
|
|
1,
|
|
44,
|
|
34,
|
|
},
|
|
},
|
|
7,
|
|
},
|
|
{
|
|
2,
|
|
Medium,
|
|
dataEncoderType1To9,
|
|
[]block{
|
|
{
|
|
1,
|
|
44,
|
|
28,
|
|
},
|
|
},
|
|
7,
|
|
},
|
|
{
|
|
2,
|
|
High,
|
|
dataEncoderType1To9,
|
|
[]block{
|
|
{
|
|
1,
|
|
44,
|
|
22,
|
|
},
|
|
},
|
|
7,
|
|
},
|
|
{
|
|
2,
|
|
Highest,
|
|
dataEncoderType1To9,
|
|
[]block{
|
|
{
|
|
1,
|
|
44,
|
|
16,
|
|
},
|
|
},
|
|
7,
|
|
},
|
|
{
|
|
3,
|
|
Low,
|
|
dataEncoderType1To9,
|
|
[]block{
|
|
{
|
|
1,
|
|
70,
|
|
55,
|
|
},
|
|
},
|
|
7,
|
|
},
|
|
{
|
|
3,
|
|
Medium,
|
|
dataEncoderType1To9,
|
|
[]block{
|
|
{
|
|
1,
|
|
70,
|
|
44,
|
|
},
|
|
},
|
|
7,
|
|
},
|
|
{
|
|
3,
|
|
High,
|
|
dataEncoderType1To9,
|
|
[]block{
|
|
{
|
|
2,
|
|
35,
|
|
17,
|
|
},
|
|
},
|
|
7,
|
|
},
|
|
{
|
|
3,
|
|
Highest,
|
|
dataEncoderType1To9,
|
|
[]block{
|
|
{
|
|
2,
|
|
35,
|
|
13,
|
|
},
|
|
},
|
|
7,
|
|
},
|
|
{
|
|
4,
|
|
Low,
|
|
dataEncoderType1To9,
|
|
[]block{
|
|
{
|
|
1,
|
|
100,
|
|
80,
|
|
},
|
|
},
|
|
7,
|
|
},
|
|
{
|
|
4,
|
|
Medium,
|
|
dataEncoderType1To9,
|
|
[]block{
|
|
{
|
|
2,
|
|
50,
|
|
32,
|
|
},
|
|
},
|
|
7,
|
|
},
|
|
{
|
|
4,
|
|
High,
|
|
dataEncoderType1To9,
|
|
[]block{
|
|
{
|
|
2,
|
|
50,
|
|
24,
|
|
},
|
|
},
|
|
7,
|
|
},
|
|
{
|
|
4,
|
|
Highest,
|
|
dataEncoderType1To9,
|
|
[]block{
|
|
{
|
|
4,
|
|
25,
|
|
9,
|
|
},
|
|
},
|
|
7,
|
|
},
|
|
{
|
|
5,
|
|
Low,
|
|
dataEncoderType1To9,
|
|
[]block{
|
|
{
|
|
1,
|
|
134,
|
|
108,
|
|
},
|
|
},
|
|
7,
|
|
},
|
|
{
|
|
5,
|
|
Medium,
|
|
dataEncoderType1To9,
|
|
[]block{
|
|
{
|
|
2,
|
|
67,
|
|
43,
|
|
},
|
|
},
|
|
7,
|
|
},
|
|
{
|
|
5,
|
|
High,
|
|
dataEncoderType1To9,
|
|
[]block{
|
|
{
|
|
2,
|
|
33,
|
|
15,
|
|
},
|
|
{
|
|
2,
|
|
34,
|
|
16,
|
|
},
|
|
},
|
|
7,
|
|
},
|
|
{
|
|
5,
|
|
Highest,
|
|
dataEncoderType1To9,
|
|
[]block{
|
|
{
|
|
2,
|
|
33,
|
|
11,
|
|
},
|
|
{
|
|
2,
|
|
34,
|
|
12,
|
|
},
|
|
},
|
|
7,
|
|
},
|
|
{
|
|
6,
|
|
Low,
|
|
dataEncoderType1To9,
|
|
[]block{
|
|
{
|
|
2,
|
|
86,
|
|
68,
|
|
},
|
|
},
|
|
7,
|
|
},
|
|
{
|
|
6,
|
|
Medium,
|
|
dataEncoderType1To9,
|
|
[]block{
|
|
{
|
|
4,
|
|
43,
|
|
27,
|
|
},
|
|
},
|
|
7,
|
|
},
|
|
{
|
|
6,
|
|
High,
|
|
dataEncoderType1To9,
|
|
[]block{
|
|
{
|
|
4,
|
|
43,
|
|
19,
|
|
},
|
|
},
|
|
7,
|
|
},
|
|
{
|
|
6,
|
|
Highest,
|
|
dataEncoderType1To9,
|
|
[]block{
|
|
{
|
|
4,
|
|
43,
|
|
15,
|
|
},
|
|
},
|
|
7,
|
|
},
|
|
{
|
|
7,
|
|
Low,
|
|
dataEncoderType1To9,
|
|
[]block{
|
|
{
|
|
2,
|
|
98,
|
|
78,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
7,
|
|
Medium,
|
|
dataEncoderType1To9,
|
|
[]block{
|
|
{
|
|
4,
|
|
49,
|
|
31,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
7,
|
|
High,
|
|
dataEncoderType1To9,
|
|
[]block{
|
|
{
|
|
2,
|
|
32,
|
|
14,
|
|
},
|
|
{
|
|
4,
|
|
33,
|
|
15,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
7,
|
|
Highest,
|
|
dataEncoderType1To9,
|
|
[]block{
|
|
{
|
|
4,
|
|
39,
|
|
13,
|
|
},
|
|
{
|
|
1,
|
|
40,
|
|
14,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
8,
|
|
Low,
|
|
dataEncoderType1To9,
|
|
[]block{
|
|
{
|
|
2,
|
|
121,
|
|
97,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
8,
|
|
Medium,
|
|
dataEncoderType1To9,
|
|
[]block{
|
|
{
|
|
2,
|
|
60,
|
|
38,
|
|
},
|
|
{
|
|
2,
|
|
61,
|
|
39,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
8,
|
|
High,
|
|
dataEncoderType1To9,
|
|
[]block{
|
|
{
|
|
4,
|
|
40,
|
|
18,
|
|
},
|
|
{
|
|
2,
|
|
41,
|
|
19,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
8,
|
|
Highest,
|
|
dataEncoderType1To9,
|
|
[]block{
|
|
{
|
|
4,
|
|
40,
|
|
14,
|
|
},
|
|
{
|
|
2,
|
|
41,
|
|
15,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
9,
|
|
Low,
|
|
dataEncoderType1To9,
|
|
[]block{
|
|
{
|
|
2,
|
|
146,
|
|
116,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
9,
|
|
Medium,
|
|
dataEncoderType1To9,
|
|
[]block{
|
|
{
|
|
3,
|
|
58,
|
|
36,
|
|
},
|
|
{
|
|
2,
|
|
59,
|
|
37,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
9,
|
|
High,
|
|
dataEncoderType1To9,
|
|
[]block{
|
|
{
|
|
4,
|
|
36,
|
|
16,
|
|
},
|
|
{
|
|
4,
|
|
37,
|
|
17,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
9,
|
|
Highest,
|
|
dataEncoderType1To9,
|
|
[]block{
|
|
{
|
|
4,
|
|
36,
|
|
12,
|
|
},
|
|
{
|
|
4,
|
|
37,
|
|
13,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
10,
|
|
Low,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
2,
|
|
86,
|
|
68,
|
|
},
|
|
{
|
|
2,
|
|
87,
|
|
69,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
10,
|
|
Medium,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
4,
|
|
69,
|
|
43,
|
|
},
|
|
{
|
|
1,
|
|
70,
|
|
44,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
10,
|
|
High,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
6,
|
|
43,
|
|
19,
|
|
},
|
|
{
|
|
2,
|
|
44,
|
|
20,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
10,
|
|
Highest,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
6,
|
|
43,
|
|
15,
|
|
},
|
|
{
|
|
2,
|
|
44,
|
|
16,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
11,
|
|
Low,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
4,
|
|
101,
|
|
81,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
11,
|
|
Medium,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
1,
|
|
80,
|
|
50,
|
|
},
|
|
{
|
|
4,
|
|
81,
|
|
51,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
11,
|
|
High,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
4,
|
|
50,
|
|
22,
|
|
},
|
|
{
|
|
4,
|
|
51,
|
|
23,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
11,
|
|
Highest,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
3,
|
|
36,
|
|
12,
|
|
},
|
|
{
|
|
8,
|
|
37,
|
|
13,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
12,
|
|
Low,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
2,
|
|
116,
|
|
92,
|
|
},
|
|
{
|
|
2,
|
|
117,
|
|
93,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
12,
|
|
Medium,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
6,
|
|
58,
|
|
36,
|
|
},
|
|
{
|
|
2,
|
|
59,
|
|
37,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
12,
|
|
High,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
4,
|
|
46,
|
|
20,
|
|
},
|
|
{
|
|
6,
|
|
47,
|
|
21,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
12,
|
|
Highest,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
7,
|
|
42,
|
|
14,
|
|
},
|
|
{
|
|
4,
|
|
43,
|
|
15,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
13,
|
|
Low,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
4,
|
|
133,
|
|
107,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
13,
|
|
Medium,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
8,
|
|
59,
|
|
37,
|
|
},
|
|
{
|
|
1,
|
|
60,
|
|
38,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
13,
|
|
High,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
8,
|
|
44,
|
|
20,
|
|
},
|
|
{
|
|
4,
|
|
45,
|
|
21,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
13,
|
|
Highest,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
12,
|
|
33,
|
|
11,
|
|
},
|
|
{
|
|
4,
|
|
34,
|
|
12,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
14,
|
|
Low,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
3,
|
|
145,
|
|
115,
|
|
},
|
|
{
|
|
1,
|
|
146,
|
|
116,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
14,
|
|
Medium,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
4,
|
|
64,
|
|
40,
|
|
},
|
|
{
|
|
5,
|
|
65,
|
|
41,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
14,
|
|
High,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
11,
|
|
36,
|
|
16,
|
|
},
|
|
{
|
|
5,
|
|
37,
|
|
17,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
14,
|
|
Highest,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
11,
|
|
36,
|
|
12,
|
|
},
|
|
{
|
|
5,
|
|
37,
|
|
13,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
15,
|
|
Low,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
5,
|
|
109,
|
|
87,
|
|
},
|
|
{
|
|
1,
|
|
110,
|
|
88,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
15,
|
|
Medium,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
5,
|
|
65,
|
|
41,
|
|
},
|
|
{
|
|
5,
|
|
66,
|
|
42,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
15,
|
|
High,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
5,
|
|
54,
|
|
24,
|
|
},
|
|
{
|
|
7,
|
|
55,
|
|
25,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
15,
|
|
Highest,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
11,
|
|
36,
|
|
12,
|
|
},
|
|
{
|
|
7,
|
|
37,
|
|
13,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
16,
|
|
Low,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
5,
|
|
122,
|
|
98,
|
|
},
|
|
{
|
|
1,
|
|
123,
|
|
99,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
16,
|
|
Medium,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
7,
|
|
73,
|
|
45,
|
|
},
|
|
{
|
|
3,
|
|
74,
|
|
46,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
16,
|
|
High,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
15,
|
|
43,
|
|
19,
|
|
},
|
|
{
|
|
2,
|
|
44,
|
|
20,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
16,
|
|
Highest,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
3,
|
|
45,
|
|
15,
|
|
},
|
|
{
|
|
13,
|
|
46,
|
|
16,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
17,
|
|
Low,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
1,
|
|
135,
|
|
107,
|
|
},
|
|
{
|
|
5,
|
|
136,
|
|
108,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
17,
|
|
Medium,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
10,
|
|
74,
|
|
46,
|
|
},
|
|
{
|
|
1,
|
|
75,
|
|
47,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
17,
|
|
High,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
1,
|
|
50,
|
|
22,
|
|
},
|
|
{
|
|
15,
|
|
51,
|
|
23,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
17,
|
|
Highest,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
2,
|
|
42,
|
|
14,
|
|
},
|
|
{
|
|
17,
|
|
43,
|
|
15,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
18,
|
|
Low,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
5,
|
|
150,
|
|
120,
|
|
},
|
|
{
|
|
1,
|
|
151,
|
|
121,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
18,
|
|
Medium,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
9,
|
|
69,
|
|
43,
|
|
},
|
|
{
|
|
4,
|
|
70,
|
|
44,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
18,
|
|
High,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
17,
|
|
50,
|
|
22,
|
|
},
|
|
{
|
|
1,
|
|
51,
|
|
23,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
18,
|
|
Highest,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
2,
|
|
42,
|
|
14,
|
|
},
|
|
{
|
|
19,
|
|
43,
|
|
15,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
19,
|
|
Low,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
3,
|
|
141,
|
|
113,
|
|
},
|
|
{
|
|
4,
|
|
142,
|
|
114,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
19,
|
|
Medium,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
3,
|
|
70,
|
|
44,
|
|
},
|
|
{
|
|
11,
|
|
71,
|
|
45,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
19,
|
|
High,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
17,
|
|
47,
|
|
21,
|
|
},
|
|
{
|
|
4,
|
|
48,
|
|
22,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
19,
|
|
Highest,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
9,
|
|
39,
|
|
13,
|
|
},
|
|
{
|
|
16,
|
|
40,
|
|
14,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
20,
|
|
Low,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
3,
|
|
135,
|
|
107,
|
|
},
|
|
{
|
|
5,
|
|
136,
|
|
108,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
20,
|
|
Medium,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
3,
|
|
67,
|
|
41,
|
|
},
|
|
{
|
|
13,
|
|
68,
|
|
42,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
20,
|
|
High,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
15,
|
|
54,
|
|
24,
|
|
},
|
|
{
|
|
5,
|
|
55,
|
|
25,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
20,
|
|
Highest,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
15,
|
|
43,
|
|
15,
|
|
},
|
|
{
|
|
10,
|
|
44,
|
|
16,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
21,
|
|
Low,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
4,
|
|
144,
|
|
116,
|
|
},
|
|
{
|
|
4,
|
|
145,
|
|
117,
|
|
},
|
|
},
|
|
4,
|
|
},
|
|
{
|
|
21,
|
|
Medium,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
17,
|
|
68,
|
|
42,
|
|
},
|
|
},
|
|
4,
|
|
},
|
|
{
|
|
21,
|
|
High,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
17,
|
|
50,
|
|
22,
|
|
},
|
|
{
|
|
6,
|
|
51,
|
|
23,
|
|
},
|
|
},
|
|
4,
|
|
},
|
|
{
|
|
21,
|
|
Highest,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
19,
|
|
46,
|
|
16,
|
|
},
|
|
{
|
|
6,
|
|
47,
|
|
17,
|
|
},
|
|
},
|
|
4,
|
|
},
|
|
{
|
|
22,
|
|
Low,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
2,
|
|
139,
|
|
111,
|
|
},
|
|
{
|
|
7,
|
|
140,
|
|
112,
|
|
},
|
|
},
|
|
4,
|
|
},
|
|
{
|
|
22,
|
|
Medium,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
17,
|
|
74,
|
|
46,
|
|
},
|
|
},
|
|
4,
|
|
},
|
|
{
|
|
22,
|
|
High,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
7,
|
|
54,
|
|
24,
|
|
},
|
|
{
|
|
16,
|
|
55,
|
|
25,
|
|
},
|
|
},
|
|
4,
|
|
},
|
|
{
|
|
22,
|
|
Highest,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
34,
|
|
37,
|
|
13,
|
|
},
|
|
},
|
|
4,
|
|
},
|
|
{
|
|
23,
|
|
Low,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
4,
|
|
151,
|
|
121,
|
|
},
|
|
{
|
|
5,
|
|
152,
|
|
122,
|
|
},
|
|
},
|
|
4,
|
|
},
|
|
{
|
|
23,
|
|
Medium,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
4,
|
|
75,
|
|
47,
|
|
},
|
|
{
|
|
14,
|
|
76,
|
|
48,
|
|
},
|
|
},
|
|
4,
|
|
},
|
|
{
|
|
23,
|
|
High,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
11,
|
|
54,
|
|
24,
|
|
},
|
|
{
|
|
14,
|
|
55,
|
|
25,
|
|
},
|
|
},
|
|
4,
|
|
},
|
|
{
|
|
23,
|
|
Highest,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
16,
|
|
45,
|
|
15,
|
|
},
|
|
{
|
|
14,
|
|
46,
|
|
16,
|
|
},
|
|
},
|
|
4,
|
|
},
|
|
{
|
|
24,
|
|
Low,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
6,
|
|
147,
|
|
117,
|
|
},
|
|
{
|
|
4,
|
|
148,
|
|
118,
|
|
},
|
|
},
|
|
4,
|
|
},
|
|
{
|
|
24,
|
|
Medium,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
6,
|
|
73,
|
|
45,
|
|
},
|
|
{
|
|
14,
|
|
74,
|
|
46,
|
|
},
|
|
},
|
|
4,
|
|
},
|
|
{
|
|
24,
|
|
High,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
11,
|
|
54,
|
|
24,
|
|
},
|
|
{
|
|
16,
|
|
55,
|
|
25,
|
|
},
|
|
},
|
|
4,
|
|
},
|
|
{
|
|
24,
|
|
Highest,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
30,
|
|
46,
|
|
16,
|
|
},
|
|
{
|
|
2,
|
|
47,
|
|
17,
|
|
},
|
|
},
|
|
4,
|
|
},
|
|
{
|
|
25,
|
|
Low,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
8,
|
|
132,
|
|
106,
|
|
},
|
|
{
|
|
4,
|
|
133,
|
|
107,
|
|
},
|
|
},
|
|
4,
|
|
},
|
|
{
|
|
25,
|
|
Medium,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
8,
|
|
75,
|
|
47,
|
|
},
|
|
{
|
|
13,
|
|
76,
|
|
48,
|
|
},
|
|
},
|
|
4,
|
|
},
|
|
{
|
|
25,
|
|
High,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
7,
|
|
54,
|
|
24,
|
|
},
|
|
{
|
|
22,
|
|
55,
|
|
25,
|
|
},
|
|
},
|
|
4,
|
|
},
|
|
{
|
|
25,
|
|
Highest,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
22,
|
|
45,
|
|
15,
|
|
},
|
|
{
|
|
13,
|
|
46,
|
|
16,
|
|
},
|
|
},
|
|
4,
|
|
},
|
|
{
|
|
26,
|
|
Low,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
10,
|
|
142,
|
|
114,
|
|
},
|
|
{
|
|
2,
|
|
143,
|
|
115,
|
|
},
|
|
},
|
|
4,
|
|
},
|
|
{
|
|
26,
|
|
Medium,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
19,
|
|
74,
|
|
46,
|
|
},
|
|
{
|
|
4,
|
|
75,
|
|
47,
|
|
},
|
|
},
|
|
4,
|
|
},
|
|
{
|
|
26,
|
|
High,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
28,
|
|
50,
|
|
22,
|
|
},
|
|
{
|
|
6,
|
|
51,
|
|
23,
|
|
},
|
|
},
|
|
4,
|
|
},
|
|
{
|
|
26,
|
|
Highest,
|
|
dataEncoderType10To26,
|
|
[]block{
|
|
{
|
|
33,
|
|
46,
|
|
16,
|
|
},
|
|
{
|
|
4,
|
|
47,
|
|
17,
|
|
},
|
|
},
|
|
4,
|
|
},
|
|
{
|
|
27,
|
|
Low,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
8,
|
|
152,
|
|
122,
|
|
},
|
|
{
|
|
4,
|
|
153,
|
|
123,
|
|
},
|
|
},
|
|
4,
|
|
},
|
|
{
|
|
27,
|
|
Medium,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
22,
|
|
73,
|
|
45,
|
|
},
|
|
{
|
|
3,
|
|
74,
|
|
46,
|
|
},
|
|
},
|
|
4,
|
|
},
|
|
{
|
|
27,
|
|
High,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
8,
|
|
53,
|
|
23,
|
|
},
|
|
{
|
|
26,
|
|
54,
|
|
24,
|
|
},
|
|
},
|
|
4,
|
|
},
|
|
{
|
|
27,
|
|
Highest,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
12,
|
|
45,
|
|
15,
|
|
},
|
|
{
|
|
28,
|
|
46,
|
|
16,
|
|
},
|
|
},
|
|
4,
|
|
},
|
|
{
|
|
28,
|
|
Low,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
3,
|
|
147,
|
|
117,
|
|
},
|
|
{
|
|
10,
|
|
148,
|
|
118,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
28,
|
|
Medium,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
3,
|
|
73,
|
|
45,
|
|
},
|
|
{
|
|
23,
|
|
74,
|
|
46,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
28,
|
|
High,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
4,
|
|
54,
|
|
24,
|
|
},
|
|
{
|
|
31,
|
|
55,
|
|
25,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
28,
|
|
Highest,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
11,
|
|
45,
|
|
15,
|
|
},
|
|
{
|
|
31,
|
|
46,
|
|
16,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
29,
|
|
Low,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
7,
|
|
146,
|
|
116,
|
|
},
|
|
{
|
|
7,
|
|
147,
|
|
117,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
29,
|
|
Medium,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
21,
|
|
73,
|
|
45,
|
|
},
|
|
{
|
|
7,
|
|
74,
|
|
46,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
29,
|
|
High,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
1,
|
|
53,
|
|
23,
|
|
},
|
|
{
|
|
37,
|
|
54,
|
|
24,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
29,
|
|
Highest,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
19,
|
|
45,
|
|
15,
|
|
},
|
|
{
|
|
26,
|
|
46,
|
|
16,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
30,
|
|
Low,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
5,
|
|
145,
|
|
115,
|
|
},
|
|
{
|
|
10,
|
|
146,
|
|
116,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
30,
|
|
Medium,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
19,
|
|
75,
|
|
47,
|
|
},
|
|
{
|
|
10,
|
|
76,
|
|
48,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
30,
|
|
High,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
15,
|
|
54,
|
|
24,
|
|
},
|
|
{
|
|
25,
|
|
55,
|
|
25,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
30,
|
|
Highest,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
23,
|
|
45,
|
|
15,
|
|
},
|
|
{
|
|
25,
|
|
46,
|
|
16,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
31,
|
|
Low,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
13,
|
|
145,
|
|
115,
|
|
},
|
|
{
|
|
3,
|
|
146,
|
|
116,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
31,
|
|
Medium,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
2,
|
|
74,
|
|
46,
|
|
},
|
|
{
|
|
29,
|
|
75,
|
|
47,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
31,
|
|
High,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
42,
|
|
54,
|
|
24,
|
|
},
|
|
{
|
|
1,
|
|
55,
|
|
25,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
31,
|
|
Highest,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
23,
|
|
45,
|
|
15,
|
|
},
|
|
{
|
|
28,
|
|
46,
|
|
16,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
32,
|
|
Low,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
17,
|
|
145,
|
|
115,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
32,
|
|
Medium,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
10,
|
|
74,
|
|
46,
|
|
},
|
|
{
|
|
23,
|
|
75,
|
|
47,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
32,
|
|
High,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
10,
|
|
54,
|
|
24,
|
|
},
|
|
{
|
|
35,
|
|
55,
|
|
25,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
32,
|
|
Highest,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
19,
|
|
45,
|
|
15,
|
|
},
|
|
{
|
|
35,
|
|
46,
|
|
16,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
33,
|
|
Low,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
17,
|
|
145,
|
|
115,
|
|
},
|
|
{
|
|
1,
|
|
146,
|
|
116,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
33,
|
|
Medium,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
14,
|
|
74,
|
|
46,
|
|
},
|
|
{
|
|
21,
|
|
75,
|
|
47,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
33,
|
|
High,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
29,
|
|
54,
|
|
24,
|
|
},
|
|
{
|
|
19,
|
|
55,
|
|
25,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
33,
|
|
Highest,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
11,
|
|
45,
|
|
15,
|
|
},
|
|
{
|
|
46,
|
|
46,
|
|
16,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
34,
|
|
Low,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
13,
|
|
145,
|
|
115,
|
|
},
|
|
{
|
|
6,
|
|
146,
|
|
116,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
34,
|
|
Medium,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
14,
|
|
74,
|
|
46,
|
|
},
|
|
{
|
|
23,
|
|
75,
|
|
47,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
34,
|
|
High,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
44,
|
|
54,
|
|
24,
|
|
},
|
|
{
|
|
7,
|
|
55,
|
|
25,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
34,
|
|
Highest,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
59,
|
|
46,
|
|
16,
|
|
},
|
|
{
|
|
1,
|
|
47,
|
|
17,
|
|
},
|
|
},
|
|
3,
|
|
},
|
|
{
|
|
35,
|
|
Low,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
12,
|
|
151,
|
|
121,
|
|
},
|
|
{
|
|
7,
|
|
152,
|
|
122,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
35,
|
|
Medium,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
12,
|
|
75,
|
|
47,
|
|
},
|
|
{
|
|
26,
|
|
76,
|
|
48,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
35,
|
|
High,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
39,
|
|
54,
|
|
24,
|
|
},
|
|
{
|
|
14,
|
|
55,
|
|
25,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
35,
|
|
Highest,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
22,
|
|
45,
|
|
15,
|
|
},
|
|
{
|
|
41,
|
|
46,
|
|
16,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
36,
|
|
Low,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
6,
|
|
151,
|
|
121,
|
|
},
|
|
{
|
|
14,
|
|
152,
|
|
122,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
36,
|
|
Medium,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
6,
|
|
75,
|
|
47,
|
|
},
|
|
{
|
|
34,
|
|
76,
|
|
48,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
36,
|
|
High,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
46,
|
|
54,
|
|
24,
|
|
},
|
|
{
|
|
10,
|
|
55,
|
|
25,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
36,
|
|
Highest,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
2,
|
|
45,
|
|
15,
|
|
},
|
|
{
|
|
64,
|
|
46,
|
|
16,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
37,
|
|
Low,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
17,
|
|
152,
|
|
122,
|
|
},
|
|
{
|
|
4,
|
|
153,
|
|
123,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
37,
|
|
Medium,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
29,
|
|
74,
|
|
46,
|
|
},
|
|
{
|
|
14,
|
|
75,
|
|
47,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
37,
|
|
High,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
49,
|
|
54,
|
|
24,
|
|
},
|
|
{
|
|
10,
|
|
55,
|
|
25,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
37,
|
|
Highest,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
24,
|
|
45,
|
|
15,
|
|
},
|
|
{
|
|
46,
|
|
46,
|
|
16,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
38,
|
|
Low,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
4,
|
|
152,
|
|
122,
|
|
},
|
|
{
|
|
18,
|
|
153,
|
|
123,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
38,
|
|
Medium,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
13,
|
|
74,
|
|
46,
|
|
},
|
|
{
|
|
32,
|
|
75,
|
|
47,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
38,
|
|
High,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
48,
|
|
54,
|
|
24,
|
|
},
|
|
{
|
|
14,
|
|
55,
|
|
25,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
38,
|
|
Highest,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
42,
|
|
45,
|
|
15,
|
|
},
|
|
{
|
|
32,
|
|
46,
|
|
16,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
39,
|
|
Low,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
20,
|
|
147,
|
|
117,
|
|
},
|
|
{
|
|
4,
|
|
148,
|
|
118,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
39,
|
|
Medium,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
40,
|
|
75,
|
|
47,
|
|
},
|
|
{
|
|
7,
|
|
76,
|
|
48,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
39,
|
|
High,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
43,
|
|
54,
|
|
24,
|
|
},
|
|
{
|
|
22,
|
|
55,
|
|
25,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
39,
|
|
Highest,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
10,
|
|
45,
|
|
15,
|
|
},
|
|
{
|
|
67,
|
|
46,
|
|
16,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
40,
|
|
Low,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
19,
|
|
148,
|
|
118,
|
|
},
|
|
{
|
|
6,
|
|
149,
|
|
119,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
40,
|
|
Medium,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
18,
|
|
75,
|
|
47,
|
|
},
|
|
{
|
|
31,
|
|
76,
|
|
48,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
40,
|
|
High,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
34,
|
|
54,
|
|
24,
|
|
},
|
|
{
|
|
34,
|
|
55,
|
|
25,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
{
|
|
40,
|
|
Highest,
|
|
dataEncoderType27To40,
|
|
[]block{
|
|
{
|
|
20,
|
|
45,
|
|
15,
|
|
},
|
|
{
|
|
61,
|
|
46,
|
|
16,
|
|
},
|
|
},
|
|
0,
|
|
},
|
|
}
|
|
)
|
|
|
|
var (
|
|
// Each QR Code contains a 15-bit Format Information value. The 15 bits
|
|
// consist of 5 data bits concatenated with 10 error correction bits.
|
|
//
|
|
// The 5 data bits consist of:
|
|
// - 2 bits for the error correction level (L=01, M=00, G=11, H=10).
|
|
// - 3 bits for the data mask pattern identifier.
|
|
//
|
|
// formatBitSequence is a mapping from the 5 data bits to the completed 15-bit
|
|
// Format Information value.
|
|
//
|
|
// For example, a QR Code using error correction level L, and data mask
|
|
// pattern identifier 001:
|
|
//
|
|
// 01 | 001 = 01001 = 0x9
|
|
// formatBitSequence[0x9].qrCode = 0x72f3 = 111001011110011
|
|
formatBitSequence = []struct {
|
|
regular uint32
|
|
micro uint32
|
|
}{
|
|
{0x5412, 0x4445},
|
|
{0x5125, 0x4172},
|
|
{0x5e7c, 0x4e2b},
|
|
{0x5b4b, 0x4b1c},
|
|
{0x45f9, 0x55ae},
|
|
{0x40ce, 0x5099},
|
|
{0x4f97, 0x5fc0},
|
|
{0x4aa0, 0x5af7},
|
|
{0x77c4, 0x6793},
|
|
{0x72f3, 0x62a4},
|
|
{0x7daa, 0x6dfd},
|
|
{0x789d, 0x68ca},
|
|
{0x662f, 0x7678},
|
|
{0x6318, 0x734f},
|
|
{0x6c41, 0x7c16},
|
|
{0x6976, 0x7921},
|
|
{0x1689, 0x06de},
|
|
{0x13be, 0x03e9},
|
|
{0x1ce7, 0x0cb0},
|
|
{0x19d0, 0x0987},
|
|
{0x0762, 0x1735},
|
|
{0x0255, 0x1202},
|
|
{0x0d0c, 0x1d5b},
|
|
{0x083b, 0x186c},
|
|
{0x355f, 0x2508},
|
|
{0x3068, 0x203f},
|
|
{0x3f31, 0x2f66},
|
|
{0x3a06, 0x2a51},
|
|
{0x24b4, 0x34e3},
|
|
{0x2183, 0x31d4},
|
|
{0x2eda, 0x3e8d},
|
|
{0x2bed, 0x3bba},
|
|
}
|
|
|
|
// QR Codes version 7 and higher contain an 18-bit Version Information value,
|
|
// consisting of a 6 data bits and 12 error correction bits.
|
|
//
|
|
// versionBitSequence is a mapping from QR Code version to the completed
|
|
// 18-bit Version Information value.
|
|
//
|
|
// For example, a QR code of version 7:
|
|
// versionBitSequence[0x7] = 0x07c94 = 000111110010010100
|
|
versionBitSequence = []uint32{
|
|
0x00000,
|
|
0x00000,
|
|
0x00000,
|
|
0x00000,
|
|
0x00000,
|
|
0x00000,
|
|
0x00000,
|
|
0x07c94,
|
|
0x085bc,
|
|
0x09a99,
|
|
0x0a4d3,
|
|
0x0bbf6,
|
|
0x0c762,
|
|
0x0d847,
|
|
0x0e60d,
|
|
0x0f928,
|
|
0x10b78,
|
|
0x1145d,
|
|
0x12a17,
|
|
0x13532,
|
|
0x149a6,
|
|
0x15683,
|
|
0x168c9,
|
|
0x177ec,
|
|
0x18ec4,
|
|
0x191e1,
|
|
0x1afab,
|
|
0x1b08e,
|
|
0x1cc1a,
|
|
0x1d33f,
|
|
0x1ed75,
|
|
0x1f250,
|
|
0x209d5,
|
|
0x216f0,
|
|
0x228ba,
|
|
0x2379f,
|
|
0x24b0b,
|
|
0x2542e,
|
|
0x26a64,
|
|
0x27541,
|
|
0x28c69,
|
|
}
|
|
)
|
|
|
|
const (
|
|
formatInfoLengthBits = 15
|
|
versionInfoLengthBits = 18
|
|
)
|
|
|
|
// formatInfo returns the 15-bit Format Information value for a QR
|
|
// code.
|
|
func (v qrCodeVersion) formatInfo(maskPattern int) *bitset.Bitset {
|
|
formatID := 0
|
|
|
|
switch v.level {
|
|
case Low:
|
|
formatID = 0x08 // 0b01000
|
|
case Medium:
|
|
formatID = 0x00 // 0b00000
|
|
case High:
|
|
formatID = 0x18 // 0b11000
|
|
case Highest:
|
|
formatID = 0x10 // 0b10000
|
|
default:
|
|
log.Panicf("Invalid level %d", v.level)
|
|
}
|
|
|
|
if maskPattern < 0 || maskPattern > 7 {
|
|
log.Panicf("Invalid maskPattern %d", maskPattern)
|
|
}
|
|
|
|
formatID |= maskPattern & 0x7
|
|
|
|
result := bitset.New()
|
|
|
|
result.AppendUint32(formatBitSequence[formatID].regular, formatInfoLengthBits)
|
|
|
|
return result
|
|
}
|
|
|
|
// versionInfo returns the 18-bit Version Information value for a QR Code.
|
|
//
|
|
// Version Information is applicable only to QR Codes versions 7-40 inclusive.
|
|
// nil is returned if Version Information is not required.
|
|
func (v qrCodeVersion) versionInfo() *bitset.Bitset {
|
|
if v.version < 7 {
|
|
return nil
|
|
}
|
|
|
|
result := bitset.New()
|
|
result.AppendUint32(versionBitSequence[v.version], 18)
|
|
|
|
return result
|
|
}
|
|
|
|
// numDataBits returns the data capacity in bits.
|
|
func (v qrCodeVersion) numDataBits() int {
|
|
numDataBits := 0
|
|
for _, b := range v.block {
|
|
numDataBits += 8 * b.numBlocks * b.numDataCodewords // 8 bits in a byte
|
|
}
|
|
|
|
return numDataBits
|
|
}
|
|
|
|
// chooseQRCodeVersion chooses the most suitable QR Code version for a stated
|
|
// data length in bits, the error recovery level required, and the data encoder
|
|
// used.
|
|
//
|
|
// The chosen QR Code version is the smallest version able to fit numDataBits
|
|
// and the optional terminator bits required by the specified encoder.
|
|
//
|
|
// On success the chosen QR Code version is returned.
|
|
func chooseQRCodeVersion(level RecoveryLevel, encoder *dataEncoder, numDataBits int) *qrCodeVersion {
|
|
var chosenVersion *qrCodeVersion
|
|
|
|
for _, v := range versions {
|
|
if v.level != level {
|
|
continue
|
|
} else if v.version < encoder.minVersion {
|
|
continue
|
|
} else if v.version > encoder.maxVersion {
|
|
break
|
|
}
|
|
|
|
numFreeBits := v.numDataBits() - numDataBits
|
|
|
|
if numFreeBits >= 0 {
|
|
chosenVersion = &v
|
|
break
|
|
}
|
|
}
|
|
|
|
return chosenVersion
|
|
}
|
|
|
|
func (v qrCodeVersion) numTerminatorBitsRequired(numDataBits int) int {
|
|
numFreeBits := v.numDataBits() - numDataBits
|
|
|
|
var numTerminatorBits int
|
|
|
|
switch {
|
|
case numFreeBits >= 4:
|
|
numTerminatorBits = 4
|
|
default:
|
|
numTerminatorBits = numFreeBits
|
|
}
|
|
|
|
return numTerminatorBits
|
|
}
|
|
|
|
// numBlocks returns the number of blocks.
|
|
func (v qrCodeVersion) numBlocks() int {
|
|
numBlocks := 0
|
|
|
|
for _, b := range v.block {
|
|
numBlocks += b.numBlocks
|
|
}
|
|
|
|
return numBlocks
|
|
}
|
|
|
|
// numBitsToPadToCodeword returns the number of bits required to pad data of
|
|
// length numDataBits upto the nearest codeword size.
|
|
func (v qrCodeVersion) numBitsToPadToCodeword(numDataBits int) int {
|
|
if numDataBits == v.numDataBits() {
|
|
return 0
|
|
}
|
|
|
|
return (8 - numDataBits%8) % 8
|
|
}
|
|
|
|
// symbolSize returns the size of the QR Code symbol in number of modules (which
|
|
// is both the width and height, since QR codes are square). The QR Code has
|
|
// size symbolSize() x symbolSize() pixels. This does not include the quiet
|
|
// zone.
|
|
func (v qrCodeVersion) symbolSize() int {
|
|
return 21 + (v.version-1)*4
|
|
}
|
|
|
|
// quietZoneSize returns the number of pixels of border space on each side of
|
|
// the QR Code. The quiet space assists with decoding.
|
|
func (v qrCodeVersion) quietZoneSize() int {
|
|
return 4
|
|
}
|
|
|
|
// getQRCodeVersion returns the QR Code version by version number and recovery
|
|
// level. Returns nil if the requested combination is not defined.
|
|
func getQRCodeVersion(level RecoveryLevel, version int) *qrCodeVersion {
|
|
for _, v := range versions {
|
|
if v.level == level && v.version == version {
|
|
return &v
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|