rqrcode 0.1.0 → 0.2.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,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