Don't like ads? PRO users don't see any ads ;-)
Guest

Untitled

By: a guest on Sep 21st, 2012  |  syntax: None  |  size: 6.18 KB  |  hits: 11  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. require 'logger'
  2. require 'pp'
  3.  
  4. $log = Logger.new(STDOUT)
  5. $log.level = Logger::DEBUG
  6.  
  7. class Image
  8.   attr_accessor :width, :height, :pixels
  9.  
  10.   def initialize(width, height)
  11.     @width = width
  12.     @height = height
  13.     @pixels = Array.new(@width * @height)
  14.   end
  15.  
  16.   def getPixel(x, y)
  17.     @pixels[y * @width + x]
  18.   end
  19.  
  20.   def setPixel(x, y, color)
  21.     @pixels[y * @width + x] = color
  22.   end
  23.  
  24.   def setPixels(pixels)
  25.     @pixels = pixels
  26.   end
  27.  
  28.   def dump_pixels
  29.     result = "image#dump_pixels\n"
  30.     for y in 0...@height
  31.       line = []
  32.       format = ""
  33.       for x in 0...@width
  34.         line.push(@pixels[y * @width + x])
  35.         format += "%02s "
  36.       end
  37.       result += format % line + "\n"
  38.     end
  39.     result
  40.   end
  41. end
  42.  
  43. class Point
  44.   attr_accessor :x, :y
  45.  
  46.   def initialize(x, y)
  47.     @x = x
  48.     @y = y
  49.   end
  50. end
  51.  
  52. # scan line and fill algorithm
  53. # via http://www40.atwiki.jp/spellbound/pages/315.html
  54. module Painter
  55.   class << self
  56.     def fill(image, x, y, fill_color)
  57.       width = image.width
  58.       height = image.height
  59.       index = y * width + x
  60.       return if image.pixels[index] == fill_color
  61.  
  62.       color = image.pixels[index]
  63.       buffer = []
  64.       buffer.push(Point.new(x, y))
  65.  
  66.       while buffer.length > 0
  67.         point = buffer.shift()
  68.         next if image.pixels[point.y * width + point.x] == fill_color
  69.  
  70.         left = point.x
  71.         while 0 < left
  72.           break if image.pixels[point.y * width + left - 1] != color
  73.           left = left - 1
  74.         end
  75.         right = point.x
  76.         while right < width
  77.           break if image.pixels[point.y * width + right + 1] != color
  78.           right = right + 1
  79.         end
  80.  
  81.         # fill color
  82.         for x in left..right
  83.           image.pixels[point.y * width + x] = fill_color
  84.         end
  85.  
  86.         if point.y + 1 < height
  87.           scan_line(image, left, right, point.y + 1, color, buffer)
  88.         end
  89.         if 0 <= point.y - 1
  90.           scan_line(image, left, right, point.y - 1, color, buffer)
  91.         end
  92.       end
  93.     end
  94.  
  95.     private
  96.     def scan_line(image, left, right, y, color, buffer)
  97.       width = image.width
  98.       height = image.height
  99.       while left <= right
  100.         while left <= right
  101.           break if image.pixels[y * width + left] == color
  102.           left = left + 1
  103.         end
  104.         break if right < left
  105.         while left <= right
  106.           break if image.pixels[y * width + left] != color
  107.           left = left + 1
  108.         end
  109.         buffer.push(Point.new(left - 1, y))
  110.       end
  111.     end
  112.   end
  113. end
  114.  
  115. module Grouper
  116.   class << self
  117.     def analyze_image(image)
  118.       groups = grouping(image)
  119.       width = image.width
  120.       height = image.height
  121.       result = {}
  122.       for y in 0...height
  123.         for x in 0...width
  124.           index = y * width + x
  125.           group = image.pixels[index]
  126.           if result[group] == nil
  127.             result[group] = []
  128.           end
  129.           result[group].push([x,y])
  130.         end
  131.       end
  132.       result
  133.     end
  134.  
  135.     def grouping(image)
  136.       width = image.width
  137.       height = image.height
  138.       initial_groups = groups_in_image(image)
  139.       $log.debug initial_groups
  140.  
  141.       group_id = 'a'
  142.       x = 0
  143.       y = 0
  144.       dbg_step = 0
  145.       dbg_stop_step = 10
  146.       loop do
  147.         index = y * width + x
  148.         color = image.pixels[index]
  149.         $log.debug "----------------------------------------"
  150.         $log.debug "(#{x}:#{y}) = #{color}, #{group_id}"
  151.  
  152.         _dbg=<<DBG
  153.         $log.debug "[dbg_step:#{dbg_step}, dbg_stop_step:#{dbg_stop_step}]"
  154.         if dbg_step == dbg_stop_step
  155.           break
  156.         end
  157.         dbg_step = dbg_step + 1
  158.         #$log.debug image.dump_pixels
  159. DBG
  160.  
  161.         return if index >= width * height
  162.         groups = groups_in_image(image)
  163.         $log.debug groups
  164.         has_initial_groups = initial_groups.inject(false) {|r,ig| r || groups.include?(ig)}
  165.         $log.debug "# has_initial_groups = #{has_initial_groups}"
  166.         return groups_in_image(image) unless has_initial_groups
  167.         if has_initial_groups
  168.           is_initial_color = initial_groups.inject(false) {|r,ig| r || (ig == color)}
  169.           $log.debug "# is_initial_color = #{is_initial_color}"
  170.           if is_initial_color
  171.             $log.debug "# (#{x}, #{y}) #{group_id}"
  172.             Painter.fill(image, x, y, group_id)
  173.             $log.debug image.dump_pixels
  174.             #group_id.succ!
  175.             group_id = group_id.succ
  176.           end
  177.           if x < width
  178.             x = x + 1
  179.           else
  180.             if y < height
  181.               x = 0
  182.               y = y + 1
  183.             end
  184.           end
  185.         end
  186.       end
  187.     end
  188.  
  189.     private
  190.     def groups_in_image(image)
  191.       groups = []
  192.       for y in 0...image.height
  193.         for x in 0...image.width
  194.           color = image.pixels[y * image.width + x]
  195.           groups.push(color) unless groups.include? color
  196.         end
  197.       end
  198.       groups
  199.     end
  200.   end
  201. end
  202.  
  203.  
  204.  
  205. image = Image.new(11, 10)
  206. _test_data_a = [
  207.   -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1,
  208.   -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1,
  209.   -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1,
  210.   -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1,
  211.   -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1,
  212.   -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1,
  213.   -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1,
  214.   -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1,
  215.   -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1,
  216.   -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1,
  217. ]
  218. _test_data_b = [
  219.   -1, -1, -1, 1, 1, 1, 1, -1, 1, -1, -1,
  220.   -1, -1, -1, 1, 1, 1, 1, -1, 1, -1, -1,
  221.   -1, -1, -1, 1, 1, 1, 1, -1,-1, -1, -1,
  222.   -1, -1, -1, 1, 1, 1, 1,  1, 1, -1, -1,
  223.   -1, -1, -1, 1, 1, 1, 1,  1, 1, -1, -1,
  224.   -1, -1, -1, 1, 1, 1, 1,  1, 1, -1, -1,
  225.   -1, -1, -1, 1, 1, 1, 1,  1, 1, -1, -1,
  226.   -1,  1, -1, 1, 1, 1, 1,  1, 1, -1, -1,
  227.   -1,  1, -1, 1, 1, 1, 1,  1, 1, -1, -1,
  228.   -1,  1, -1, 1, 1, 1, 1,  1, 1, -1, -1,
  229. ]
  230. image.setPixels(_test_data_b)
  231.  
  232. puts "[initial data] ----------"
  233. puts image.dump_pixels
  234.  
  235. _fill_test =<<FILL_TEST
  236. puts "[result 1] ----------"
  237. Painter.fill(image, 0, 0, 'a')
  238. image.dump_pixels
  239.  
  240. #puts "[result 2] ----------"
  241. #Painter.fill(image, 5, 3, 'b')
  242. #image.dump_pixels
  243.  
  244. puts "[result 3] ----------"
  245. Painter.fill(image, 10, 8, 'c')
  246. image.dump_pixels
  247. FILL_TEST
  248.  
  249. puts "[result 1] ----------"
  250. #Painter.fill(image, 0, 0, 'a')
  251. #image.dump_pixels
  252. #Painter.fill(image, 3, 0, 'b')
  253. #image.dump_pixels
  254.  
  255. #groups = Grouper.grouping(image)
  256. #pp groups
  257.  
  258. result = Grouper.analyze_image(image)
  259. pp result