/usr/lib/ruby/vendor_ruby/chunky_png/canvas/resampling.rb is in ruby-chunky-png 1.2.8-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 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 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 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 133 134 135 136 137 138 139 140 141 142 143 144 | module ChunkyPNG
class Canvas
# 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
module Resampling
# 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
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
return indicies
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
def steps_residues(width, new_width)
indicies = Array.new(size=new_width, obj=nil)
residues = Array.new(size=new_width, obj=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
return indicies, residues
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.
def resample_nearest_neighbor!(new_width, new_height)
steps_x = steps(width, new_width)
steps_y = steps(height, new_height)
pixels = Array(size=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
def resample_nearest_neighbor(new_width, new_height)
dup.resample_nearest_neighbor!(new_width, new_height)
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.
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(size=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
def resample_bilinear(new_width, new_height)
dup.resample_bilinear!(new_width, new_height)
end
alias_method :resample, :resample_nearest_neighbor
alias_method :resize, :resample
end
end
end
|