RosettaCodeData/Task/Image-convolution/Ruby/image-convolution.rb

58 lines
1.5 KiB
Ruby

class Pixmap
# Apply a convolution kernel to a whole image
def convolute(kernel)
newimg = Pixmap.new(@width, @height)
pb = ProgressBar.new(@width) if $DEBUG
@width.times do |x|
@height.times do |y|
apply_kernel(x, y, kernel, newimg)
end
pb.update(x) if $DEBUG
end
pb.close if $DEBUG
newimg
end
# Applies a convolution kernel to produce a single pixel in the destination
def apply_kernel(x, y, kernel, newimg)
x0 = x==0 ? 0 : x-1
y0 = y==0 ? 0 : y-1
x1 = x
y1 = y
x2 = x+1==@width ? x : x+1
y2 = y+1==@height ? y : y+1
r = g = b = 0.0
[x0, x1, x2].zip(kernel).each do |xx, kcol|
[y0, y1, y2].zip(kcol).each do |yy, k|
r += k * self[xx,yy].r
g += k * self[xx,yy].g
b += k * self[xx,yy].b
end
end
newimg[x,y] = RGBColour.new(luma(r), luma(g), luma(b))
end
# Function for clamping values to those that we can use with colors
def luma(value)
if value < 0
0
elsif value > 255
255
else
value
end
end
end
# Demonstration code using the teapot image from Tk's widget demo
teapot = Pixmap.open('teapot.ppm')
[ ['Emboss', [[-2.0, -1.0, 0.0], [-1.0, 1.0, 1.0], [0.0, 1.0, 2.0]]],
['Sharpen', [[-1.0, -1.0, -1.0], [-1.0, 9.0, -1.0], [-1.0, -1.0, -1.0]]],
['Blur', [[0.1111,0.1111,0.1111],[0.1111,0.1111,0.1111],[0.1111,0.1111,0.1111]]],
].each do |label, kernel|
savefile = 'teapot_' + label.downcase + '.ppm'
teapot.convolute(kernel).save(savefile)
end