Skip to content

Instantly share code, notes, and snippets.

@astro
Created November 22, 2008 15:46
Show Gist options
  • Save astro/27856 to your computer and use it in GitHub Desktop.
Save astro/27856 to your computer and use it in GitHub Desktop.
#!/usr/bin/env ruby
require 'RMagick'
include Magick
infile, outfile = ARGV
unless infile && outfile
puts "Usage: #{$0} <infile> <outfile>"
exit 1
end
class ImageData
BLOCK_WIDTH = 10
BLOCK_HEIGHT = 10
def self.from_file(filename)
new Image.read(filename).first
end
def write_file(filename)
@img.write(filename)
end
def initialize(img)
@img = img
clamp!
end
def clamp!
crop!(0, 0, width, height)
end
def crop!(bx, by, bw, bh)
puts "crop #{bx}x#{by}+#{bw}x#{bh} (#{@img.columns}x#{@img.rows})"
x, y = bx * BLOCK_WIDTH, by * BLOCK_HEIGHT
w, h = bw * BLOCK_WIDTH, bh * BLOCK_HEIGHT
@img = @img.crop(x, y, w, h, true)
puts "=> #{@img.columns}x#{@img.rows}"
self
end
def entropy_of(bx, by)
# Raw pixels:
pixels = @img.get_pixels(bx * BLOCK_WIDTH, by * BLOCK_HEIGHT,
BLOCK_WIDTH, BLOCK_HEIGHT)
# Intensities as [ 0.0, 0.1, 0.2 .. 1.0 ]
intensities = pixels.map { |pixel| (pixel.intensity / 6553.5).to_i / 10.0 }
amounts = Hash.new(0)
intensities.each do |i|
amounts[i] += 1
end
probabilities = {}
amounts.each do |intensity,amounts|
probabilities[intensity] = amounts / (BLOCK_WIDTH * BLOCK_HEIGHT).to_f
end
- intensities.inject(0) do |sum,intensity|
sum + probabilities[intensity] * Math.log(probabilities[intensity])
end
end
def width
@img.columns / BLOCK_WIDTH
end
def height
@img.rows / BLOCK_HEIGHT
end
def block_void?(x, y)
entropy_of(x, y) < 1.0
end
AREA_VOID_THRESHOLD = 0.98
def area_void?(x, y, w, h)
voids = 0
(y..(y+h-1)).each do |by|
(x..(x+w-1)).each do |bx|
voids += 1 if block_void?(bx, by)
end
end
puts "#{x}x#{y}+#{w}x#{h} => #{voids / (w * h).to_f}"
voids / (w * h).to_f > AREA_VOID_THRESHOLD
end
def print_out
height.times { |y|
width.times { |x|
if block_void?(x, y)
print " "
else
print "x"
end
}
puts
}
end
end
d = ImageData.from_file(infile)
puts "Before:"
#d.print_out
begin
done = true
# From top:
unless d.area_void?(0, 0, d.width, 1)
d.crop!(0, 1, d.width, d.height - 1)
done = false
end
# From left:
unless d.area_void?(0, 0, 1, d.height)
d.crop!(1, 0, d.width - 1, d.height)
done = false
end
# From bottom:
unless d.area_void?(0, d.height - 1, d.width, 1)
d.crop!(0, 0, d.width, d.height - 1)
done = false
end
# From right:
unless d.area_void?(d.width - 1, 0, 1, d.height)
d.crop!(0, 0, d.width - 1, d.height)
done = false
end
end while not done
d.write_file(outfile)
puts "After:"
d.print_out
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment