class Qrio::SamplingGrid
Attributes
angles[R]
block_height[R]
block_width[R]
bottom_left[R]
bounds[R]
finder_patterns[R]
matrix[R]
orientation[R]
origin_corner[R]
provisional_version[R]
top_right[R]
Public Class Methods
new(matrix, finder_patterns)
click to toggle source
# File lib/qrio/sampling_grid.rb, line 8 def initialize(matrix, finder_patterns) @matrix = matrix @finder_patterns = finder_patterns @angles = [] find_origin_corner detect_orientation end
Public Instance Methods
build_finder_pattern_neighbors()
click to toggle source
# File lib/qrio/sampling_grid.rb, line 77 def build_finder_pattern_neighbors @finder_patterns.each do |source| @finder_patterns.each do |destination| next if source.center == destination.center @angles << Neighbor.new(source, destination) end end end
detect_orientation()
click to toggle source
which way is the QR rotated?
0) normal - shared finder patterns in top left 1) - shared finder patterns in top right 2) - shared finder patterns in bottom right 3) - shared finder patterns in bottom left
# File lib/qrio/sampling_grid.rb, line 48 def detect_orientation # TODO : handle multiple possible matches other_corners = non_origin_finder_patterns dc = other_corners.map(&:distance).inject(0){|s,d| s + d } / 2.0 threshold = dc / 2.0 other_corners = other_corners.map(&:destination) set_block_dimensions(@origin_corner, *other_corners) @provisional_version = ((dc / @block_width).round - 10) / 4 xs = other_corners.map{|fp| fp.center.first } ys = other_corners.map{|fp| fp.center.last } above = ys.select{|y| y < (@origin_corner.center.last - threshold) } left = xs.select{|x| x < (@origin_corner.center.first - threshold) } @orientation = if above.any? left.any? ? 2 : 3 else left.any? ? 1 : 0 end end
extracted_pixels() { |round, round| ... }
click to toggle source
# File lib/qrio/sampling_grid.rb, line 128 def extracted_pixels start_x = @origin_corner.center.first - (@block_width * 3.0) start_y = @origin_corner.center.last - (@block_height * 3.0) dest_x = @bottom_left.center.first - (@block_width * 3.0) dest_y = @top_right.center.last - (@block_height * 3.0) # TODO : take bottom right alignment pattern into consideration dy = (dest_y - start_y) / logical_width dx = (dest_x - start_x) / logical_height logical_height.round.times do |row_index| row_start_x = start_x + row_index * dx row_start_y = start_y + (row_index * @block_height) logical_width.round.times do |col_index| x = row_start_x + (col_index * @block_width) y = row_start_y + (col_index * dy) yield x.round, y.round end end end
find_origin_corner(normalized=false)
click to toggle source
# File lib/qrio/sampling_grid.rb, line 17 def find_origin_corner(normalized=false) build_finder_pattern_neighbors shared_corners = @finder_patterns.select do |fp| fp.neighbors.select(&:right_angle?).count > 1 end # TODO : handle multiple possible matches if @origin_corner = shared_corners.first if normalized # we have correct orientation, identify fp positions @top_right = non_origin_finder_patterns.map(&:destination).detect{|fp| fp.center.last < @matrix.height / 2.0 } @bottom_left = non_origin_finder_patterns.map(&:destination).detect{|fp| fp.center.first < @matrix.width / 2.0 } else set_bounds end end end
logical_height()
click to toggle source
# File lib/qrio/sampling_grid.rb, line 95 def logical_height @matrix.height / @block_height end
logical_width()
click to toggle source
# File lib/qrio/sampling_grid.rb, line 91 def logical_width @matrix.width / @block_width end
non_origin_finder_patterns()
click to toggle source
# File lib/qrio/sampling_grid.rb, line 73 def non_origin_finder_patterns @origin_corner.neighbors.select(&:right_angle?)[0,2] end
normalize()
click to toggle source
# File lib/qrio/sampling_grid.rb, line 99 def normalize @matrix = @matrix.extract(*@bounds.to_point_size) translate(*@bounds.top_left) if @orientation > 0 (4 - @orientation).times do rotate end end find_origin_corner(true) end
rotate()
click to toggle source
# File lib/qrio/sampling_grid.rb, line 123 def rotate @matrix = @matrix.rotate @finder_patterns.map!{|f| f.rotate(@bounds.width, @bounds.height) } end
set_block_dimensions(*finder_patterns)
click to toggle source
# File lib/qrio/sampling_grid.rb, line 86 def set_block_dimensions(*finder_patterns) @block_width = finder_patterns.inject(0){|s,f| s + f.width } / 21.0 @block_height = finder_patterns.inject(0){|s,f| s + f.height } / 21.0 end
set_bounds()
click to toggle source
# File lib/qrio/sampling_grid.rb, line 36 def set_bounds @bounds = @origin_corner.dup @bounds.neighbors.select(&:right_angle?).each do |n| @bounds = @bounds.union(n.destination) end end
translate(x, y)
click to toggle source
# File lib/qrio/sampling_grid.rb, line 112 def translate(x, y) @angles = [] other_corners = non_origin_finder_patterns.map(&:destination) @origin_corner = @origin_corner.translate(x, y) translated = [@origin_corner] translated += other_corners.map{|c| c.translate(x, y) } @finder_patterns = translated end