Module: ChunkyPNG::Canvas::Resampling
- Included in:
- ChunkyPNG::Canvas
- Defined in:
- lib/chunky_png/canvas/resampling.rb
Overview
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.
Instance Method Summary collapse
- #resample_bilinear(new_width, new_height) ⇒ Object
-
#resample_bilinear!(new_width, new_height) ⇒ ChunkyPNG::Canvas
Resamples the canvas with bilinear interpolation.
- #resample_nearest_neighbor(new_width, new_height) ⇒ Object (also: #resample)
-
#resample_nearest_neighbor!(new_width, new_height) ⇒ ChunkyPNG::Canvas
Resamples the canvas using nearest neighbor interpolation.
-
#steps(width, new_width) ⇒ Array<Integer>
Integer Interpolation between two values.
-
#steps_residues(width, new_width) ⇒ Array<Integer>
Fractional Interpolation between two values.
Instance Method Details
#resample_bilinear(new_width, new_height) ⇒ Object
134 135 136 |
# File 'lib/chunky_png/canvas/resampling.rb', line 134 def resample_bilinear(new_width, new_height) dup.resample_bilinear!(new_width, new_height) end |
#resample_bilinear!(new_width, new_height) ⇒ ChunkyPNG::Canvas
Resamples the canvas with bilinear interpolation.
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
# File 'lib/chunky_png/canvas/resampling.rb', line 98 def resample_bilinear!(new_width, new_height) index_x, interp_x = steps_residues(width, new_width) index_y, interp_y = steps_residues(height, new_height) pixels = Array.new(new_width * new_height) i = 0 for y in 1..new_height # Clamp the indicies to the edges of the image y1 = [index_y[y - 1], 0].max y2 = [index_y[y - 1] + 1, height - 1].min y_residue = interp_y[y - 1] for x in 1..new_width # Clamp the indicies to the edges of the image x1 = [index_x[x - 1], 0].max x2 = [index_x[x - 1] + 1, width - 1].min x_residue = interp_x[x - 1] pixel_11 = get_pixel(x1, y1) pixel_21 = get_pixel(x2, y1) pixel_12 = get_pixel(x1, y2) pixel_22 = get_pixel(x2, y2) # Interpolate by Row pixel_top = ChunkyPNG::Color.interpolate_quick(pixel_21, pixel_11, x_residue) pixel_bot = ChunkyPNG::Color.interpolate_quick(pixel_22, pixel_12, x_residue) # Interpolate by Column pixels[i] = ChunkyPNG::Color.interpolate_quick(pixel_bot, pixel_top, y_residue) i += 1 end end replace_canvas!(new_width.to_i, new_height.to_i, pixels) end |
#resample_nearest_neighbor(new_width, new_height) ⇒ Object Also known as: resample
90 91 92 |
# File 'lib/chunky_png/canvas/resampling.rb', line 90 def resample_nearest_neighbor(new_width, new_height) dup.resample_nearest_neighbor!(new_width, new_height) end |
#resample_nearest_neighbor!(new_width, new_height) ⇒ ChunkyPNG::Canvas
Resamples the canvas using nearest neighbor interpolation.
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/chunky_png/canvas/resampling.rb', line 74 def resample_nearest_neighbor!(new_width, new_height) steps_x = steps(width, new_width) steps_y = steps(height, new_height) pixels = Array.new(new_width * new_height) i = 0 for y in steps_y for x in steps_x pixels[i] = get_pixel(x, y) i += 1 end end replace_canvas!(new_width.to_i, new_height.to_i, pixels) end |
#steps(width, new_width) ⇒ Array<Integer>
Integer Interpolation between two values
Used for generating indicies for interpolation (eg, nearest neighbour).
21 22 23 24 25 26 27 28 |
# File 'lib/chunky_png/canvas/resampling.rb', line 21 def steps(width, new_width) indicies, residues = steps_residues(width, new_width) for i in 1..new_width indicies[i - 1] = (indicies[i - 1] + (residues[i - 1] + 127) / 255) end indicies end |
#steps_residues(width, new_width) ⇒ Array<Integer>
Fractional Interpolation between two values
Used for generating values for interpolation (eg, bilinear). Produces both the indices and the interpolation factors (residues).
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/chunky_png/canvas/resampling.rb', line 38 def steps_residues(width, new_width) indicies = Array.new(new_width, nil) residues = Array.new(new_width, nil) # This works by accumulating the fractional error and # overflowing when necessary. # We use mixed number arithmetic with a denominator of # 2 * new_width base_step = width / new_width err_step = (width % new_width) << 1 denominator = new_width << 1 # Initial pixel index = (width - new_width) / denominator err = (width - new_width) % denominator for i in 1..new_width indicies[i - 1] = index residues[i - 1] = (255.0 * err.to_f / denominator.to_f).round index += base_step err += err_step if err >= denominator index += 1 err -= denominator end end [indicies, residues] end |