rqrcode 0.8.2 → 1.0.1

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.
Files changed (46) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/ruby.yml +20 -0
  3. data/.gitignore +9 -1
  4. data/Gemfile +3 -8
  5. data/LICENSE.txt +21 -0
  6. data/README.md +121 -123
  7. data/Rakefile +6 -10
  8. data/_config.yml +1 -0
  9. data/bin/console +14 -0
  10. data/bin/setup +8 -0
  11. data/images/ansi-screen-shot.png +0 -0
  12. data/images/github-qrcode.png +0 -0
  13. data/images/github-qrcode.svg +32 -0
  14. data/lib/rqrcode.rb +7 -15
  15. data/{test/helper.rb → lib/rqrcode/export.rb} +3 -6
  16. data/lib/rqrcode/export/ansi.rb +77 -0
  17. data/lib/rqrcode/export/html.rb +6 -8
  18. data/lib/rqrcode/export/png.rb +18 -19
  19. data/lib/rqrcode/export/svg.rb +16 -7
  20. data/lib/rqrcode/qrcode.rb +3 -4
  21. data/lib/rqrcode/qrcode/qrcode.rb +17 -0
  22. data/lib/rqrcode/version.rb +3 -1
  23. data/rqrcode.gemspec +28 -24
  24. metadata +62 -55
  25. data/.travis.yml +0 -7
  26. data/CHANGELOG +0 -84
  27. data/LICENSE +0 -19
  28. data/TODO.md +0 -4
  29. data/lib/rqrcode/core_ext.rb +0 -5
  30. data/lib/rqrcode/core_ext/array.rb +0 -5
  31. data/lib/rqrcode/core_ext/array/behavior.rb +0 -12
  32. data/lib/rqrcode/core_ext/integer.rb +0 -5
  33. data/lib/rqrcode/core_ext/integer/bitwise.rb +0 -13
  34. data/lib/rqrcode/qrcode/qr_8bit_byte.rb +0 -36
  35. data/lib/rqrcode/qrcode/qr_alphanumeric.rb +0 -47
  36. data/lib/rqrcode/qrcode/qr_bit_buffer.rb +0 -99
  37. data/lib/rqrcode/qrcode/qr_code.rb +0 -492
  38. data/lib/rqrcode/qrcode/qr_math.rb +0 -63
  39. data/lib/rqrcode/qrcode/qr_numeric.rb +0 -66
  40. data/lib/rqrcode/qrcode/qr_polynomial.rb +0 -78
  41. data/lib/rqrcode/qrcode/qr_rs_block.rb +0 -314
  42. data/lib/rqrcode/qrcode/qr_util.rb +0 -272
  43. data/test/data.rb +0 -23
  44. data/test/test_regresions.rb +0 -10
  45. data/test/test_rqrcode.rb +0 -125
  46. data/test/test_rqrcode_export.rb +0 -23
@@ -1,492 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- #--
4
- # Copyright 2008 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_numk => 1 << 1,
17
- :mode_8bit_byte => 1 << 2,
18
- :mode_kanji => 1 << 3
19
- }
20
-
21
- QRMODE_NAME = {
22
- :number => :mode_number,
23
- :alphanumeric => :mode_alpha_numk,
24
- :byte_8bit => :mode_8bit_byte
25
- }
26
-
27
- QRERRORCORRECTLEVEL = {
28
- :l => 1,
29
- :m => 0,
30
- :q => 3,
31
- :h => 2
32
- }
33
-
34
- QRMASKPATTERN = {
35
- :pattern000 => 0,
36
- :pattern001 => 1,
37
- :pattern010 => 2,
38
- :pattern011 => 3,
39
- :pattern100 => 4,
40
- :pattern101 => 5,
41
- :pattern110 => 6,
42
- :pattern111 => 7
43
- }
44
-
45
- QRMASKCOMPUTATIONS = [
46
- Proc.new { |i,j| (i + j) % 2 == 0 },
47
- Proc.new { |i,j| i % 2 == 0 },
48
- Proc.new { |i,j| j % 3 == 0 },
49
- Proc.new { |i,j| (i + j) % 3 == 0 },
50
- Proc.new { |i,j| ((i / 2).floor + (j / 3).floor) % 2 == 0 },
51
- Proc.new { |i,j| (i * j) % 2 + (i * j) % 3 == 0 },
52
- Proc.new { |i,j| ((i * j) % 2 + (i * j) % 3) % 2 == 0 },
53
- Proc.new { |i,j| ((i * j) % 3 + (i + j) % 2) % 2 == 0 },
54
- ]
55
-
56
-
57
-
58
- QRPOSITIONPATTERNLENGTH = (7 + 1) * 2 + 1
59
- QRFORMATINFOLENGTH = 15
60
-
61
- #http://web.archive.org/web/20110710094955/http://www.denso-wave.com/qrcode/vertable1-e.html
62
- QRMAXDIGITS = {
63
- :l => {:mode_number => [41, 77, 127, 187, 255, 322, 370, 461, 552, 652],
64
- :mode_alpha_numk => [25, 47, 77, 114, 154, 195, 224, 279, 335, 395],
65
- :mode_8bit_byte => [17, 32, 53, 78, 106, 134, 154, 192, 230, 271, 321, 367, 425, 458, 520, 586, 644, 718, 792, 858],
66
- :mode_kanji => [10, 20, 32, 48, 65, 82, 95, 118, 141, 167]},
67
- :m => {:mode_number => [34, 63, 101, 149, 202, 255, 293, 365, 432, 513],
68
- :mode_alpha_numk => [20, 38, 61, 90, 122, 154, 178, 221, 262, 311],
69
- :mode_8bit_byte => [14, 26, 42, 62, 84, 106, 122, 152, 180, 213, 251, 287, 331, 362, 412, 450, 504, 560, 624, 666],
70
- :mode_kanji => [ 8, 16, 26, 38, 54, 65, 75, 93, 111, 131]},
71
- :q => {:mode_number => [27, 48, 77, 111, 144, 178, 207, 259, 312, 364],
72
- :mode_alpha_numk => [16, 29, 47, 67, 87, 108, 125, 157, 189, 221],
73
- :mode_8bit_byte => [11, 20, 32, 46, 60, 74, 86, 108, 130, 151, 177, 203, 241, 258, 292, 22, 364, 394, 442, 482],
74
- :mode_kanji => [ 7, 12, 20, 28, 37, 45, 53, 66, 80, 93]},
75
- :h => {:mode_number => [17, 34, 58, 82, 106, 139, 154, 202, 235, 288],
76
- :mode_alpha_numk => [10, 20, 35, 50, 64, 84, 93, 122, 143, 174],
77
- :mode_8bit_byte => [ 7, 14, 24, 34, 44, 58, 64, 84, 98, 119, 137, 155, 177, 194, 220, 250, 280, 310, 338, 382],
78
- :mode_kanji => [ 4, 8, 15, 21, 27, 36, 39, 52, 60, 74]},
79
- }
80
-
81
-
82
- # StandardErrors
83
-
84
- class QRCodeArgumentError < ArgumentError; end
85
- class QRCodeRunTimeError < RuntimeError; end
86
-
87
- # == Creation
88
- #
89
- # QRCode objects expect only one required constructor parameter
90
- # and an optional hash of any other. Here's a few examples:
91
- #
92
- # qr = RQRCode::QRCode.new('hello world')
93
- # qr = RQRCode::QRCode.new('hello world', :size => 1, :level => :m, :mode => :alphanumeric )
94
- #
95
-
96
- class QRCode
97
- attr_reader :modules, :module_count, :version, :error_correction_level
98
-
99
- # Expects a string to be parsed in, other args are optional
100
- #
101
- # # string - the string you wish to encode
102
- # # size - the size of the qrcode (default 4)
103
- # # level - the error correction level, can be:
104
- # * Level :l 7% of code can be restored
105
- # * Level :m 15% of code can be restored
106
- # * Level :q 25% of code can be restored
107
- # * Level :h 30% of code can be restored (default :h)
108
- # # mode - the mode of the qrcode (defaults to alphanumeric or byte_8bit, depending on the input data):
109
- # * :number
110
- # * :alphanumeric
111
- # * :byte_8bit
112
- # * :kanji
113
- #
114
- # qr = RQRCode::QRCode.new('hello world', :size => 1, :level => :m, :mode => :alphanumeric )
115
- #
116
-
117
- def initialize( string, *args )
118
- if !string.is_a? String
119
- raise QRCodeArgumentError, "The passed data is #{string.class}, not String"
120
- end
121
-
122
- options = args.extract_options!
123
- level = (options[:level] || :h).to_sym
124
-
125
- if !QRERRORCORRECTLEVEL.has_key?(level)
126
- raise QRCodeArgumentError, "Unknown error correction level `#{level.inspect}`"
127
- end
128
-
129
- @data = string
130
-
131
- mode = QRMODE_NAME[(options[:mode] || '').to_sym]
132
- mode ||= QRAlphanumeric.valid_data?( @data ) ? :mode_alpha_numk : :mode_8bit_byte # deprecate?
133
-
134
- max_size_array = QRMAXDIGITS[level][mode]
135
- size = options[:size] || smallest_size_for(string, max_size_array)
136
-
137
- if size > QRUtil.max_size
138
- raise QRCodeArgumentError, "Given size greater than maximum possible size of #{QRUtil.max_size}"
139
- end
140
-
141
- @error_correct_level = QRERRORCORRECTLEVEL[level]
142
- @version = size
143
- @module_count = @version * 4 + QRPOSITIONPATTERNLENGTH
144
- @modules = Array.new( @module_count )
145
- @data_list =
146
- case mode
147
- when :mode_number
148
- QRNumeric.new( @data )
149
- when :mode_alpha_numk
150
- QRAlphanumeric.new( @data )
151
- else
152
- QR8bitByte.new( @data )
153
- end
154
-
155
- @data_cache = nil
156
- self.make
157
- end
158
-
159
- # <tt>is_dark</tt> is called with a +col+ and +row+ parameter. This will
160
- # return true or false based on whether that coordinate exists in the
161
- # matrix returned. It would normally be called while iterating through
162
- # <tt>modules</tt>. A simple example would be:
163
- #
164
- # instance.is_dark( 10, 10 ) => true
165
- #
166
-
167
- def is_dark( row, col )
168
- if !row.between?(0, @module_count - 1) || !col.between?(0, @module_count - 1)
169
- raise QRCodeRunTimeError, "Invalid row/column pair: #{row}, #{col}"
170
- end
171
- @modules[row][col]
172
- end
173
-
174
- alias dark? is_dark
175
-
176
- # This is a public method that returns the QR Code you have
177
- # generated as a string. It will not be able to be read
178
- # in this format by a QR Code reader, but will give you an
179
- # idea if the final outout. It takes two optional args
180
- # +:true+ and +:false+ which are there for you to choose
181
- # how the output looks. Here's an example of it's use:
182
- #
183
- # instance.to_s =>
184
- # xxxxxxx x x x x x xx xxxxxxx
185
- # x x xxx xxxxxx xxx x x
186
- # x xxx x xxxxx x xx x xxx x
187
- #
188
- # instance._to_s( :dark => 'E', :light => 'Q') =>
189
- # EEEEEEEQEQQEQEQQQEQEQQEEQQEEEEEEE
190
- # EQQQQQEQQEEEQQEEEEEEQEEEQQEQQQQQE
191
- # EQEEEQEQQEEEEEQEQQQQQQQEEQEQEEEQE
192
- #
193
- def to_s( *args )
194
- options = args.extract_options!
195
- dark = options[:dark] || options[:true] || 'x'
196
- light = options[:light] || options[:false] || ' '
197
- quiet_zone_size = options[:quiet_zone_size] || 0
198
-
199
- rows = []
200
-
201
- @modules.each do |row|
202
- cols = light * quiet_zone_size
203
- row.each do |col|
204
- cols += (col ? dark : light)
205
- end
206
- rows << cols
207
- end
208
-
209
- quiet_zone_size.times do
210
- rows.unshift(light * (rows.first.length / light.size))
211
- rows << light * (rows.first.length / light.size)
212
- end
213
- rows.join("\n")
214
- end
215
-
216
- protected
217
-
218
- def make #:nodoc:
219
- prepare_common_patterns
220
- make_impl( false, get_best_mask_pattern )
221
- end
222
-
223
- private
224
-
225
- def prepare_common_patterns
226
- @modules.map! { |row| Array.new(@module_count) }
227
-
228
- place_position_probe_pattern(0, 0)
229
- place_position_probe_pattern(@module_count - 7, 0)
230
- place_position_probe_pattern(0, @module_count - 7)
231
- place_position_adjust_pattern
232
- place_timing_pattern
233
-
234
- @common_patterns = @modules.map(&:clone)
235
- end
236
-
237
- def make_impl( test, mask_pattern ) #:nodoc:
238
- @modules = @common_patterns.map(&:clone)
239
-
240
- place_format_info(test, mask_pattern)
241
- place_version_info(test) if @version >= 7
242
-
243
- if @data_cache.nil?
244
- @data_cache = QRCode.create_data(
245
- @version, @error_correct_level, @data_list
246
- )
247
- end
248
-
249
- map_data( @data_cache, mask_pattern )
250
- end
251
-
252
-
253
- def place_position_probe_pattern( row, col ) #:nodoc:
254
- (-1..7).each do |r|
255
- next if !(row + r).between?(0, @module_count - 1)
256
-
257
- (-1..7).each do |c|
258
- next if !(col + c).between?(0, @module_count - 1)
259
-
260
- is_vert_line = (r.between?(0, 6) && (c == 0 || c == 6))
261
- is_horiz_line = (c.between?(0, 6) && (r == 0 || r == 6))
262
- is_square = r.between?(2,4) && c.between?(2, 4)
263
-
264
- is_part_of_probe = is_vert_line || is_horiz_line || is_square
265
- @modules[row + r][col + c] = is_part_of_probe
266
- end
267
- end
268
- end
269
-
270
-
271
- def get_best_mask_pattern #:nodoc:
272
- min_lost_point = 0
273
- pattern = 0
274
-
275
- ( 0...8 ).each do |i|
276
- make_impl( true, i )
277
- lost_point = QRUtil.get_lost_points(self.modules)
278
-
279
- if i == 0 || min_lost_point > lost_point
280
- min_lost_point = lost_point
281
- pattern = i
282
- end
283
- end
284
- pattern
285
- end
286
-
287
-
288
- def place_timing_pattern #:nodoc:
289
- ( 8...@module_count - 8 ).each do |i|
290
- @modules[i][6] = @modules[6][i] = i % 2 == 0
291
- end
292
- end
293
-
294
-
295
- def place_position_adjust_pattern #:nodoc:
296
- positions = QRUtil.get_pattern_positions(@version)
297
-
298
- positions.each do |row|
299
- positions.each do |col|
300
- next unless @modules[row][col].nil?
301
-
302
- ( -2..2 ).each do |r|
303
- ( -2..2 ).each do |c|
304
- is_part_of_pattern = (r.abs == 2 || c.abs == 2 || ( r == 0 && c == 0 ))
305
- @modules[row + r][col + c] = is_part_of_pattern
306
- end
307
- end
308
- end
309
- end
310
- end
311
-
312
-
313
- def place_version_info(test) #:nodoc:
314
- bits = QRUtil.get_bch_version(@version)
315
-
316
- ( 0...18 ).each do |i|
317
- mod = ( !test && ( (bits >> i) & 1) == 1 )
318
- @modules[ (i / 3).floor ][ i % 3 + @module_count - 8 - 3 ] = mod
319
- @modules[ i % 3 + @module_count - 8 - 3 ][ (i / 3).floor ] = mod
320
- end
321
- end
322
-
323
-
324
- def place_format_info(test, mask_pattern) #:nodoc:
325
- data = (@error_correct_level << 3 | mask_pattern)
326
- bits = QRUtil.get_bch_format_info(data)
327
-
328
- QRFORMATINFOLENGTH.times do |i|
329
- mod = (!test && ( (bits >> i) & 1) == 1)
330
-
331
- # vertical
332
- if i < 6
333
- row = i
334
- elsif i < 8
335
- row = i + 1
336
- else
337
- row = @module_count - 15 + i
338
- end
339
- @modules[row][8] = mod
340
-
341
- # horizontal
342
- if i < 8
343
- col = @module_count - i - 1
344
- elsif i < 9
345
- col = 15 - i - 1 + 1
346
- else
347
- col = 15 - i - 1
348
- end
349
- @modules[8][col] = mod
350
- end
351
-
352
- # fixed module
353
- @modules[ @module_count - 8 ][8] = !test
354
- end
355
-
356
-
357
- def map_data( data, mask_pattern ) #:nodoc:
358
- inc = -1
359
- row = @module_count - 1
360
- bit_index = 7
361
- byte_index = 0
362
-
363
- ( @module_count - 1 ).step( 1, -2 ) do |col|
364
- col = col - 1 if col <= 6
365
-
366
- while true do
367
- ( 0...2 ).each do |c|
368
-
369
- if @modules[row][ col - c ].nil?
370
- dark = false
371
- if byte_index < data.size && !data[byte_index].nil?
372
- dark = (( (data[byte_index]).rszf( bit_index ) & 1) == 1 )
373
- end
374
- mask = QRUtil.get_mask( mask_pattern, row, col - c )
375
- dark = !dark if mask
376
- @modules[row][ col - c ] = dark
377
- bit_index -= 1
378
-
379
- if bit_index == -1
380
- byte_index += 1
381
- bit_index = 7
382
- end
383
- end
384
- end
385
-
386
- row += inc
387
-
388
- if row < 0 || @module_count <= row
389
- row -= inc
390
- inc = -inc
391
- break
392
- end
393
- end
394
- end
395
- end
396
-
397
- def smallest_size_for(string, max_size_array) #:nodoc:
398
- l = string.bytesize
399
- ver = max_size_array.index{|i| i >= l}
400
- raise QRCodeRunTimeError,"code length overflow. (#{l} digits > any version capacity)" unless ver
401
- ver + 1
402
- end
403
-
404
- def QRCode.count_max_data_bits(rs_blocks)
405
- max_data_bytes = rs_blocks.reduce(0) do |sum, rs_block|
406
- sum + rs_block.data_count
407
- end
408
-
409
- return max_data_bytes * 8
410
- end
411
-
412
- def QRCode.create_data(version, error_correct_level, data_list) #:nodoc:
413
- rs_blocks = QRRSBlock.get_rs_blocks(version, error_correct_level)
414
- max_data_bits = QRCode.count_max_data_bits(rs_blocks)
415
- buffer = QRBitBuffer.new(version)
416
-
417
- data_list.write(buffer)
418
- buffer.end_of_message(max_data_bits)
419
-
420
- if buffer.get_length_in_bits > max_data_bits
421
- raise QRCodeRunTimeError, "code length overflow. (#{buffer.get_length_in_bits}>#{max_data_bits}). (Try a larger size!)"
422
- end
423
-
424
- buffer.pad_until(max_data_bits)
425
-
426
- QRCode.create_bytes( buffer, rs_blocks )
427
- end
428
-
429
-
430
- def QRCode.create_bytes( buffer, rs_blocks ) #:nodoc:
431
- offset = 0
432
- max_dc_count = 0
433
- max_ec_count = 0
434
- dcdata = Array.new( rs_blocks.size )
435
- ecdata = Array.new( rs_blocks.size )
436
-
437
- rs_blocks.each_with_index do |rs_block, r|
438
- dc_count = rs_block.data_count
439
- ec_count = rs_block.total_count - dc_count
440
- max_dc_count = [ max_dc_count, dc_count ].max
441
- max_ec_count = [ max_ec_count, ec_count ].max
442
-
443
- dcdata_block = Array.new(dc_count)
444
- dcdata_block.size.times do |i|
445
- dcdata_block[i] = 0xff & buffer.buffer[ i + offset ]
446
- end
447
- dcdata[r] = dcdata_block
448
-
449
- offset = offset + dc_count
450
- rs_poly = QRUtil.get_error_correct_polynomial( ec_count )
451
- raw_poly = QRPolynomial.new( dcdata[r], rs_poly.get_length - 1 )
452
- mod_poly = raw_poly.mod( rs_poly )
453
-
454
- ecdata_block = Array.new(rs_poly.get_length - 1)
455
- ecdata_block.size.times do |i|
456
- mod_index = i + mod_poly.get_length - ecdata_block.size
457
- ecdata_block[i] = mod_index >= 0 ? mod_poly.get( mod_index ) : 0
458
- end
459
- ecdata[r] = ecdata_block
460
- end
461
-
462
- total_code_count = rs_blocks.reduce(0) do |sum, rs_block|
463
- sum + rs_block.total_count
464
- end
465
-
466
- data = Array.new( total_code_count )
467
- index = 0
468
-
469
- max_dc_count.times do |i|
470
- rs_blocks.size.times do |r|
471
- if i < dcdata[r].size
472
- data[index] = dcdata[r][i]
473
- index += 1
474
- end
475
- end
476
- end
477
-
478
- max_ec_count.times do |i|
479
- rs_blocks.size.times do |r|
480
- if i < ecdata[r].size
481
- data[index] = ecdata[r][i]
482
- index += 1
483
- end
484
- end
485
- end
486
-
487
- data
488
- end
489
-
490
- end
491
-
492
- end