-
Notifications
You must be signed in to change notification settings - Fork 0
/
vertical_blur.cr
67 lines (55 loc) · 2.33 KB
/
vertical_blur.cr
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
# Blur an image along the vertical axis
#
# Taking sample `image`:
#
# <img src="https://raw.githubusercontent.com/Vici37/cr-image/master/docs/images/sample.jpg" alt="Woman with black turtleneck and white background"/>
#
# ```
# image.vertical_blur(1).save("vertical_1_sample.jpg")
# image.vertical_blur(5).save("vertical_5_sample.jpg")
# ```
# <img src="https://raw.githubusercontent.com/Vici37/cr-image/master/docs/images/vertical_1_sample.jpg" alt="Blurred sample image with value 1"/>
# <img src="https://raw.githubusercontent.com/Vici37/cr-image/master/docs/images/vertical_5_sample.jpg" alt="Blurred sample image with value 5"/>
module CrImage::Operation::VerticalBlur
def vertical_blur(value : Int32) : self
clone.vertical_blur!(value)
end
def vertical_blur!(value : Int32) : self
buffer = Bytes.new(size, 0)
multiplier = 1 / (value + value + 1)
each_color_channel do |channel|
@width.times do |x|
center_index : Int32 = x
left_bound : Int32 = center_index
right_bound : Int32 = center_index + value * @width
first_value : Int32 = channel.unsafe_fetch(center_index).to_i
last_value : Int32 = channel.unsafe_fetch(center_index + @width * (@height - 1)).to_i
current_sum : Int32 = (value + 1) * first_value
(0..value - 1).each do |i|
current_sum += channel.unsafe_fetch(center_index + i * @width)
end
(0..value).each do
current_sum += channel.unsafe_fetch(right_bound).to_i - first_value
buffer.unsafe_put(center_index, (current_sum * multiplier).to_u8)
right_bound += @width
center_index += @width
end
(value + 1..@height - value - 1).each do
current_sum += channel.unsafe_fetch(right_bound).to_i - channel.unsafe_fetch(left_bound).to_i
buffer.unsafe_put(center_index, (current_sum * multiplier).to_u8)
left_bound += @width
right_bound += @width
center_index += @width
end
(@height - value..@height - 1).each do
current_sum += last_value - channel.unsafe_fetch(left_bound).to_i
buffer.unsafe_put(center_index, (current_sum * multiplier).to_u8)
left_bound += @width
center_index += @width
end
end
channel.@buffer.copy_from(buffer.to_unsafe, buffer.size)
end
self
end
end