rqrcode 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ #--
4
+ # Copyright 2004 by Duncan Robertson (duncan@whomwah.com).
5
+ # All rights reserved.
6
+
7
+ # Permission is granted for use, copying, modification, distribution,
8
+ # and distribution of modified versions of this work as long as the
9
+ # above copyright notice is included.
10
+ #++
11
+
12
+ module RQRCode #:nodoc:
13
+
14
+ class QRMath
15
+
16
+ module_eval {
17
+ exp_table = Array.new(256)
18
+ log_table = Array.new(256)
19
+
20
+ ( 0...8 ).each do |i|
21
+ exp_table[i] = 1 << i
22
+ end
23
+
24
+ ( 8...256 ).each do |i|
25
+ exp_table[i] = exp_table[i - 4] \
26
+ ^ exp_table[i - 5] \
27
+ ^ exp_table[i - 6] \
28
+ ^ exp_table[i - 8]
29
+ end
30
+
31
+ ( 0...255 ).each do |i|
32
+ log_table[exp_table[i] ] = i
33
+ end
34
+
35
+ EXP_TABLE = exp_table
36
+ LOG_TABLE = log_table
37
+ }
38
+
39
+ class << self
40
+
41
+ def glog(n)
42
+ raise QRCodeRunTimeError, "glog(#{n})" if ( n < 1 )
43
+ LOG_TABLE[n]
44
+ end
45
+
46
+
47
+ def gexp(n)
48
+ while n < 0
49
+ n = n + 255
50
+ end
51
+
52
+ while n >= 256
53
+ n = n - 255
54
+ end
55
+
56
+ EXP_TABLE[n]
57
+ end
58
+
59
+ end
60
+
61
+ end
62
+
63
+ end
@@ -0,0 +1,78 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ #--
4
+ # Copyright 2004 by Duncan Robertson (duncan@whomwah.com).
5
+ # All rights reserved.
6
+
7
+ # Permission is granted for use, copying, modification, distribution,
8
+ # and distribution of modified versions of this work as long as the
9
+ # above copyright notice is included.
10
+ #++
11
+
12
+ module RQRCode #:nodoc:
13
+
14
+ class QRPolynomial
15
+
16
+ def initialize( num, shift )
17
+ raise QRCodeRunTimeError, "#{num.size}/#{shift}" if num.empty?
18
+ offset = 0
19
+
20
+ while offset < num.size && num[offset] == 0
21
+ offset = offset + 1
22
+ end
23
+
24
+ @num = Array.new( num.size - offset + shift )
25
+
26
+ ( 0...num.size - offset ).each do |i|
27
+ @num[i] = num[i + offset]
28
+ end
29
+ end
30
+
31
+
32
+ def get( index )
33
+ @num[index]
34
+ end
35
+
36
+
37
+ def get_length
38
+ @num.size
39
+ end
40
+
41
+
42
+ def multiply( e )
43
+ num = Array.new( get_length + e.get_length - 1 )
44
+
45
+ ( 0...get_length ).each do |i|
46
+ ( 0...e.get_length ).each do |j|
47
+ tmp = num[i + j].nil? ? 0 : num[i + j]
48
+ num[i + j] = tmp ^ QRMath.gexp(QRMath.glog( get(i) ) + QRMath.glog(e.get(j)))
49
+ end
50
+ end
51
+
52
+ return QRPolynomial.new( num, 0 )
53
+ end
54
+
55
+
56
+ def mod( e )
57
+ if get_length - e.get_length < 0
58
+ return self
59
+ end
60
+
61
+ ratio = QRMath.glog(get(0)) - QRMath.glog(e.get(0))
62
+ num = Array.new(get_length)
63
+
64
+ ( 0...get_length ).each do |i|
65
+ num[i] = get(i)
66
+ end
67
+
68
+ ( 0...e.get_length ).each do |i|
69
+ tmp = num[i].nil? ? 0 : num[i]
70
+ num[i] = tmp ^ QRMath.gexp(QRMath.glog(e.get(i)) + ratio)
71
+ end
72
+
73
+ return QRPolynomial.new( num, 0 ).mod(e)
74
+ end
75
+
76
+ end
77
+
78
+ end
@@ -0,0 +1,134 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ #--
4
+ # Copyright 2004 by Duncan Robertson (duncan@whomwah.com).
5
+ # All rights reserved.
6
+
7
+ # Permission is granted for use, copying, modification, distribution,
8
+ # and distribution of modified versions of this work as long as the
9
+ # above copyright notice is included.
10
+ #++
11
+
12
+ module RQRCode #:nodoc:
13
+
14
+ class QRRSBlock
15
+ attr_reader :data_count, :total_count
16
+
17
+ def initialize( total_count, data_count )
18
+ @total_count = total_count
19
+ @data_count = data_count
20
+ end
21
+
22
+ RS_BLOCK_TABLE = [
23
+
24
+ # L
25
+ # M
26
+ # Q
27
+ # H
28
+
29
+ # 1
30
+ [1, 26, 19],
31
+ [1, 26, 16],
32
+ [1, 26, 13],
33
+ [1, 26, 9],
34
+
35
+ # 2
36
+ [1, 44, 34],
37
+ [1, 44, 28],
38
+ [1, 44, 22],
39
+ [1, 44, 16],
40
+
41
+ # 3
42
+ [1, 70, 55],
43
+ [1, 70, 44],
44
+ [2, 35, 17],
45
+ [2, 35, 13],
46
+
47
+ # 4
48
+ [1, 100, 80],
49
+ [2, 50, 32],
50
+ [2, 50, 24],
51
+ [4, 25, 9],
52
+
53
+ # 5
54
+ [1, 134, 108],
55
+ [2, 67, 43],
56
+ [2, 33, 15, 2, 34, 16],
57
+ [2, 33, 11, 2, 34, 12],
58
+
59
+ # 6
60
+ [2, 86, 68],
61
+ [4, 43, 27],
62
+ [4, 43, 19],
63
+ [4, 43, 15],
64
+
65
+ # 7
66
+ [2, 98, 78],
67
+ [4, 49, 31],
68
+ [2, 32, 14, 4, 33, 15],
69
+ [4, 39, 13, 1, 40, 14],
70
+
71
+ # 8
72
+ [2, 121, 97],
73
+ [2, 60, 38, 2, 61, 39],
74
+ [4, 40, 18, 2, 41, 19],
75
+ [4, 40, 14, 2, 41, 15],
76
+
77
+ # 9
78
+ [2, 146, 116],
79
+ [3, 58, 36, 2, 59, 37],
80
+ [4, 36, 16, 4, 37, 17],
81
+ [4, 36, 12, 4, 37, 13],
82
+
83
+ # 10
84
+ [2, 86, 68, 2, 87, 69],
85
+ [4, 69, 43, 1, 70, 44],
86
+ [6, 43, 19, 2, 44, 20],
87
+ [6, 43, 15, 2, 44, 16]
88
+
89
+ ]
90
+
91
+
92
+ def QRRSBlock.get_rs_blocks( type_no, error_correct_level )
93
+ rs_block = QRRSBlock.get_rs_block_table( type_no, error_correct_level )
94
+
95
+ if rs_block.nil?
96
+ raise QRCodeRunTimeError,
97
+ "bad rsblock @ typeno: #{type_no}/error_correct_level:#{error_correct_level}"
98
+ end
99
+
100
+ length = rs_block.size / 3
101
+ list = []
102
+
103
+ ( 0...length ).each do |i|
104
+ count = rs_block[i * 3 + 0]
105
+ total_count = rs_block[i * 3 + 1]
106
+ data_count = rs_block[i * 3 + 2]
107
+
108
+ ( 0...count ).each do |j|
109
+ list << QRRSBlock.new( total_count, data_count )
110
+ end
111
+ end
112
+
113
+ list
114
+ end
115
+
116
+
117
+ def QRRSBlock.get_rs_block_table( type_number, error_correct_level )
118
+ case error_correct_level
119
+ when QRERRORCORRECTLEVEL[:l]
120
+ QRRSBlock::RS_BLOCK_TABLE[(type_number - 1) * 4 + 0]
121
+ when QRERRORCORRECTLEVEL[:m]
122
+ QRRSBlock::RS_BLOCK_TABLE[(type_number - 1) * 4 + 1]
123
+ when QRERRORCORRECTLEVEL[:q]
124
+ QRRSBlock::RS_BLOCK_TABLE[(type_number - 1) * 4 + 2]
125
+ when QRERRORCORRECTLEVEL[:h]
126
+ QRRSBlock::RS_BLOCK_TABLE[(type_number - 1) * 4 + 3]
127
+ else
128
+ nil
129
+ end
130
+ end
131
+
132
+ end
133
+
134
+ end
@@ -0,0 +1,254 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ #--
4
+ # Copyright 2004 by Duncan Robertson (duncan@whomwah.com).
5
+ # All rights reserved.
6
+
7
+ # Permission is granted for use, copying, modification, distribution,
8
+ # and distribution of modified versions of this work as long as the
9
+ # above copyright notice is included.
10
+ #++
11
+
12
+ module RQRCode #:nodoc:
13
+
14
+ class QRUtil
15
+
16
+ PATTERN_POSITION_TABLE = [
17
+
18
+ [],
19
+ [6, 18],
20
+ [6, 22],
21
+ [6, 26],
22
+ [6, 30],
23
+ [6, 34],
24
+ [6, 22, 38],
25
+ [6, 24, 42],
26
+ [6, 26, 46],
27
+ [6, 28, 50],
28
+ [6, 30, 54],
29
+ [6, 32, 58],
30
+ [6, 34, 62],
31
+ [6, 26, 46, 66],
32
+ [6, 26, 48, 70],
33
+ [6, 26, 50, 74],
34
+ [6, 30, 54, 78],
35
+ [6, 30, 56, 82],
36
+ [6, 30, 58, 86],
37
+ [6, 34, 62, 90],
38
+ [6, 28, 50, 72, 94],
39
+ [6, 26, 50, 74, 98],
40
+ [6, 30, 54, 78, 102],
41
+ [6, 28, 54, 80, 106],
42
+ [6, 32, 58, 84, 110],
43
+ [6, 30, 58, 86, 114],
44
+ [6, 34, 62, 90, 118],
45
+ [6, 26, 50, 74, 98, 122],
46
+ [6, 30, 54, 78, 102, 126],
47
+ [6, 26, 52, 78, 104, 130],
48
+ [6, 30, 56, 82, 108, 134],
49
+ [6, 34, 60, 86, 112, 138],
50
+ [6, 30, 58, 86, 114, 142],
51
+ [6, 34, 62, 90, 118, 146],
52
+ [6, 30, 54, 78, 102, 126, 150],
53
+ [6, 24, 50, 76, 102, 128, 154],
54
+ [6, 28, 54, 80, 106, 132, 158],
55
+ [6, 32, 58, 84, 110, 136, 162],
56
+ [6, 26, 54, 82, 110, 138, 166],
57
+ [6, 30, 58, 86, 114, 142, 170]
58
+ ]
59
+
60
+ G15 = 1 << 10 | 1 << 8 | 1 << 5 | 1 << 4 | 1 << 2 | 1 << 1 | 1 << 0
61
+ G18 = 1 << 12 | 1 << 11 | 1 << 10 | 1 << 9 | 1 << 8 | 1 << 5 | 1 << 2 | 1 << 0
62
+ G15_MASK = 1 << 14 | 1 << 12 | 1 << 10 | 1 << 4 | 1 << 1
63
+
64
+
65
+ def QRUtil.get_bch_type_info( data )
66
+ d = data << 10
67
+ while QRUtil.get_bch_digit(d) - QRUtil.get_bch_digit(G15) >= 0
68
+ d ^= (G15 << (QRUtil.get_bch_digit(d) - QRUtil.get_bch_digit(G15)))
69
+ end
70
+ (( data << 10 ) | d) ^ G15_MASK
71
+ end
72
+
73
+
74
+ def QRUtil.get_bch_type_number( data )
75
+ d = data << 12
76
+ while QRUtil.get_bch_digit(d) - QRUtil.get_bch_digit(G18) >= 0
77
+ d ^= (G18 << (QRUtil.get_bch_digit(d) - QRUtil.get_bch_digit(G18)))
78
+ end
79
+ ( data << 12 ) | d
80
+ end
81
+
82
+
83
+ def QRUtil.get_bch_digit( data )
84
+ digit = 0
85
+
86
+ while data != 0
87
+ digit = digit + 1
88
+ data = (data).rszf(1)
89
+ end
90
+
91
+ digit
92
+ end
93
+
94
+
95
+ def QRUtil.get_pattern_position( type_number )
96
+ PATTERN_POSITION_TABLE[ type_number - 1 ]
97
+ end
98
+
99
+
100
+ def QRUtil.get_mask( mask_pattern, i, j )
101
+ case mask_pattern
102
+ when QRMASKPATTERN[:pattern000]
103
+ (i + j) % 2 == 0
104
+ when QRMASKPATTERN[:pattern001]
105
+ i % 2 == 0
106
+ when QRMASKPATTERN[:pattern010]
107
+ j % 3 == 0
108
+ when QRMASKPATTERN[:pattern011]
109
+ (i + j) % 3 == 0
110
+ when QRMASKPATTERN[:pattern100]
111
+ ((i / 2).floor + (j / 3).floor ) % 2 == 0
112
+ when QRMASKPATTERN[:pattern101]
113
+ (i * j) % 2 + (i * j) % 3 == 0
114
+ when QRMASKPATTERN[:pattern110]
115
+ ( (i * j) % 2 + (i * j) % 3) % 2 == 0
116
+ when QRMASKPATTERN[:pattern111]
117
+ ( (i * j) % 3 + (i + j) % 2) % 2 == 0
118
+ else
119
+ raise QRCodeRunTimeError, "bad mask_pattern: #{mask_pattern}"
120
+ end
121
+ end
122
+
123
+
124
+ def QRUtil.get_error_correct_polynomial( error_correct_length )
125
+ a = QRPolynomial.new( [1], 0 )
126
+
127
+ ( 0...error_correct_length ).each do |i|
128
+ a = a.multiply( QRPolynomial.new( [1, QRMath.gexp(i)], 0 ) )
129
+ end
130
+
131
+ a
132
+ end
133
+
134
+
135
+ def QRUtil.get_length_in_bits( mode, type )
136
+ if 1 <= type && type < 10
137
+
138
+ # 1 - 9
139
+ case mode
140
+ when QRMODE[:mode_number] : 10
141
+ when QRMODE[:mode_alpha_num] : 9
142
+ when QRMODE[:mode_8bit_byte] : 8
143
+ when QRMODE[:mode_kanji] : 8
144
+ else
145
+ raise QRCodeRunTimeError, "mode: #{mode}"
146
+ end
147
+
148
+ elsif type < 27
149
+
150
+ # 10 -26
151
+ case mode
152
+ when QRMODE[:mode_number] : 12
153
+ when QRMODE[:mode_alpha_num] : 11
154
+ when QRMODE[:mode_8bit_byte] : 16
155
+ when QRMODE[:mode_kanji] : 10
156
+ else
157
+ raise QRCodeRunTimeError, "mode: #{mode}"
158
+ end
159
+
160
+ elsif type < 41
161
+
162
+ # 27 - 40
163
+ case mode
164
+ when QRMODE[:mode_number] : 14
165
+ when QRMODE[:mode_alpha_num] : 13
166
+ when QRMODE[:mode_8bit_byte] : 16
167
+ when QRMODE[:mode_kanji] : 12
168
+ else
169
+ raise QRCodeRunTimeError, "mode: #{mode}"
170
+ end
171
+
172
+ else
173
+ raise QRCodeRunTimeError, "type: #{type}"
174
+ end
175
+ end
176
+
177
+
178
+ def QRUtil.get_lost_point( qr_code )
179
+ module_count = qr_code.module_count
180
+ lost_point = 0
181
+
182
+ # level1
183
+ ( 0...module_count ).each do |row|
184
+ ( 0...module_count ).each do |col|
185
+ same_count = 0
186
+ dark = qr_code.is_dark( row, col )
187
+
188
+ ( -1..1 ).each do |r|
189
+ next if row + r < 0 || module_count <= row + r
190
+
191
+ ( -1..1 ).each do |c|
192
+ next if col + c < 0 || module_count <= col + c
193
+ next if r == 0 && c == 0
194
+ if dark == qr_code.is_dark( row + r, col + c )
195
+ same_count += 1
196
+ end
197
+ end
198
+ end
199
+
200
+ if same_count > 5
201
+ lost_point += (3 + same_count - 5)
202
+ end
203
+ end
204
+ end
205
+
206
+ # level 2
207
+ ( 0...( module_count - 1 ) ).each do |row|
208
+ ( 0...( module_count - 1 ) ).each do |col|
209
+ count = 0
210
+ count = count + 1 if qr_code.is_dark( row, col )
211
+ count = count + 1 if qr_code.is_dark( row + 1, col )
212
+ count = count + 1 if qr_code.is_dark( row, col + 1 )
213
+ count = count + 1 if qr_code.is_dark( row + 1, col + 1 )
214
+ lost_point = lost_point + 3 if (count == 0 || count == 4)
215
+ end
216
+ end
217
+
218
+ # level 3
219
+ ( 0...module_count ).each do |row|
220
+ ( 0...( module_count - 6 ) ).each do |col|
221
+ if qr_code.is_dark( row, col ) && !qr_code.is_dark( row, col + 1 ) && qr_code.is_dark( row, col + 2 ) && qr_code.is_dark( row, col + 3 ) && qr_code.is_dark( row, col + 4 ) && !qr_code.is_dark( row, col + 5 ) && qr_code.is_dark( row, col + 6 )
222
+ lost_point = lost_point + 40
223
+ end
224
+ end
225
+ end
226
+
227
+ ( 0...module_count ).each do |col|
228
+ ( 0...( module_count - 6 ) ).each do |row|
229
+ if qr_code.is_dark(row, col) && !qr_code.is_dark(row + 1, col) && qr_code.is_dark(row + 2, col) && qr_code.is_dark(row + 3, col) && qr_code.is_dark(row + 4, col) && !qr_code.is_dark(row + 5, col) && qr_code.is_dark(row + 6, col)
230
+ lost_point = lost_point + 40
231
+ end
232
+ end
233
+ end
234
+
235
+ # level 4
236
+ dark_count = 0
237
+
238
+ ( 0...module_count ).each do |col|
239
+ ( 0...module_count ).each do |row|
240
+ if qr_code.is_dark(row, col)
241
+ dark_count = dark_count + 1
242
+ end
243
+ end
244
+ end
245
+
246
+ ratio = (100 * dark_count / module_count / module_count - 50).abs / 5
247
+ lost_point = lost_point * 10
248
+
249
+ lost_point
250
+ end
251
+
252
+ end
253
+
254
+ end