Created
June 27, 2011 15:49
-
-
Save carl-ellis/1049124 to your computer and use it in GitHub Desktop.
Code Brawl #2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Pixelise! | |
| ========= | |
| This has two pixelising function, a straight average of the colour channels in a given block, or a weighted mean based | |
| upon a two dimensional normal distribution. | |
| The code uses the weighted version, but the other is kept on for display purposes. | |
| Name your image "input.png" and run the program. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| require 'chunky_png' | |
| # 2d gaussian | |
| # | |
| # @params x x coord | |
| # @params y y coord | |
| # @params w width of sample | |
| # @params h height of sample | |
| def twodguass(x,y,w,h) | |
| #distro constants | |
| big_a = 1 | |
| a = 0.5 | |
| b = 0 | |
| c = 0.5 | |
| x_0 = w/2 | |
| y_0 = h/2 | |
| p1 = a*((x-x_0)**2) | |
| p2 = 2*b*((x-x_0)*(y-y_0)) | |
| p3 = c*((y-y_0)**2) | |
| p = (p1+p2+p3)*-1 | |
| return big_a*(Math.exp(p)) | |
| end | |
| # Pixelise functions | |
| # Return the average colour of a given area | |
| # | |
| # @params image image to manipulate | |
| # @params x x coord | |
| # @params y y coord | |
| # @params w width of area | |
| # @params h height of area | |
| def av_area(image, x, y, w, h) | |
| # image meta for error checking | |
| i_w = image.width | |
| i_h = image.height | |
| # Total area | |
| tot = w*h | |
| # average bins | |
| av_r = 0 | |
| av_g = 0 | |
| av_b = 0 | |
| # fill bins | |
| (0...w).each do |i| | |
| (0...h).each do |j| | |
| if(x+i >= i_w || y+j >= i_h) | |
| tot -=1 | |
| else | |
| raw = image[x+i,y+j] | |
| av_r += ChunkyPNG::Color.r(raw) | |
| av_g += ChunkyPNG::Color.g(raw) | |
| av_b += ChunkyPNG::Color.b(raw) | |
| end | |
| end | |
| end | |
| # divide bins | |
| av_r /= tot | |
| av_g /= tot | |
| av_b /= tot | |
| return ChunkyPNG::Color.rgb(av_r, av_g, av_b) | |
| end | |
| # Return the weighted average colour of a given area | |
| # | |
| # @params image image to manipulate | |
| # @params x x coord | |
| # @params y y coord | |
| # @params w width of area | |
| # @params h height of area | |
| def w_av_area(image, x, y, w, h) | |
| # image meta for error checking | |
| i_w = image.width | |
| i_h = image.height | |
| # Total weight | |
| tot = 0 | |
| # average bins | |
| av_r = 0 | |
| av_g = 0 | |
| av_b = 0 | |
| # fill bins | |
| (0...w).each do |i| | |
| (0...h).each do |j| | |
| if(x+i >= i_w || y+j >= i_h) | |
| else | |
| weight = twodguass(i,j,w,h) | |
| tot += weight | |
| raw = image[x+i,y+j] | |
| av_r += ChunkyPNG::Color.r(raw) * weight | |
| av_g += ChunkyPNG::Color.g(raw) * weight | |
| av_b += ChunkyPNG::Color.b(raw) * weight | |
| end | |
| end | |
| end | |
| # divide bins | |
| av_r /= tot | |
| av_g /= tot | |
| av_b /= tot | |
| return ChunkyPNG::Color.rgb(av_r.to_i, av_g.to_i, av_b.to_i) | |
| end | |
| # Pixelise function | |
| # | |
| # @params image image to pixelise | |
| # @params b_w block width | |
| # @params b_h block height | |
| # | |
| # @return pixelised image | |
| def pixelise(image, b_w, b_h) | |
| # Get image size | |
| w = image.width | |
| h = image.height | |
| # Number of blocks | |
| nbx = (w/b_w.to_f).ceil | |
| nby = (h/b_h.to_f).ceil | |
| # Go through each "block" in the image | |
| (0...nbx).each do |p_x| | |
| (0...nby).each do |p_y| | |
| # Top left coord | |
| x = p_x * b_w | |
| y = p_y * b_h | |
| # Get the average colour of the block | |
| p_colour = w_av_area(image, x, y, b_w, b_h); | |
| # Fill in block | |
| (0...b_w).each do |x1| | |
| (0...b_h).each do |y1| | |
| # Fill in up to edges | |
| image[x+x1,y+y1] = p_colour if !(x+x1 >= w || y+y1 >= h) | |
| end | |
| end | |
| end | |
| end | |
| return image | |
| end | |
| ### Script | |
| # Grab image | |
| image = ChunkyPNG::Image.from_file('input.png') | |
| # Size of pixeled area | |
| b_w = 10 | |
| b_h = 10 | |
| # Run the pixelisation | |
| image = pixelise(image, b_w, b_h) | |
| # save | |
| image.save('output.png') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
