Skip to content

Instantly share code, notes, and snippets.

@DouglasMeyer
Created June 27, 2011 18:03
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 DouglasMeyer/3ae34b4672329790ac99 to your computer and use it in GitHub Desktop.
Save DouglasMeyer/3ae34b4672329790ac99 to your computer and use it in GitHub Desktop.
Pixelizing images with ChunkyPNG
require 'chunky_png'
image = ChunkyPNG::Image.from_file('input.png')
width, height = image.width, image.height
image.resample_nearest_neighbor!(width/10, height/10)
image.resample_nearest_neighbor!(width, height)
image.save('output.png')
require 'chunky_png'
module ChunkyPNG
class Canvas
module BilinearResampling
def resample_bilinear!(new_width, new_height)
width_ratio = width.to_f / new_width.to_f
height_ratio = height.to_f / new_height.to_f
pixels = []
1.upto(new_height) do |y|
1.upto(new_width) do |x|
pixels << get_bilinear_pixel((x-0.5)*width_ratio, (y-0.5)*height_ratio, width_ratio, height_ratio)
end
end
replace_canvas!(new_width, new_height, pixels)
end
private
def get_bilinear_pixel(x, y, sample_width, sample_height)
x = x - sample_width/2
y = y - sample_height/2
pixel_weights = []
(y.floor..[(y+sample_height).ceil, height-1].min).each do |image_y|
weight_y = 1
offset = y - image_y
weight_y = offset if offset > 0
offset = image_y - (y + sample_height)
weight_y = offset if offset > 0
(x.floor..[(x+sample_width).ceil, width-1].min).each do |image_x|
weight = weight_y
offset = x - image_x
weight = (weight_y ** 2 + offset ** 2) ** 0.5 if offset > 0
offset = image_x - (x + sample_width)
weight = (weight_y ** 2 + offset ** 2) ** 0.5 if offset > 0
pixel_weights << [get_pixel(image_x, image_y), weight]
end
end
total_weight = pixel_weights.inject(0){|acc,(_,w)| acc+w }
ChunkyPNG::Color.rgba(
(pixel_weights.inject(0){|acc,(p,w)| acc+ChunkyPNG::Color.r(p)*w }/total_weight).round,
(pixel_weights.inject(0){|acc,(p,w)| acc+ChunkyPNG::Color.g(p)*w }/total_weight).round,
(pixel_weights.inject(0){|acc,(p,w)| acc+ChunkyPNG::Color.b(p)*w }/total_weight).round,
(pixel_weights.inject(0){|acc,(p,w)| acc+ChunkyPNG::Color.a(p)*w }/total_weight).round
)
end
end
include BilinearResampling
end
end
image = ChunkyPNG::Image.from_file('input.png')
width, height = image.width, image.height
image.resample_bilinear!(width/10, height/10)
image.resample_nearest_neighbor!(width, height)
image.save('output.png')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment