// 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
}