Class: RQRCodeCore::QRCode

Inherits:
Object
  • Object
show all
Extended by:
Gem::Deprecate
Defined in:
lib/rqrcode_core/qrcode/qr_code.rb

Overview

Creation

QRCode objects expect only one required constructor parameter and an optional hash of any other. Here’s a few examples:

qr = RQRCodeCore::QRCode.new('hello world')
qr = RQRCodeCore::QRCode.new('hello world', size: 1, level: :m, mode: :alphanumeric)

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(string, *args) ⇒ QRCode

Expects a string to be parsed in, other args are optional

# string - the string you wish to encode
# size   - the size (Integer) of the qrcode (defaults to smallest size needed to encode the string)
# level  - the error correction level, can be:
   * Level :l 7%  of code can be restored
   * Level :m 15% of code can be restored
   * Level :q 25% of code can be restored
   * Level :h 30% of code can be restored (default :h)
# mode   - the mode of the qrcode (defaults to alphanumeric or byte_8bit, depending on the input data):
   * :number
   * :alphanumeric
   * :byte_8bit
   * :kanji

qr = RQRCodeCore::QRCode.new('hello world', size: 1, level: :m, mode: :alphanumeric)


173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
# File 'lib/rqrcode_core/qrcode/qr_code.rb', line 173

def initialize(string, *args)
  if !string.is_a? String
    raise QRCodeArgumentError, "The passed data is #{string.class}, not String"
  end

  options = extract_options!(args)
  level = (options[:level] || :h).to_sym

  if !QRERRORCORRECTLEVEL.has_key?(level)
    raise QRCodeArgumentError, "Unknown error correction level `#{level.inspect}`"
  end

  @data = string

  mode = QRMODE_NAME[(options[:mode] || "").to_sym]
  # If mode is not explicitely given choose mode according to data type
  mode ||= if RQRCodeCore::QRNumeric.valid_data?(@data)
    QRMODE_NAME[:number]
  elsif QRAlphanumeric.valid_data?(@data)
    QRMODE_NAME[:alphanumeric]
  else
    QRMODE_NAME[:byte_8bit]
  end

  max_size_array = QRMAXDIGITS[level][mode]
  size = options[:size] || smallest_size_for(string, max_size_array)

  if size > QRUtil.max_size
    raise QRCodeArgumentError, "Given size greater than maximum possible size of #{QRUtil.max_size}"
  end

  @error_correct_level = QRERRORCORRECTLEVEL[level]
  @version = size
  @module_count = @version * 4 + QRPOSITIONPATTERNLENGTH
  @modules = Array.new(@module_count)
  @data_list =
    case mode
    when :mode_number
      QRNumeric.new(@data)
    when :mode_alpha_numk
      QRAlphanumeric.new(@data)
    else
      QR8bitByte.new(@data)
    end

  @data_cache = nil
  make
end

Instance Attribute Details

#module_countObject (readonly)

Returns the value of attribute module_count.



153
154
155
# File 'lib/rqrcode_core/qrcode/qr_code.rb', line 153

def module_count
  @module_count
end

#modulesObject (readonly)

Returns the value of attribute modules.



153
154
155
# File 'lib/rqrcode_core/qrcode/qr_code.rb', line 153

def modules
  @modules
end

#versionObject (readonly)

Returns the value of attribute version.



153
154
155
# File 'lib/rqrcode_core/qrcode/qr_code.rb', line 153

def version
  @version
end

Class Method Details

.count_max_data_bits(rs_blocks) ⇒ Object



493
494
495
496
497
498
499
# File 'lib/rqrcode_core/qrcode/qr_code.rb', line 493

def count_max_data_bits(rs_blocks)
  max_data_bytes = rs_blocks.reduce(0) do |sum, rs_block|
    sum + rs_block.data_count
  end

  max_data_bytes * 8
end

.create_bytes(buffer, rs_blocks) ⇒ Object

:nodoc:



518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
# File 'lib/rqrcode_core/qrcode/qr_code.rb', line 518

def create_bytes(buffer, rs_blocks) #:nodoc:
  offset = 0
  max_dc_count = 0
  max_ec_count = 0
  dcdata = Array.new(rs_blocks.size)
  ecdata = Array.new(rs_blocks.size)

  rs_blocks.each_with_index do |rs_block, r|
    dc_count = rs_block.data_count
    ec_count = rs_block.total_count - dc_count
    max_dc_count = [max_dc_count, dc_count].max
    max_ec_count = [max_ec_count, ec_count].max

    dcdata_block = Array.new(dc_count)
    dcdata_block.size.times do |i|
      dcdata_block[i] = 0xff & buffer.buffer[i + offset]
    end
    dcdata[r] = dcdata_block

    offset += dc_count
    rs_poly = QRUtil.get_error_correct_polynomial(ec_count)
    raw_poly = QRPolynomial.new(dcdata[r], rs_poly.get_length - 1)
    mod_poly = raw_poly.mod(rs_poly)

    ecdata_block = Array.new(rs_poly.get_length - 1)
    ecdata_block.size.times do |i|
      mod_index = i + mod_poly.get_length - ecdata_block.size
      ecdata_block[i] = mod_index >= 0 ? mod_poly.get(mod_index) : 0
    end
    ecdata[r] = ecdata_block
  end

  total_code_count = rs_blocks.reduce(0) do |sum, rs_block|
    sum + rs_block.total_count
  end

  data = Array.new(total_code_count)
  index = 0

  max_dc_count.times do |i|
    rs_blocks.size.times do |r|
      if i < dcdata[r].size
        data[index] = dcdata[r][i]
        index += 1
      end
    end
  end

  max_ec_count.times do |i|
    rs_blocks.size.times do |r|
      if i < ecdata[r].size
        data[index] = ecdata[r][i]
        index += 1
      end
    end
  end

  data
end

.create_data(version, error_correct_level, data_list) ⇒ Object

:nodoc:



501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
# File 'lib/rqrcode_core/qrcode/qr_code.rb', line 501

def create_data(version, error_correct_level, data_list) #:nodoc:
  rs_blocks = QRRSBlock.get_rs_blocks(version, error_correct_level)
  max_data_bits = QRCode.count_max_data_bits(rs_blocks)
  buffer = QRBitBuffer.new(version)

  data_list.write(buffer)
  buffer.end_of_message(max_data_bits)

  if buffer.get_length_in_bits > max_data_bits
    raise QRCodeRunTimeError, "code length overflow. (#{buffer.get_length_in_bits}>#{max_data_bits}). (Try a larger size!)"
  end

  buffer.pad_until(max_data_bits)

  QRCode.create_bytes(buffer, rs_blocks)
end

Instance Method Details

#checked?(row, col) ⇒ Boolean Also known as: dark?

checked? is called with a col and row parameter. This will return true or false based on whether that coordinate exists in the matrix returned. It would normally be called while iterating through modules. A simple example would be:

instance.checked?( 10, 10 ) => true

Returns:

  • (Boolean)


230
231
232
233
234
235
# File 'lib/rqrcode_core/qrcode/qr_code.rb', line 230

def checked?(row, col)
  if !row.between?(0, @module_count - 1) || !col.between?(0, @module_count - 1)
    raise QRCodeRunTimeError, "Invalid row/column pair: #{row}, #{col}"
  end
  @modules[row][col]
end

#error_correction_levelObject

Return a symbol for current error connection level



292
293
294
# File 'lib/rqrcode_core/qrcode/qr_code.rb', line 292

def error_correction_level
  QRERRORCORRECTLEVEL.invert[@error_correct_level]
end

#inspectObject

Public overide as default inspect is very verbose

RQRCodeCore::QRCode.new('my string to generate', size: 4, level: :h)
=> QRCodeCore: @data='my string to generate', @error_correct_level=2, @version=4, @module_count=33


287
288
289
# File 'lib/rqrcode_core/qrcode/qr_code.rb', line 287

def inspect
  "QRCodeCore: @data='#{@data}', @error_correct_level=#{@error_correct_level}, @version=#{@version}, @module_count=#{@module_count}"
end

#modeObject

Return a symbol in QRMODE.keys for current mode used



297
298
299
300
301
302
303
304
305
306
# File 'lib/rqrcode_core/qrcode/qr_code.rb', line 297

def mode
  case @data_list
  when QRNumeric
    :mode_number
  when QRAlphanumeric
    :mode_alpha_numk
  else
    :mode_8bit_byte
  end
end

#to_s(*args) ⇒ Object

This is a public method that returns the QR Code you have generated as a string. It will not be able to be read in this format by a QR Code reader, but will give you an idea if the final outout. It takes two optional args :dark and :light which are there for you to choose how the output looks. Here’s an example of it’s use:

instance.to_s =>
xxxxxxx x  x x   x x  xx  xxxxxxx
x     x  xxx  xxxxxx xxx  x     x
x xxx x  xxxxx x       xx x xxx x

instance.to_s( dark: 'E', light: 'Q' ) =>
EEEEEEEQEQQEQEQQQEQEQQEEQQEEEEEEE
EQQQQQEQQEEEQQEEEEEEQEEEQQEQQQQQE
EQEEEQEQQEEEEEQEQQQQQQQEEQEQEEEQE


258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
# File 'lib/rqrcode_core/qrcode/qr_code.rb', line 258

def to_s(*args)
  options = extract_options!(args)
  dark = options[:dark] || "x"
  light = options[:light] || " "
  quiet_zone_size = options[:quiet_zone_size] || 0

  rows = []

  @modules.each do |row|
    cols = light * quiet_zone_size
    row.each do |col|
      cols += (col ? dark : light)
    end
    rows << cols
  end

  quiet_zone_size.times do
    rows.unshift(light * (rows.first.length / light.size))
    rows << light * (rows.first.length / light.size)
  end
  rows.join("\n")
end