Skip to content

Instantly share code, notes, and snippets.

@jorrizza
Created June 27, 2011 15:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jorrizza/1049134 to your computer and use it in GitHub Desktop.
Save jorrizza/1049134 to your computer and use it in GitHub Desktop.
Codebrawl entry

Pixelizer entry for Codebrawl

This example needs Ruby 1.9.

Two ways to run this:

$ ./pixelizer.rb infile.png > outfile.png
$ ./pixelizer.rb - > outfile.png < infile.png
#!/usr/bin/env ruby
require 'chunky_png'
class Pixelizer
include ChunkyPNG
# The ChunkyPNG::Image instance.
attr_reader :png
# The pixelizer accepts an IO object, like a file handle or $stdin.
def initialize(io)
@png = Image.from_io io
end
# Pixelizes using a very simple algorithm. Every block of 10x10 pixels
# is evaluated, and replaced by one single color closest to the set of
# colors within that block. You can overwrite the 10x10 pixels by setting
# the first argument.
def pixelize!(block_size = 10)
dimension = @png.dimension
@block_point = Point.new 0, 0
while @block_point.within_bounds? dimension
y_delta = dimension.height - @block_point.y
@block_height = y_delta < block_size ? y_delta : block_size
while @block_point.within_bounds? dimension
x_delta = dimension.width - @block_point.x
@block_width = x_delta < block_size ? x_delta : block_size
pixelize_block!
@block_point.x += block_size
end
@block_point.x = 0
@block_point.y += block_size
end
end
protected
# Replaces the block with a single color.
def pixelize_block!
new_color = blur_color
for block_y in 0...@block_height
for block_x in 0...@block_width
@png[@block_point.x + block_x, @block_point.y + block_y] = new_color
end
end
end
# Calculates the new color for a block based on surrounding colors.
# Completely transparent pixels don't count of course.
def blur_color
colors = {r: [], g: [], b: [], a: []}
for block_y in 0...@block_height
for block_x in 0...@block_width
color = @png[@block_point.x + block_x, @block_point.y + block_y]
unless Color.fully_transparent? color
colors.keys.each do |channel|
colors[channel] << Color.send(channel, color)
end
end
end
end
return Color::TRANSPARENT if colors[:r].empty?
Color.rgba *(colors.map do |chan, set|
set.inject(:+) / set.length
end)
end
end
unless ARGV[0]
$stderr.puts "Usage: #{$0} [input.png | -] > output.png"
exit 1
end
begin
io = ARGV[0] == '-' ? $stdin : File.open(ARGV[0], 'rb')
pix = Pixelizer.new io
pix.pixelize!
pix.png.write $stdout
rescue
$stderr.puts "Sorry, something went wrong.\n#{$!}"
exit 1
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment