module ChunkyPNG::Canvas::Resampling
The ChunkyPNG::Canvas::Resampling
module defines methods to perform image resampling to a {ChunkyPNG::Canvas}.
Currently, only the nearest neighbor algorithm is implemented. Bilinear and cubic algorithms may be added later on.
@see ChunkyPNG::Canvas
Public Instance Methods
# File lib/chunky_png/canvas/resampling.rb 139 def resample_bilinear(new_width, new_height) 140 dup.resample_bilinear!(new_width, new_height) 141 end
Resamples the canvas with bilinear interpolation. @param [Integer] new_width The width of the resampled canvas. @param [Integer] new_height The height of the resampled canvas. @return [ChunkyPNG::Canvas] A new canvas instance with the resampled pixels.
# File lib/chunky_png/canvas/resampling.rb 103 def resample_bilinear!(new_width, new_height) 104 index_x, interp_x = steps_residues(width, new_width) 105 index_y, interp_y = steps_residues(height, new_height) 106 107 pixels = Array.new(new_width*new_height) 108 i = 0 109 for y in 1..new_height 110 # Clamp the indicies to the edges of the image 111 y1 = [index_y[y-1], 0].max 112 y2 = [index_y[y-1] + 1, height - 1].min 113 y_residue = interp_y[y-1] 114 115 for x in 1..new_width 116 # Clamp the indicies to the edges of the image 117 x1 = [index_x[x-1], 0].max 118 x2 = [index_x[x-1] + 1, width - 1].min 119 x_residue = interp_x[x-1] 120 121 pixel_11 = get_pixel(x1, y1) 122 pixel_21 = get_pixel(x2, y1) 123 pixel_12 = get_pixel(x1, y2) 124 pixel_22 = get_pixel(x2, y2) 125 126 # Interpolate by Row 127 pixel_top = ChunkyPNG::Color.interpolate_quick(pixel_21, pixel_11, x_residue) 128 pixel_bot = ChunkyPNG::Color.interpolate_quick(pixel_22, pixel_12, x_residue) 129 130 # Interpolate by Column 131 132 pixels[i] = ChunkyPNG::Color.interpolate_quick(pixel_bot, pixel_top, y_residue) 133 i += 1 134 end 135 end 136 replace_canvas!(new_width.to_i, new_height.to_i, pixels) 137 end
# File lib/chunky_png/canvas/resampling.rb 95 def resample_nearest_neighbor(new_width, new_height) 96 dup.resample_nearest_neighbor!(new_width, new_height) 97 end
Resamples the canvas using nearest neighbor interpolation. @param [Integer] new_width The width of the resampled canvas. @param [Integer] new_height The height of the resampled canvas. @return [ChunkyPNG::Canvas] A new canvas instance with the resampled pixels.
# File lib/chunky_png/canvas/resampling.rb 78 def resample_nearest_neighbor!(new_width, new_height) 79 steps_x = steps(width, new_width) 80 steps_y = steps(height, new_height) 81 82 83 pixels = Array.new(new_width*new_height) 84 i = 0 85 for y in steps_y 86 for x in steps_x 87 pixels[i] = get_pixel(x, y) 88 i += 1 89 end 90 end 91 92 replace_canvas!(new_width.to_i, new_height.to_i, pixels) 93 end
Integer Interpolation between two values
Used for generating indicies for interpolation (eg, nearest neighbour).
@param [Integer] width The width of the source @param [Integer] new_width The width of the destination @return [Array<Integer>] An Array of Integer indicies
# File lib/chunky_png/canvas/resampling.rb 24 def steps(width, new_width) 25 indicies, residues = steps_residues(width, new_width) 26 27 for i in 1..new_width 28 indicies[i-1] = (indicies[i-1] + (residues[i-1] + 127)/255) 29 end 30 return indicies 31 end
Fractional Interpolation between two values
Used for generating values for interpolation (eg, bilinear). Produces both the indices and the interpolation factors (residues).
@param [Integer] width The width of the source @param [Integer] new_width The width of the destination @return [Array<Integer>, Array<Integer>] Two arrays of indicies and residues
# File lib/chunky_png/canvas/resampling.rb 41 def steps_residues(width, new_width) 42 indicies = Array.new(new_width, obj=nil) 43 residues = Array.new(new_width, obj=nil) 44 45 # This works by accumulating the fractional error and 46 # overflowing when necessary. 47 48 # We use mixed number arithmetic with a denominator of 49 # 2 * new_width 50 base_step = width / new_width 51 err_step = (width % new_width) << 1 52 denominator = (new_width) << 1 53 54 # Initial pixel 55 index = (width - new_width) / denominator 56 err = (width - new_width) % denominator 57 58 for i in 1..new_width 59 indicies[i-1] = index 60 residues[i-1] = (255.0 * err.to_f / denominator.to_f).round 61 62 index += base_step 63 err += err_step 64 if err >= denominator 65 index += 1 66 err -= denominator 67 end 68 end 69 70 return indicies, residues 71 end