Skip to content

Instantly share code, notes, and snippets.

@thorncp
Created June 30, 2011 23:56
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 thorncp/233cae774314821d4a74 to your computer and use it in GitHub Desktop.
Save thorncp/233cae774314821d4a74 to your computer and use it in GitHub Desktop.
Pixelizing images with ChunkyPNG

Doing the damn thing

Outputs two versions of the image: a simple pixelated version and a version inspired by Andy Warhol.

Run it

ruby derp.rb
require 'chunky_png'
module ChunkyPNG
class PixelChunk
attr_reader :image, :left, :top, :right, :bottom
def initialize(image, left, top, right, bottom)
@image, @left, @top, @right, @bottom = image, left, top, right, bottom
end
def points
@points ||= [*left..right].product([*top..bottom])
end
def pixels
points.map { |x, y| image[x, y] }
end
def average
pix = self.pixels
red = pix.map { |p| Color.r p }.inject(:+) / pix.size
green = pix.map { |p| Color.g p }.inject(:+) / pix.size
blue = pix.map { |p| Color.b p }.inject(:+) / pix.size
Color.rgb(red, green, blue)
end
def color=(color)
points.each do |x, y|
image[x, y] = color
end
end
def pixelize!
self.color = average
end
def quadrant(size)
xs = (0..image.width).step(image.width / size).each_cons(2).map { |a,b| a..b }
ys = (0..image.height).step(image.height / size).each_cons(2).map { |a,b| a..b }
[xs.index { |x| x.cover? right }, ys.index { |y| y.cover? bottom }]
end
end
class Image
def pixelize(size)
dup.pixelize!(size)
end
def pixelize!(size)
pixel_chunks(size).each(&:pixelize!)
self
end
def pixelize_with_warhol(size)
dup.pixelize_with_warhol!(size)
end
def pixelize_with_warhol!(size)
pixel_chunks(size).each_with_index do |chunk, index|
avg = chunk.average
red = Color.r(avg)
green = Color.g(avg)
blue = Color.b(avg)
it = 0.5
case chunk.quadrant(3)
when [0,0], [1,1], [2,2]
green -= green * it
when [1,0], [2,1], [0,2]
blue -= blue * it
else
red -= red * it
end
chunk.color = Color.rgb(red.to_i, green.to_i, blue.to_i)
end
self
end
def pixel_chunks(size)
unless @pixel_chunks
xs = (0...width).step(size).to_a
ys = (0...height).step(size).to_a
@pixel_chunks = xs.product(ys).map { |x,y| PixelChunk.new(self, x, y, [x+size, width].min - 1, [y+size, height].min - 1) }
end
@pixel_chunks
end
end
end
image = ChunkyPNG::Image.from_file('input.png')
image.pixelize(10).save('output.png')
image.pixelize_with_warhol(10).save('warhol.png')
`open output.png` rescue nil
`open warhol.png` rescue nil
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment