-
Notifications
You must be signed in to change notification settings - Fork 0
/
horizontal_blur.cr
67 lines (55 loc) · 2.25 KB
/
horizontal_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 horizontal 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.horizontal_blur(1).save("horizontal_1_sample.jpg")
# image.horizontal_blur(5).save("horizontal_5_sample.jpg")
# ```
# <img src="https://raw.githubusercontent.com/Vici37/cr-image/master/docs/images/horizontal_1_sample.jpg" alt="Blurred sample image with k 1"/>
# <img src="https://raw.githubusercontent.com/Vici37/cr-image/master/docs/images/horizontal_5_sample.jpg" alt="Blurred sample image with k 5"/>
module CrImage::Operation::HorizontalBlur
def horizontal_blur(k : Int32) : self
clone.horizontal_blur!(k)
end
def horizontal_blur!(k : Int32) : self
buffer = Bytes.new(size, 0)
multiplier = 1 / (k + k + 1)
each_color_channel do |channel|
@height.times do |y|
center_index : Int32 = y * @width
left__bound : Int32 = center_index
right_bound : Int32 = center_index + k
first_value : Int32 = channel.unsafe_fetch(center_index).to_i
last__value : Int32 = channel.unsafe_fetch(center_index + @width - 1).to_i
current_sum : Int32 = (k + 1) * first_value
(0..k - 1).each do |i|
current_sum += channel.unsafe_fetch(center_index + i)
end
(0..k).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 += 1
center_index += 1
end
(k + 1..@width - k - 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)
right_bound += 1
left__bound += 1
center_index += 1
end
(@width - k..@width - 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 += 1
center_index += 1
end
end
channel.@buffer.copy_from(buffer.to_unsafe, buffer.size)
end
self
end
end