class Qrio::QrMatrix
Constants
- ALIGNMENT_CENTERS
- BLOCK_STRUCTURE
- ERROR_CORRECTION_LEVEL
- FORMAT_MASK
- MODE
- WORD_WIDTHS
Public Class Methods
new(*args)
click to toggle source
Calls superclass method
Qrio::Matrix::new
# File lib/qrio/qr_matrix.rb, line 3 def initialize(*args) super @unmasked = false end
Public Instance Methods
block_count()
click to toggle source
# File lib/qrio/qr_matrix.rb, line 231 def block_count block_structure.inject(0){|sum, (blocks,data,ecc)| sum += blocks } end
block_structure()
click to toggle source
# File lib/qrio/qr_matrix.rb, line 235 def block_structure @block_structure ||= begin @short_blocks = [] @long_blocks = [] params = block_structure_params.dup @short_blocks = params.slice!(0,3) structure = [@short_blocks] unless params.empty? @long_blocks = @short_blocks.dup @long_blocks[0] = params[0] structure << @long_blocks end structure end end
data_or_correction?(x, y)
click to toggle source
# File lib/qrio/qr_matrix.rb, line 259 def data_or_correction?(x, y) ! in_finder_pattern?(x, y) && ! in_alignment_pattern?(x, y) && ! in_alignment_line?(x, y) end
draw_alignment_patterns()
click to toggle source
# File lib/qrio/qr_matrix.rb, line 282 def draw_alignment_patterns rows = ALIGNMENT_CENTERS[version - 1].dup cols = rows.dup cols.each do |cy| rows.each do |cx| unless in_finder_pattern?(cx, cy) ((cy - 2)...(cy + 2)).each do |y| ((cx - 2)...(cx + 2)).each do |x| self[x, y] = (cx - x).abs == 2 || (cy - y).abs == 2 || (x == cx && y == cy) end end end end end end
ecc_bytes_per_block()
click to toggle source
# File lib/qrio/qr_matrix.rb, line 255 def ecc_bytes_per_block block_structure.first.last end
error_correction_level()
click to toggle source
# File lib/qrio/qr_matrix.rb, line 125 def error_correction_level ERROR_CORRECTION_LEVEL[read_format[:error_correction]] end
in_alignment_line?(x, y)
click to toggle source
# File lib/qrio/qr_matrix.rb, line 301 def in_alignment_line?(x, y) (x == 6) || (y == 6) end
in_alignment_pattern?(x, y)
click to toggle source
# File lib/qrio/qr_matrix.rb, line 271 def in_alignment_pattern?(x, y) return false if version == 1 alignment_centers = ALIGNMENT_CENTERS[version - 1] cy = alignment_centers.detect{|c| (c - y).abs <= 2 } cx = alignment_centers.detect{|c| (c - x).abs <= 2 } cx && cy && ! in_finder_pattern?(cx, cy) end
in_finder_pattern?(x, y)
click to toggle source
# File lib/qrio/qr_matrix.rb, line 265 def in_finder_pattern?(x, y) (x < 9 && y < 9) || (x > (width - 9) && y < 9) || (x < 9 && y > (height - 9)) end
mask_pattern()
click to toggle source
# File lib/qrio/qr_matrix.rb, line 129 def mask_pattern read_format[:mask_pattern] end
mode()
click to toggle source
# File lib/qrio/qr_matrix.rb, line 216 def mode MODE[@mode] end
raw_bytes()
click to toggle source
raw bytestream, as read from the QR symbol
# File lib/qrio/qr_matrix.rb, line 163 def raw_bytes @raw_bytes ||= read_raw_bytes end
text()
click to toggle source
# File lib/qrio/qr_matrix.rb, line 179 def text @text ||= begin text = [] unmask unless @unmasked # deinterlace @blocks = [] byte_pointer = 0 # TODO : handle ragged block sizes block_structure.each do |count, data, ecc| data.times do |word_index| block_count.times do |blk_index| @blocks[blk_index] ||= [] @blocks[blk_index] << raw_bytes[byte_pointer] byte_pointer += 1 end end end @blocks = @blocks.flatten set_mode character_count = read character_count.times do |idx| byte = read text << byte.chr end text.join end end
to_s()
click to toggle source
# File lib/qrio/qr_matrix.rb, line 167 def to_s str = "" rows.each do |row| row.each do |m| str << (m ? '#' : ' ') end str << "\n" end str end
unmask()
click to toggle source
# File lib/qrio/qr_matrix.rb, line 137 def unmask p = [ lambda{|x,y| (x + y) % 2 == 0 }, lambda{|x,y| x % 2 == 0 }, lambda{|x,y| y % 3 == 0 }, lambda{|x,y| (x + y) % 3 == 0 }, lambda{|x,y| ((x / 2) + (y / 3)) % 2 == 0 }, lambda{|x,y| prod = x * y; (prod % 2) + (prod % 3) == 0 }, lambda{|x,y| prod = x * y; (((prod % 2) + (prod % 3)) % 2) == 0 }, lambda{|x,y| prod = x * y; sum = x + y; (((prod % 3) + (sum % 2)) % 2) == 0 } ][mask_pattern] raise "could not load mask pattern #{ mask_pattern }" unless p 0.upto(height - 1) do |y| 0.upto(width - 1) do |x| if data_or_correction?(x, y) self[x, y] = self[x, y] ^ p.call(x, y) end end end @unmasked = ! @unmasked end
version()
click to toggle source
# File lib/qrio/qr_matrix.rb, line 133 def version (width - 17) / 4 end
word_size()
click to toggle source
# File lib/qrio/qr_matrix.rb, line 220 def word_size @word_size ||= begin widths = WORD_WIDTHS[mode] version_width = widths.detect{|k,v| k.include? version } raise "Could not find word width" if version_width.nil? version_width.last end end
Private Instance Methods
add_bit(x, y)
click to toggle source
# File lib/qrio/qr_matrix.rb, line 358 def add_bit(x, y) if data_or_correction?(x, y) @byte.push self[x, y] if @byte.length == 8 @raw_bytes << @byte.map{|b| b ? '1' : '0' }.join.to_i(2) @byte = [] end end end
block_structure_params()
click to toggle source
# File lib/qrio/qr_matrix.rb, line 319 def block_structure_params BLOCK_STRUCTURE[version - 1][read_format[:error_correction]].dup end
read(bits=nil)
click to toggle source
read bits
bits from bitstream and return the binary
# File lib/qrio/qr_matrix.rb, line 324 def read(bits=nil) bits ||= word_size binary = [] bits.times do |i| block_index, bit_index = @pointer.divmod(8) data = @blocks[block_index] || 0 binary << (((data >> (7 - bit_index)) & 1) == 1) @pointer += 1 end binary.map{|b| b ? '1' : '0' }.join.to_i(2) end
read_format()
click to toggle source
# File lib/qrio/qr_matrix.rb, line 369 def read_format @format ||= begin bits = 0 0.upto(5) do |x| bits = bits << 1 bits += 1 if self[x, 8] end bits = bits << 1 bits += 1 if self[7, 8] bits = bits << 1 bits += 1 if self[8, 8] bits = bits << 1 bits += 1 if self[8, 7] 5.downto(0) do |y| bits = bits << 1 bits += 1 if self[8, y] end format_string = (bits ^ FORMAT_MASK).to_s(2).rjust(15, '0') # TODO check BCH error detection # TODO if too many errors, read alternate format blocks { :error_correction => format_string[0,2].to_i(2), :mask_pattern => format_string[2,3].to_i(2), :bch_error_detection => format_string[5..-1].to_i(2) } end end
read_raw_bytes()
click to toggle source
# File lib/qrio/qr_matrix.rb, line 338 def read_raw_bytes @raw_bytes = [] @byte = [] (0..(width - 3)).step(2) do |bcol| bcol = width - 1 - bcol scanning_up = ((bcol / 2) % 2) == 0 bcol -= 1 if bcol <= 6 (0..(height - 1)).each do |brow| brow = height - 1 - brow if scanning_up add_bit(bcol, brow) add_bit(bcol - 1, brow) end end @raw_bytes end
set_data_length()
click to toggle source
# File lib/qrio/qr_matrix.rb, line 315 def set_data_length @data_length ||= read end
set_mode()
click to toggle source
# File lib/qrio/qr_matrix.rb, line 307 def set_mode @mode ||= begin @pointer ||= 0 mode_number = read(4) end raise "Unknown mode #{ @mode }" unless mode end