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,35 @@
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
13
+
14
+ class QR8bitByte
15
+ attr_reader :mode
16
+
17
+ def initialize( data )
18
+ @mode = QRMODE[:mode_8bit_byte]
19
+ @data = data;
20
+ end
21
+
22
+
23
+ def get_length
24
+ @data.size
25
+ end
26
+
27
+
28
+ def write( buffer )
29
+ ( 0...@data.size ).each do |i|
30
+ buffer.put( @data[i], 8 )
31
+ end
32
+ end
33
+ end
34
+
35
+ end
@@ -0,0 +1,56 @@
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
13
+
14
+ class QRBitBuffer
15
+ attr_reader :buffer
16
+
17
+ def initialize
18
+ @buffer = []
19
+ @length = 0
20
+ end
21
+
22
+
23
+ def get( index )
24
+ buf_index = (index / 8).floor
25
+ (( (@buffer[buf_index]).rszf(7 - index % 8)) & 1) == 1
26
+ end
27
+
28
+
29
+ def put( num, length )
30
+ ( 0...length ).each do |i|
31
+ put_bit((((num).rszf(length - i - 1)) & 1) == 1)
32
+ end
33
+ end
34
+
35
+
36
+ def get_length_in_bits
37
+ @length
38
+ end
39
+
40
+
41
+ def put_bit( bit )
42
+ buf_index = ( @length / 8 ).floor
43
+ if @buffer.size <= buf_index
44
+ @buffer << 0
45
+ end
46
+
47
+ if bit
48
+ @buffer[buf_index] |= ((0x80).rszf(@length % 8))
49
+ end
50
+
51
+ @length += 1
52
+ end
53
+
54
+ end
55
+
56
+ end
@@ -0,0 +1,394 @@
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
+ QRMODE = {
15
+ :mode_number => 1 << 0,
16
+ :mode_alpha_num => 1 << 1,
17
+ :mode_8bit_byte => 1 << 2,
18
+ :mode_kanji => 1 << 3
19
+ }
20
+
21
+ QRERRORCORRECTLEVEL = {
22
+ :l => 1,
23
+ :m => 0,
24
+ :q => 3,
25
+ :h => 2
26
+ }
27
+
28
+ QRMASKPATTERN = {
29
+ :pattern000 => 0,
30
+ :pattern001 => 1,
31
+ :pattern010 => 2,
32
+ :pattern011 => 3,
33
+ :pattern100 => 4,
34
+ :pattern101 => 5,
35
+ :pattern110 => 6,
36
+ :pattern111 => 7
37
+ }
38
+
39
+ # Generic QRCode exception class.
40
+
41
+ class QRCodeArgumentError < ArgumentError; end
42
+ class QRCodeRunTimeError < RuntimeError; end
43
+
44
+ # This is the main interface for creating your QRCode
45
+ # You create a new instance of QRCode and then you have
46
+ # a few simple methods to choose form
47
+
48
+ class QRCode
49
+ attr_reader :modules, :module_count
50
+
51
+ PAD0 = 0xEC
52
+ PAD1 = 0x11
53
+
54
+ # Expects a string to be parsed in, other options have defaults
55
+
56
+ def initialize( *args )
57
+ raise QRCodeArgumentError unless args.first.kind_of?( String )
58
+
59
+ @data = args.shift
60
+ options = args.extract_options!
61
+ level = options[:level] || :h
62
+ @error_correct_level = QRERRORCORRECTLEVEL[ level.to_sym ]
63
+ @type_number = options[:size] || 4
64
+ @module_count = @type_number * 4 + 17
65
+ @modules = nil
66
+ @data_cache = nil
67
+ @data_list = QR8bitByte.new( @data )
68
+
69
+ self.make # let's go !
70
+ end
71
+
72
+ # called parsing in a row and col coordinate
73
+ # * return true or false
74
+ # * raise exception if row < 0
75
+ # * raise exception if col < 0
76
+ # * raise exception if @module_count <= row
77
+ # * raise exception if @module_count <= col
78
+
79
+ def is_dark( row, col )
80
+ if row < 0 || @module_count <= row || col < 0 || @module_count <= col
81
+ raise QRCodeRunTimeError, "#{row},#{col}"
82
+ end
83
+ @modules[row][col]
84
+ end
85
+
86
+ def to_console
87
+ (0...@module_count).each do |col|
88
+ tmp = []
89
+ (0...@module_count).each do |row|
90
+ if is_dark(col,row)
91
+ tmp << "x"
92
+ else
93
+ tmp << " "
94
+ end
95
+ end
96
+ puts tmp.join
97
+ end
98
+ end
99
+
100
+ protected
101
+
102
+ def make #:nodoc:
103
+ make_impl( false, get_best_mask_pattern )
104
+ end
105
+
106
+ private
107
+
108
+
109
+ def make_impl( test, mask_pattern ) #:nodoc:
110
+ @modules = Array.new( @module_count )
111
+
112
+ ( 0...@module_count ).each do |row|
113
+ @modules[row] = Array.new( @module_count )
114
+ end
115
+
116
+ setup_position_probe_pattern( 0, 0 )
117
+ setup_position_probe_pattern( @module_count - 7, 0 )
118
+ setup_position_probe_pattern( 0, @module_count - 7 )
119
+ setup_position_adjust_pattern
120
+ setup_timing_pattern
121
+ setup_type_info( test, mask_pattern )
122
+ setup_type_number( test ) if @type_number >= 7
123
+
124
+ if @data_cache.nil?
125
+ @data_cache = QRCode.create_data(
126
+ @type_number, @error_correct_level, @data_list
127
+ )
128
+ end
129
+
130
+ map_data( @data_cache, mask_pattern )
131
+ end
132
+
133
+
134
+ def setup_position_probe_pattern( row, col ) #:nodoc:
135
+ ( -1..7 ).each do |r|
136
+ next if ( row + r ) <= -1 || @module_count <= ( row + r )
137
+ ( -1..7 ).each do |c|
138
+ next if ( col + c ) <= -1 || @module_count <= ( col + c )
139
+ if 0 <= r && r <= 6 && ( c == 0 || c == 6 ) || 0 <= c && c <= 6 && ( r == 0 || r == 6 ) || 2 <= r && r <= 4 && 2 <= c && c <= 4
140
+ @modules[row + r][col + c] = true;
141
+ else
142
+ @modules[row + r][col + c] = false;
143
+ end
144
+ end
145
+ end
146
+ end
147
+
148
+
149
+ def get_best_mask_pattern #:nodoc:
150
+ min_lost_point = 0
151
+ pattern = 0
152
+
153
+ ( 0...8 ).each do |i|
154
+ make_impl( true, i )
155
+ lost_point = QRUtil.get_lost_point( self )
156
+
157
+ if i == 0 || min_lost_point > lost_point
158
+ min_lost_point = lost_point
159
+ pattern = i
160
+ end
161
+ end
162
+ pattern
163
+ end
164
+
165
+
166
+ def setup_timing_pattern #:nodoc:
167
+ ( 8...@module_count - 8 ).each do |r|
168
+ next unless @modules[r][6].nil?
169
+ @modules[r][6] = (r % 2 == 0)
170
+ end
171
+
172
+ ( 8...@module_count - 8 ).each do |c|
173
+ next unless @modules[6][c].nil?
174
+ @modules[6][c] = (c % 2 == 0)
175
+ end
176
+ end
177
+
178
+
179
+ def setup_position_adjust_pattern #:nodoc:
180
+ pos = QRUtil.get_pattern_position(@type_number)
181
+
182
+ ( 0...pos.size ).each do |i|
183
+ ( 0...pos.size ).each do |j|
184
+ row = pos[i]
185
+ col = pos[j]
186
+
187
+ next unless @modules[row][col].nil?
188
+
189
+ ( -2..2 ).each do |r|
190
+ ( -2..2 ).each do |c|
191
+ if r == -2 || r == 2 || c == -2 || c == 2 || ( r == 0 && c == 0 )
192
+ @modules[row + r][col + c] = true
193
+ else
194
+ @modules[row + r][col + c] = false
195
+ end
196
+ end
197
+ end
198
+ end
199
+ end
200
+ end
201
+
202
+
203
+ def setup_type_number( test ) #:nodoc:
204
+ bits = QRUtil.get_bch_type_number( @type_number )
205
+
206
+ ( 0...18 ).each do |i|
207
+ mod = ( !test && ( (bits >> i) & 1) == 1 )
208
+ @modules[ (i / 3).floor ][ i % 3 + @module_count - 8 - 3 ] = mod
209
+ end
210
+
211
+ ( 0...18 ).each do |i|
212
+ mod = ( !test && ( (bits >> i) & 1) == 1 )
213
+ @modules[ i % 3 + @module_count - 8 - 3 ][ (i / 3).floor ] = mod
214
+ end
215
+ end
216
+
217
+
218
+ def setup_type_info( test, mask_pattern ) #:nodoc:
219
+ data = (@error_correct_level << 3 | mask_pattern)
220
+ bits = QRUtil.get_bch_type_info( data )
221
+
222
+ # vertical
223
+ ( 0...15 ).each do |i|
224
+ mod = (!test && ( (bits >> i) & 1) == 1)
225
+
226
+ if i < 6
227
+ @modules[i][8] = mod
228
+ elsif i < 8
229
+ @modules[ i + 1 ][8] = mod
230
+ else
231
+ @modules[ @module_count - 15 + i ][8] = mod
232
+ end
233
+
234
+ end
235
+
236
+ # horizontal
237
+ ( 0...15 ).each do |i|
238
+ mod = (!test && ( (bits >> i) & 1) == 1)
239
+
240
+ if i < 8
241
+ @modules[8][ @module_count - i - 1 ] = mod
242
+ elsif i < 9
243
+ @modules[8][ 15 - i - 1 + 1 ] = mod
244
+ else
245
+ @modules[8][ 15 - i - 1 ] = mod
246
+ end
247
+ end
248
+
249
+ # fixed module
250
+ @modules[ @module_count - 8 ][8] = !test
251
+ end
252
+
253
+
254
+ def map_data( data, mask_pattern ) #:nodoc:
255
+ inc = -1
256
+ row = @module_count - 1
257
+ bit_index = 7
258
+ byte_index = 0
259
+
260
+ ( @module_count - 1 ).step( 1, -2 ) do |col|
261
+ col = col - 1 if col <= 6
262
+
263
+ while true do
264
+ ( 0...2 ).each do |c|
265
+
266
+ if @modules[row][ col - c ].nil?
267
+ dark = false
268
+ if byte_index < data.size
269
+ dark = (( (data[byte_index]).rszf( bit_index ) & 1) == 1 )
270
+ end
271
+ mask = QRUtil.get_mask( mask_pattern, row, col - c )
272
+ dark = !dark if mask
273
+ @modules[row][ col - c ] = dark
274
+ bit_index -= 1
275
+
276
+ if bit_index == -1
277
+ byte_index += 1
278
+ bit_index = 7
279
+ end
280
+ end
281
+ end
282
+
283
+ row += inc
284
+
285
+ if row < 0 || @module_count <= row
286
+ row -= inc
287
+ inc = -inc
288
+ break
289
+ end
290
+ end
291
+ end
292
+ end
293
+
294
+ def QRCode.create_data( type_number, error_correct_level, data_list ) #:nodoc:
295
+ rs_blocks = QRRSBlock.get_rs_blocks( type_number, error_correct_level )
296
+ buffer = QRBitBuffer.new
297
+
298
+ data = data_list
299
+ buffer.put( data.mode, 4 )
300
+ buffer.put(
301
+ data.get_length, QRUtil.get_length_in_bits( data.mode, type_number )
302
+ )
303
+ data.write( buffer )
304
+
305
+ total_data_count = 0
306
+ ( 0...rs_blocks.size ).each do |i|
307
+ total_data_count = total_data_count + rs_blocks[i].data_count
308
+ end
309
+
310
+ if buffer.get_length_in_bits > total_data_count * 8
311
+ raise QRCodeRunTimeError,
312
+ "code length overflow. (#{buffer.get_length_in_bits}>#{total_data_count})"
313
+ end
314
+
315
+ if buffer.get_length_in_bits + 4 <= total_data_count * 8
316
+ buffer.put( 0, 4 )
317
+ end
318
+
319
+ while buffer.get_length_in_bits % 8 != 0
320
+ buffer.put_bit( false )
321
+ end
322
+
323
+ while true
324
+ break if buffer.get_length_in_bits >= total_data_count * 8
325
+ buffer.put( QRCode::PAD0, 8 )
326
+ break if buffer.get_length_in_bits >= total_data_count * 8
327
+ buffer.put( QRCode::PAD1, 8 )
328
+ end
329
+
330
+ QRCode.create_bytes( buffer, rs_blocks )
331
+ end
332
+
333
+
334
+ def QRCode.create_bytes( buffer, rs_blocks ) #:nodoc:
335
+ offset = 0
336
+ max_dc_count = 0
337
+ max_ec_count = 0
338
+ dcdata = Array.new( rs_blocks.size )
339
+ ecdata = Array.new( rs_blocks.size )
340
+
341
+ ( 0...rs_blocks.size ).each do |r|
342
+ dc_count = rs_blocks[r].data_count
343
+ ec_count = rs_blocks[r].total_count - dc_count
344
+ max_dc_count = [ max_dc_count, dc_count ].max
345
+ max_ec_count = [ max_ec_count, ec_count ].max
346
+ dcdata[r] = Array.new( dc_count )
347
+
348
+ ( 0...dcdata[r].size ).each do |i|
349
+ dcdata[r][i] = 0xff & buffer.buffer[ i + offset ]
350
+ end
351
+
352
+ offset = offset + dc_count
353
+ rs_poly = QRUtil.get_error_correct_polynomial( ec_count )
354
+ raw_poly = QRPolynomial.new( dcdata[r], rs_poly.get_length - 1 )
355
+ mod_poly = raw_poly.mod( rs_poly )
356
+ ecdata[r] = Array.new( rs_poly.get_length - 1 )
357
+ ( 0...ecdata[r].size ).each do |i|
358
+ mod_index = i + mod_poly.get_length - ecdata[r].size
359
+ ecdata[r][i] = mod_index >= 0 ? mod_poly.get( mod_index ) : 0
360
+ end
361
+ end
362
+
363
+ total_code_count = 0
364
+ ( 0...rs_blocks.size ).each do |i|
365
+ total_code_count = total_code_count + rs_blocks[i].total_count
366
+ end
367
+
368
+ data = Array.new( total_code_count )
369
+ index = 0
370
+
371
+ ( 0...max_dc_count ).each do |i|
372
+ ( 0...rs_blocks.size ).each do |r|
373
+ if i < dcdata[r].size
374
+ index += 1
375
+ data[index-1] = dcdata[r][i]
376
+ end
377
+ end
378
+ end
379
+
380
+ ( 0...max_ec_count ).each do |i|
381
+ ( 0...rs_blocks.size ).each do |r|
382
+ if i < ecdata[r].size
383
+ index += 1
384
+ data[index-1] = ecdata[r][i]
385
+ end
386
+ end
387
+ end
388
+
389
+ data
390
+ end
391
+
392
+ end
393
+
394
+ end