rqrcode 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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