rqrcode 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,3 @@
1
+ *0.1.0* (Feb 23rd, 2008)
2
+
3
+ * Initial Release [DR]
data/README ADDED
@@ -0,0 +1,91 @@
1
+ = Project: rQRCode, Encode QRCodes
2
+
3
+ rQRCode is a library for encoding QR Codes in Ruby. It has a simple interface with all the standard qrcode options. It was adapted from the Javascript library by Kazuhiko Arase.
4
+
5
+ = An Overview
6
+
7
+ Let's clear up some rQRCode stuff.
8
+
9
+ # rQRCode is a *standalone library*. It requires no other libraries. Just Ruby!
10
+ # It is an encoding library. You can't decode QR codes with it.
11
+ # The interface is simple and assumes you just want to encode a string into a QR code
12
+ # QR code is trademarked by Denso Wave inc
13
+
14
+ = Rescources
15
+
16
+ # wikipedia [http://en.wikipedia.org/wiki/QR_Code]
17
+ # Denso-Wave website [http://www.denso-wave.com/qrcode/index-e.html]
18
+ # kaywa [http://qrcode.kaywa.com/]
19
+
20
+
21
+ == Installing
22
+
23
+ You may get the latest stable version from Rubyforge. Source gems are also available.
24
+
25
+ $ gem install rqrcode
26
+
27
+ === Loading rQRCode Itself
28
+
29
+ You have installed the gem already, yeah?
30
+
31
+ require 'rubygems'
32
+ require 'qrqcode'
33
+
34
+ === Simple QRCode generation to screen
35
+
36
+ qr = RQRCode::QRCode.new( 'my string to generate', :size => 4, :level => :h )
37
+ qr.to_console
38
+ #
39
+ # Prints:
40
+ # xxxxxxx x x x x x xx xxxxxxx
41
+ # x x xxx xxxxxx xxx x x
42
+ # x xxx x xxxxx x xx x xxx x
43
+ # ... etc
44
+
45
+ === Simple QRCode generation to view (RubyOnRails)
46
+
47
+ controller:
48
+ @qr = RQRCode::QRCode.new( 'my string to generate', :size => 4, :level => :h )
49
+
50
+ view: (minimal styling added)
51
+ <style type="text/css">
52
+ table {
53
+ border-width: 0;
54
+ border-style: none;
55
+ border-color: #0000ff;
56
+ border-collapse: collapse;
57
+ }
58
+ td {
59
+ border-width: 0;
60
+ border-style: none;
61
+ border-color: #0000ff;
62
+ border-collapse: collapse;
63
+ padding: 0;
64
+ margin: 0;
65
+ width: 10px;
66
+ height: 10px;
67
+ }
68
+ td.black { background-color: #000; }
69
+ td.white { background-color: #fff; }
70
+ </style>
71
+
72
+ <table>
73
+ <% (0...@qr.module_count).each do |x| %>
74
+ <tr>
75
+ <% (0...@qr.module_count).each do |y| %>
76
+ <% if @qr.is_dark(x,y) %>
77
+ <td class="black"/>
78
+ <% else %>
79
+ <td class="white"/>
80
+ <% end %>
81
+ <% end %>
82
+ </tr>
83
+ <% end %>
84
+ </table>
85
+
86
+ == Contact
87
+
88
+ Author:: Duncan Robertson
89
+ Email:: duncan@whomwah.com
90
+ Home Page:: http://whomwah.com
91
+ License:: MIT Licence (http://www.opensource.org/licenses/mit-license.html)
@@ -0,0 +1,13 @@
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
+ require "rqrcode/core_ext"
13
+ require "rqrcode/qrcode"
@@ -0,0 +1,5 @@
1
+ Dir[File.dirname(__FILE__) + "/core_ext/*.rb"].sort.each do |path|
2
+ filename = File.basename(path)
3
+ require "rqrcode/core_ext/#{filename}"
4
+ end
5
+
@@ -0,0 +1,5 @@
1
+ require 'rqrcode/core_ext/array/behavior'
2
+
3
+ class Array
4
+ include CoreExtensions::Array::Behavior
5
+ end
@@ -0,0 +1,9 @@
1
+ module CoreExtensions
2
+ module Array
3
+ module Behavior
4
+ def extract_options!
5
+ last.is_a?(::Hash) ? pop : {}
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ require 'rqrcode/core_ext/integer/bitwise'
2
+
3
+ class Integer
4
+ include CoreExtensions::Integer::Bitwise
5
+ end
@@ -0,0 +1,11 @@
1
+ module CoreExtensions
2
+ module Integer
3
+ module Bitwise
4
+ def rszf(count)
5
+ # zero fill right shift
6
+ (self >> count) & ((2 ** ((self.size * 8) - count))-1)
7
+ end
8
+ end
9
+ end
10
+ end
11
+
@@ -0,0 +1,924 @@
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
+ 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
+ class QRCodeArgumentError < ArgumentError; end
40
+ class QRCodeRunTimeError < RuntimeError; end
41
+
42
+ class QRCode
43
+ attr_reader :modules, :module_count
44
+
45
+ PAD0 = 0xEC
46
+ PAD1 = 0x11
47
+
48
+ def initialize( *args )
49
+ raise QRCodeArgumentError unless args.first.kind_of?( String )
50
+
51
+ @data = args.shift
52
+ options = args.extract_options!
53
+ level = options[:level] || :h
54
+ @error_correct_level = QRERRORCORRECTLEVEL[ level.to_sym ]
55
+ @type_number = options[:size] || 4
56
+ @module_count = @type_number * 4 + 17
57
+ @modules = nil
58
+ @data_cache = nil
59
+ @data_list = QR8bitByte.new( @data )
60
+
61
+ self.make # let's go !
62
+ end
63
+
64
+
65
+ def is_dark( row, col )
66
+ if row < 0 || @module_count <= row || col < 0 || @module_count <= col
67
+ raise QRCodeRunTimeError, "#{row},#{col}"
68
+ end
69
+ @modules[row][col]
70
+ end
71
+
72
+ def to_console
73
+ (0...@module_count).each do |col|
74
+ tmp = []
75
+ (0...@module_count).each do |row|
76
+ if is_dark(col,row)
77
+ tmp << "x"
78
+ else
79
+ tmp << " "
80
+ end
81
+ end
82
+ puts tmp.join
83
+ end
84
+ end
85
+
86
+ protected
87
+
88
+ def make
89
+ make_impl( false, get_best_mask_pattern )
90
+ end
91
+
92
+ private
93
+
94
+
95
+ def make_impl( test, mask_pattern )
96
+ @modules = Array.new( @module_count )
97
+
98
+ ( 0...@module_count ).each do |row|
99
+ @modules[row] = Array.new( @module_count )
100
+ end
101
+
102
+ setup_position_probe_pattern( 0, 0 )
103
+ setup_position_probe_pattern( @module_count - 7, 0 )
104
+ setup_position_probe_pattern( 0, @module_count - 7 )
105
+ setup_position_adjust_pattern
106
+ setup_timing_pattern
107
+ setup_type_info( test, mask_pattern )
108
+ setup_type_number( test ) if @type_number >= 7
109
+
110
+ if @data_cache.nil?
111
+ @data_cache = QRCode.create_data(
112
+ @type_number, @error_correct_level, @data_list
113
+ )
114
+ end
115
+
116
+ map_data( @data_cache, mask_pattern )
117
+ end
118
+
119
+
120
+ def setup_position_probe_pattern( row, col )
121
+ ( -1..7 ).each do |r|
122
+ next if ( row + r ) <= -1 || @module_count <= ( row + r )
123
+ ( -1..7 ).each do |c|
124
+ next if ( col + c ) <= -1 || @module_count <= ( col + c )
125
+ 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
126
+ @modules[row + r][col + c] = true;
127
+ else
128
+ @modules[row + r][col + c] = false;
129
+ end
130
+ end
131
+ end
132
+ end
133
+
134
+
135
+ def get_best_mask_pattern
136
+ min_lost_point = 0
137
+ pattern = 0
138
+
139
+ ( 0...8 ).each do |i|
140
+ make_impl( true, i )
141
+ lost_point = QRUtil.get_lost_point( self )
142
+
143
+ if i == 0 || min_lost_point > lost_point
144
+ min_lost_point = lost_point
145
+ pattern = i
146
+ end
147
+ end
148
+ pattern
149
+ end
150
+
151
+
152
+ def setup_timing_pattern
153
+ ( 8...@module_count - 8 ).each do |r|
154
+ next unless @modules[r][6].nil?
155
+ @modules[r][6] = (r % 2 == 0)
156
+ end
157
+
158
+ ( 8...@module_count - 8 ).each do |c|
159
+ next unless @modules[6][c].nil?
160
+ @modules[6][c] = (c % 2 == 0)
161
+ end
162
+ end
163
+
164
+
165
+ def setup_position_adjust_pattern
166
+ pos = QRUtil.get_pattern_position(@type_number)
167
+
168
+ ( 0...pos.size ).each do |i|
169
+ ( 0...pos.size ).each do |j|
170
+ row = pos[i]
171
+ col = pos[j]
172
+
173
+ next unless @modules[row][col].nil?
174
+
175
+ ( -2..2 ).each do |r|
176
+ ( -2..2 ).each do |c|
177
+ if r == -2 || r == 2 || c == -2 || c == 2 || ( r == 0 && c == 0 )
178
+ @modules[row + r][col + c] = true
179
+ else
180
+ @modules[row + r][col + c] = false
181
+ end
182
+ end
183
+ end
184
+ end
185
+ end
186
+ end
187
+
188
+
189
+ def setup_type_number( test )
190
+ bits = QRUtil.get_bch_type_number( @type_number )
191
+
192
+ ( 0...18 ).each do |i|
193
+ mod = ( !test && ( (bits >> i) & 1) == 1 )
194
+ @modules[ (i / 3).floor ][ i % 3 + @module_count - 8 - 3 ] = mod
195
+ end
196
+
197
+ ( 0...18 ).each do |i|
198
+ mod = ( !test && ( (bits >> i) & 1) == 1 )
199
+ @modules[ i % 3 + @module_count - 8 - 3 ][ (i / 3).floor ] = mod
200
+ end
201
+ end
202
+
203
+
204
+ def setup_type_info( test, mask_pattern )
205
+ data = (@error_correct_level << 3 | mask_pattern)
206
+ bits = QRUtil.get_bch_type_info( data )
207
+
208
+ # vertical
209
+ ( 0...15 ).each do |i|
210
+ mod = (!test && ( (bits >> i) & 1) == 1)
211
+
212
+ if i < 6
213
+ @modules[i][8] = mod
214
+ elsif i < 8
215
+ @modules[ i + 1 ][8] = mod
216
+ else
217
+ @modules[ @module_count - 15 + i ][8] = mod
218
+ end
219
+
220
+ end
221
+
222
+ # horizontal
223
+ ( 0...15 ).each do |i|
224
+ mod = (!test && ( (bits >> i) & 1) == 1)
225
+
226
+ if i < 8
227
+ @modules[8][ @module_count - i - 1 ] = mod
228
+ elsif i < 9
229
+ @modules[8][ 15 - i - 1 + 1 ] = mod
230
+ else
231
+ @modules[8][ 15 - i - 1 ] = mod
232
+ end
233
+ end
234
+
235
+ # fixed module
236
+ @modules[ @module_count - 8 ][8] = !test
237
+ end
238
+
239
+
240
+ def map_data( data, mask_pattern )
241
+ inc = -1
242
+ row = @module_count - 1
243
+ bit_index = 7
244
+ byte_index = 0
245
+
246
+ ( @module_count - 1 ).step( 1, -2 ) do |col|
247
+ col = col - 1 if col <= 6
248
+
249
+ while true do
250
+ ( 0...2 ).each do |c|
251
+
252
+ if @modules[row][ col - c ].nil?
253
+ dark = false
254
+ if byte_index < data.size
255
+ dark = (( (data[byte_index]).rszf( bit_index ) & 1) == 1 )
256
+ end
257
+ mask = QRUtil.get_mask( mask_pattern, row, col - c )
258
+ dark = !dark if mask
259
+ @modules[row][ col - c ] = dark
260
+ bit_index -= 1
261
+
262
+ if bit_index == -1
263
+ byte_index += 1
264
+ bit_index = 7
265
+ end
266
+ end
267
+ end
268
+
269
+ row += inc
270
+
271
+ if row < 0 || @module_count <= row
272
+ row -= inc
273
+ inc = -inc
274
+ break
275
+ end
276
+ end
277
+ end
278
+ end
279
+
280
+ def QRCode.create_data( type_number, error_correct_level, data_list )
281
+ rs_blocks = QRRSBlock.get_rs_blocks( type_number, error_correct_level )
282
+ buffer = QRBitBuffer.new
283
+
284
+ data = data_list
285
+ buffer.put( data.mode, 4 )
286
+ buffer.put(
287
+ data.get_length, QRUtil.get_length_in_bits( data.mode, type_number )
288
+ )
289
+ data.write( buffer )
290
+
291
+ total_data_count = 0
292
+ ( 0...rs_blocks.size ).each do |i|
293
+ total_data_count = total_data_count + rs_blocks[i].data_count
294
+ end
295
+
296
+ if buffer.get_length_in_bits > total_data_count * 8
297
+ raise QRCodeRunTimeError,
298
+ "code length overflow. (#{buffer.get_length_in_bits}>#{total_data_count})"
299
+ end
300
+
301
+ if buffer.get_length_in_bits + 4 <= total_data_count * 8
302
+ buffer.put( 0, 4 )
303
+ end
304
+
305
+ while buffer.get_length_in_bits % 8 != 0
306
+ buffer.put_bit( false )
307
+ end
308
+
309
+ while true
310
+ break if buffer.get_length_in_bits >= total_data_count * 8
311
+ buffer.put( QRCode::PAD0, 8 )
312
+ break if buffer.get_length_in_bits >= total_data_count * 8
313
+ buffer.put( QRCode::PAD1, 8 )
314
+ end
315
+
316
+ QRCode.create_bytes( buffer, rs_blocks )
317
+ end
318
+
319
+
320
+ def QRCode.create_bytes( buffer, rs_blocks )
321
+ offset = 0
322
+ max_dc_count = 0
323
+ max_ec_count = 0
324
+ dcdata = Array.new( rs_blocks.size )
325
+ ecdata = Array.new( rs_blocks.size )
326
+
327
+ ( 0...rs_blocks.size ).each do |r|
328
+ dc_count = rs_blocks[r].data_count
329
+ ec_count = rs_blocks[r].total_count - dc_count
330
+ max_dc_count = [ max_dc_count, dc_count ].max
331
+ max_ec_count = [ max_ec_count, ec_count ].max
332
+ dcdata[r] = Array.new( dc_count )
333
+
334
+ ( 0...dcdata[r].size ).each do |i|
335
+ dcdata[r][i] = 0xff & buffer.buffer[ i + offset ]
336
+ end
337
+
338
+ offset = offset + dc_count
339
+ rs_poly = QRUtil.get_error_correct_polynomial( ec_count )
340
+ raw_poly = QRPolynomial.new( dcdata[r], rs_poly.get_length - 1 )
341
+ mod_poly = raw_poly.mod( rs_poly )
342
+ ecdata[r] = Array.new( rs_poly.get_length - 1 )
343
+ ( 0...ecdata[r].size ).each do |i|
344
+ mod_index = i + mod_poly.get_length - ecdata[r].size
345
+ ecdata[r][i] = mod_index >= 0 ? mod_poly.get( mod_index ) : 0
346
+ end
347
+ end
348
+
349
+ total_code_count = 0
350
+ ( 0...rs_blocks.size ).each do |i|
351
+ total_code_count = total_code_count + rs_blocks[i].total_count
352
+ end
353
+
354
+ data = Array.new( total_code_count )
355
+ index = 0
356
+
357
+ ( 0...max_dc_count ).each do |i|
358
+ ( 0...rs_blocks.size ).each do |r|
359
+ if i < dcdata[r].size
360
+ index += 1
361
+ data[index-1] = dcdata[r][i]
362
+ end
363
+ end
364
+ end
365
+
366
+ ( 0...max_ec_count ).each do |i|
367
+ ( 0...rs_blocks.size ).each do |r|
368
+ if i < ecdata[r].size
369
+ index += 1
370
+ data[index-1] = ecdata[r][i]
371
+ end
372
+ end
373
+ end
374
+
375
+ data
376
+ end
377
+
378
+ end
379
+
380
+
381
+ class QR8bitByte
382
+ attr_reader :mode
383
+
384
+ def initialize( data )
385
+ @mode = QRMODE[:mode_8bit_byte]
386
+ @data = data;
387
+ end
388
+
389
+
390
+ def get_length
391
+ @data.size
392
+ end
393
+
394
+
395
+ def write( buffer )
396
+ ( 0...@data.size ).each do |i|
397
+ buffer.put( @data[i], 8 )
398
+ end
399
+ end
400
+
401
+ end
402
+
403
+
404
+ class QRPolynomial
405
+
406
+ def initialize( num, shift )
407
+ raise QRCodeRunTimeError, "#{num.size}/#{shift}" if num.empty?
408
+ offset = 0
409
+
410
+ while offset < num.size && num[offset] == 0
411
+ offset = offset + 1
412
+ end
413
+
414
+ @num = Array.new( num.size - offset + shift )
415
+
416
+ ( 0...num.size - offset ).each do |i|
417
+ @num[i] = num[i + offset]
418
+ end
419
+ end
420
+
421
+
422
+ def get( index )
423
+ @num[index]
424
+ end
425
+
426
+
427
+ def get_length
428
+ @num.size
429
+ end
430
+
431
+
432
+ def multiply( e )
433
+ num = Array.new( get_length + e.get_length - 1 )
434
+
435
+ ( 0...get_length ).each do |i|
436
+ ( 0...e.get_length ).each do |j|
437
+ tmp = num[i + j].nil? ? 0 : num[i + j]
438
+ num[i + j] = tmp ^ QRMath.gexp(QRMath.glog( get(i) ) + QRMath.glog(e.get(j)))
439
+ end
440
+ end
441
+
442
+ return QRPolynomial.new( num, 0 )
443
+ end
444
+
445
+
446
+ def mod( e )
447
+ if get_length - e.get_length < 0
448
+ return self
449
+ end
450
+
451
+ ratio = QRMath.glog(get(0)) - QRMath.glog(e.get(0))
452
+ num = Array.new(get_length)
453
+
454
+ ( 0...get_length ).each do |i|
455
+ num[i] = get(i)
456
+ end
457
+
458
+ ( 0...e.get_length ).each do |i|
459
+ tmp = num[i].nil? ? 0 : num[i]
460
+ num[i] = tmp ^ QRMath.gexp(QRMath.glog(e.get(i)) + ratio)
461
+ end
462
+
463
+ return QRPolynomial.new( num, 0 ).mod(e)
464
+ end
465
+
466
+ end
467
+
468
+
469
+ class QRRSBlock
470
+ attr_reader :data_count, :total_count
471
+
472
+ def initialize( total_count, data_count )
473
+ @total_count = total_count
474
+ @data_count = data_count
475
+ end
476
+
477
+ RS_BLOCK_TABLE = [
478
+
479
+ # L
480
+ # M
481
+ # Q
482
+ # H
483
+
484
+ # 1
485
+ [1, 26, 19],
486
+ [1, 26, 16],
487
+ [1, 26, 13],
488
+ [1, 26, 9],
489
+
490
+ # 2
491
+ [1, 44, 34],
492
+ [1, 44, 28],
493
+ [1, 44, 22],
494
+ [1, 44, 16],
495
+
496
+ # 3
497
+ [1, 70, 55],
498
+ [1, 70, 44],
499
+ [2, 35, 17],
500
+ [2, 35, 13],
501
+
502
+ # 4
503
+ [1, 100, 80],
504
+ [2, 50, 32],
505
+ [2, 50, 24],
506
+ [4, 25, 9],
507
+
508
+ # 5
509
+ [1, 134, 108],
510
+ [2, 67, 43],
511
+ [2, 33, 15, 2, 34, 16],
512
+ [2, 33, 11, 2, 34, 12],
513
+
514
+ # 6
515
+ [2, 86, 68],
516
+ [4, 43, 27],
517
+ [4, 43, 19],
518
+ [4, 43, 15],
519
+
520
+ # 7
521
+ [2, 98, 78],
522
+ [4, 49, 31],
523
+ [2, 32, 14, 4, 33, 15],
524
+ [4, 39, 13, 1, 40, 14],
525
+
526
+ # 8
527
+ [2, 121, 97],
528
+ [2, 60, 38, 2, 61, 39],
529
+ [4, 40, 18, 2, 41, 19],
530
+ [4, 40, 14, 2, 41, 15],
531
+
532
+ # 9
533
+ [2, 146, 116],
534
+ [3, 58, 36, 2, 59, 37],
535
+ [4, 36, 16, 4, 37, 17],
536
+ [4, 36, 12, 4, 37, 13],
537
+
538
+ # 10
539
+ [2, 86, 68, 2, 87, 69],
540
+ [4, 69, 43, 1, 70, 44],
541
+ [6, 43, 19, 2, 44, 20],
542
+ [6, 43, 15, 2, 44, 16]
543
+
544
+ ]
545
+
546
+
547
+ def QRRSBlock.get_rs_blocks( type_no, error_correct_level )
548
+ rs_block = QRRSBlock.get_rs_block_table( type_no, error_correct_level )
549
+
550
+ if rs_block.nil?
551
+ raise QRCodeRunTimeError,
552
+ "bad rsblock @ typeno: #{type_no}/error_correct_level:#{error_correct_level}"
553
+ end
554
+
555
+ length = rs_block.size / 3
556
+ list = []
557
+
558
+ ( 0...length ).each do |i|
559
+ count = rs_block[i * 3 + 0]
560
+ total_count = rs_block[i * 3 + 1]
561
+ data_count = rs_block[i * 3 + 2]
562
+
563
+ ( 0...count ).each do |j|
564
+ list << QRRSBlock.new( total_count, data_count )
565
+ end
566
+ end
567
+
568
+ list
569
+ end
570
+
571
+
572
+ def QRRSBlock.get_rs_block_table( type_number, error_correct_level )
573
+ case error_correct_level
574
+ when QRERRORCORRECTLEVEL[:l]
575
+ QRRSBlock::RS_BLOCK_TABLE[(type_number - 1) * 4 + 0]
576
+ when QRERRORCORRECTLEVEL[:m]
577
+ QRRSBlock::RS_BLOCK_TABLE[(type_number - 1) * 4 + 1]
578
+ when QRERRORCORRECTLEVEL[:q]
579
+ QRRSBlock::RS_BLOCK_TABLE[(type_number - 1) * 4 + 2]
580
+ when QRERRORCORRECTLEVEL[:h]
581
+ QRRSBlock::RS_BLOCK_TABLE[(type_number - 1) * 4 + 3]
582
+ else
583
+ nil
584
+ end
585
+ end
586
+
587
+ end
588
+
589
+
590
+ class QRBitBuffer
591
+ attr_reader :buffer
592
+
593
+ def initialize
594
+ @buffer = []
595
+ @length = 0
596
+ end
597
+
598
+
599
+ def get( index )
600
+ buf_index = (index / 8).floor
601
+ (( (@buffer[buf_index]).rszf(7 - index % 8)) & 1) == 1
602
+ end
603
+
604
+
605
+ def put( num, length )
606
+ ( 0...length ).each do |i|
607
+ put_bit((((num).rszf(length - i - 1)) & 1) == 1)
608
+ end
609
+ end
610
+
611
+
612
+ def get_length_in_bits
613
+ @length
614
+ end
615
+
616
+
617
+ def put_bit( bit )
618
+ buf_index = ( @length / 8 ).floor
619
+ if @buffer.size <= buf_index
620
+ @buffer << 0
621
+ end
622
+
623
+ if bit
624
+ @buffer[buf_index] |= ((0x80).rszf(@length % 8))
625
+ end
626
+
627
+ @length += 1
628
+ end
629
+
630
+ end
631
+
632
+
633
+ class QRUtil
634
+
635
+ PATTERN_POSITION_TABLE = [
636
+
637
+ [],
638
+ [6, 18],
639
+ [6, 22],
640
+ [6, 26],
641
+ [6, 30],
642
+ [6, 34],
643
+ [6, 22, 38],
644
+ [6, 24, 42],
645
+ [6, 26, 46],
646
+ [6, 28, 50],
647
+ [6, 30, 54],
648
+ [6, 32, 58],
649
+ [6, 34, 62],
650
+ [6, 26, 46, 66],
651
+ [6, 26, 48, 70],
652
+ [6, 26, 50, 74],
653
+ [6, 30, 54, 78],
654
+ [6, 30, 56, 82],
655
+ [6, 30, 58, 86],
656
+ [6, 34, 62, 90],
657
+ [6, 28, 50, 72, 94],
658
+ [6, 26, 50, 74, 98],
659
+ [6, 30, 54, 78, 102],
660
+ [6, 28, 54, 80, 106],
661
+ [6, 32, 58, 84, 110],
662
+ [6, 30, 58, 86, 114],
663
+ [6, 34, 62, 90, 118],
664
+ [6, 26, 50, 74, 98, 122],
665
+ [6, 30, 54, 78, 102, 126],
666
+ [6, 26, 52, 78, 104, 130],
667
+ [6, 30, 56, 82, 108, 134],
668
+ [6, 34, 60, 86, 112, 138],
669
+ [6, 30, 58, 86, 114, 142],
670
+ [6, 34, 62, 90, 118, 146],
671
+ [6, 30, 54, 78, 102, 126, 150],
672
+ [6, 24, 50, 76, 102, 128, 154],
673
+ [6, 28, 54, 80, 106, 132, 158],
674
+ [6, 32, 58, 84, 110, 136, 162],
675
+ [6, 26, 54, 82, 110, 138, 166],
676
+ [6, 30, 58, 86, 114, 142, 170]
677
+ ]
678
+
679
+ G15 = 1 << 10 | 1 << 8 | 1 << 5 | 1 << 4 | 1 << 2 | 1 << 1 | 1 << 0
680
+ G18 = 1 << 12 | 1 << 11 | 1 << 10 | 1 << 9 | 1 << 8 | 1 << 5 | 1 << 2 | 1 << 0
681
+ G15_MASK = 1 << 14 | 1 << 12 | 1 << 10 | 1 << 4 | 1 << 1
682
+
683
+
684
+ def QRUtil.get_bch_type_info( data )
685
+ d = data << 10
686
+ while QRUtil.get_bch_digit(d) - QRUtil.get_bch_digit(G15) >= 0
687
+ d ^= (G15 << (QRUtil.get_bch_digit(d) - QRUtil.get_bch_digit(G15)))
688
+ end
689
+ (( data << 10 ) | d) ^ G15_MASK
690
+ end
691
+
692
+
693
+ def QRUtil.get_bch_type_number( data )
694
+ d = data << 12
695
+ while QRUtil.get_bch_digit(d) - QRUtil.get_bch_digit(G18) >= 0
696
+ d ^= (G18 << (QRUtil.get_bch_digit(d) - QRUtil.get_bch_digit(G18)))
697
+ end
698
+ ( data << 12 ) | d
699
+ end
700
+
701
+
702
+ def QRUtil.get_bch_digit( data )
703
+ digit = 0
704
+
705
+ while data != 0
706
+ digit = digit + 1
707
+ data = (data).rszf(1)
708
+ end
709
+
710
+ digit
711
+ end
712
+
713
+
714
+ def QRUtil.get_pattern_position( type_number )
715
+ PATTERN_POSITION_TABLE[ type_number - 1 ]
716
+ end
717
+
718
+
719
+ def QRUtil.get_mask( mask_pattern, i, j )
720
+ case mask_pattern
721
+ when QRMASKPATTERN[:pattern000]
722
+ (i + j) % 2 == 0
723
+ when QRMASKPATTERN[:pattern001]
724
+ i % 2 == 0
725
+ when QRMASKPATTERN[:pattern010]
726
+ j % 3 == 0
727
+ when QRMASKPATTERN[:pattern011]
728
+ (i + j) % 3 == 0
729
+ when QRMASKPATTERN[:pattern100]
730
+ ((i / 2).floor + (j / 3).floor ) % 2 == 0
731
+ when QRMASKPATTERN[:pattern101]
732
+ (i * j) % 2 + (i * j) % 3 == 0
733
+ when QRMASKPATTERN[:pattern110]
734
+ ( (i * j) % 2 + (i * j) % 3) % 2 == 0
735
+ when QRMASKPATTERN[:pattern111]
736
+ ( (i * j) % 3 + (i + j) % 2) % 2 == 0
737
+ else
738
+ raise QRCodeRunTimeError, "bad mask_pattern: #{mask_pattern}"
739
+ end
740
+ end
741
+
742
+
743
+ def QRUtil.get_error_correct_polynomial( error_correct_length )
744
+ a = QRPolynomial.new( [1], 0 )
745
+
746
+ ( 0...error_correct_length ).each do |i|
747
+ a = a.multiply( QRPolynomial.new( [1, QRMath.gexp(i)], 0 ) )
748
+ end
749
+
750
+ a
751
+ end
752
+
753
+
754
+ def QRUtil.get_length_in_bits( mode, type )
755
+ if 1 <= type && type < 10
756
+
757
+ # 1 - 9
758
+ case mode
759
+ when QRMODE[:mode_number] : 10
760
+ when QRMODE[:mode_alpha_num] : 9
761
+ when QRMODE[:mode_8bit_byte] : 8
762
+ when QRMODE[:mode_kanji] : 8
763
+ else
764
+ raise QRCodeRunTimeError, "mode: #{mode}"
765
+ end
766
+
767
+ elsif type < 27
768
+
769
+ # 10 -26
770
+ case mode
771
+ when QRMODE[:mode_number] : 12
772
+ when QRMODE[:mode_alpha_num] : 11
773
+ when QRMODE[:mode_8bit_byte] : 16
774
+ when QRMODE[:mode_kanji] : 10
775
+ else
776
+ raise QRCodeRunTimeError, "mode: #{mode}"
777
+ end
778
+
779
+ elsif type < 41
780
+
781
+ # 27 - 40
782
+ case mode
783
+ when QRMODE[:mode_number] : 14
784
+ when QRMODE[:mode_alpha_num] : 13
785
+ when QRMODE[:mode_8bit_byte] : 16
786
+ when QRMODE[:mode_kanji] : 12
787
+ else
788
+ raise QRCodeRunTimeError, "mode: #{mode}"
789
+ end
790
+
791
+ else
792
+ raise QRCodeRunTimeError, "type: #{type}"
793
+ end
794
+ end
795
+
796
+
797
+ def QRUtil.get_lost_point( qr_code )
798
+ module_count = qr_code.module_count
799
+ lost_point = 0
800
+
801
+ # level1
802
+ ( 0...module_count ).each do |row|
803
+ ( 0...module_count ).each do |col|
804
+ same_count = 0
805
+ dark = qr_code.is_dark( row, col )
806
+
807
+ ( -1..1 ).each do |r|
808
+ next if row + r < 0 || module_count <= row + r
809
+
810
+ ( -1..1 ).each do |c|
811
+ next if col + c < 0 || module_count <= col + c
812
+ next if r == 0 && c == 0
813
+ if dark == qr_code.is_dark( row + r, col + c )
814
+ same_count += 1
815
+ end
816
+ end
817
+ end
818
+
819
+ if same_count > 5
820
+ lost_point += (3 + same_count - 5)
821
+ end
822
+ end
823
+ end
824
+
825
+ # level 2
826
+ ( 0...( module_count - 1 ) ).each do |row|
827
+ ( 0...( module_count - 1 ) ).each do |col|
828
+ count = 0
829
+ count = count + 1 if qr_code.is_dark( row, col )
830
+ count = count + 1 if qr_code.is_dark( row + 1, col )
831
+ count = count + 1 if qr_code.is_dark( row, col + 1 )
832
+ count = count + 1 if qr_code.is_dark( row + 1, col + 1 )
833
+ lost_point = lost_point + 3 if (count == 0 || count == 4)
834
+ end
835
+ end
836
+
837
+ # level 3
838
+ ( 0...module_count ).each do |row|
839
+ ( 0...( module_count - 6 ) ).each do |col|
840
+ 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 )
841
+ lost_point = lost_point + 40
842
+ end
843
+ end
844
+ end
845
+
846
+ ( 0...module_count ).each do |col|
847
+ ( 0...( module_count - 6 ) ).each do |row|
848
+ 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)
849
+ lost_point = lost_point + 40
850
+ end
851
+ end
852
+ end
853
+
854
+ # level 4
855
+ dark_count = 0
856
+
857
+ ( 0...module_count ).each do |col|
858
+ ( 0...module_count ).each do |row|
859
+ if qr_code.is_dark(row, col)
860
+ dark_count = dark_count + 1
861
+ end
862
+ end
863
+ end
864
+
865
+ ratio = (100 * dark_count / module_count / module_count - 50).abs / 5
866
+ lost_point = lost_point * 10
867
+
868
+ lost_point
869
+ end
870
+
871
+ end
872
+
873
+
874
+ class QRMath
875
+
876
+ module_eval {
877
+ exp_table = Array.new(256)
878
+ log_table = Array.new(256)
879
+
880
+ ( 0...8 ).each do |i|
881
+ exp_table[i] = 1 << i
882
+ end
883
+
884
+ ( 8...256 ).each do |i|
885
+ exp_table[i] = exp_table[i - 4] \
886
+ ^ exp_table[i - 5] \
887
+ ^ exp_table[i - 6] \
888
+ ^ exp_table[i - 8]
889
+ end
890
+
891
+ ( 0...255 ).each do |i|
892
+ log_table[exp_table[i] ] = i
893
+ end
894
+
895
+ EXP_TABLE = exp_table
896
+ LOG_TABLE = log_table
897
+ }
898
+
899
+ class << self
900
+
901
+ def glog(n)
902
+ raise QRCodeRunTimeError, "glog(#{n})" if ( n < 1 )
903
+ LOG_TABLE[n]
904
+ end
905
+
906
+
907
+ def gexp(n)
908
+ while n < 0
909
+ n = n + 255
910
+ end
911
+
912
+ while n >= 256
913
+ n = n - 255
914
+ end
915
+
916
+ EXP_TABLE[n]
917
+ end
918
+
919
+ end
920
+
921
+ end
922
+
923
+
924
+ end