@@ -7,7 +7,7 @@ use std::collections::VecDeque;
7
7
use bit_vec:: BitVec ;
8
8
use image:: { DynamicImage , GenericImage , GenericImageView , Rgba } ;
9
9
10
- pub ( crate ) fn alpha_bleed ( img : & mut DynamicImage ) {
10
+ pub ( crate ) fn alpha_bleed ( img : & mut DynamicImage , thickness : usize ) {
11
11
let ( w, h) = img. dimensions ( ) ;
12
12
13
13
// Tells whether a given position has been touched by the bleeding algorithm
@@ -68,41 +68,59 @@ pub(crate) fn alpha_bleed(img: &mut DynamicImage) {
68
68
visited. set ( x, y) ;
69
69
to_visit. push_back ( ( x, y) ) ;
70
70
}
71
+
72
+ img. put_pixel ( x, y, Rgba ( [ 0 , 0 , 0 , 0 ] ) ) ;
71
73
}
72
74
}
73
75
74
- while let Some ( ( x, y) ) = to_visit. pop_front ( ) {
75
- // Compute the average color from all surrounding pixels that are
76
- // eligible to be sampled from.
77
- let mut new_color = ( 0 , 0 , 0 ) ;
78
- let mut contributing = 0 ;
79
-
80
- for ( x_source, y_source) in adjacent_positions ( x, y) {
81
- if can_be_sampled. get ( x_source, y_source) {
82
- let source = img. get_pixel ( x_source, y_source) ;
76
+ for _ in 0 ..thickness {
77
+ let queue_length = to_visit. len ( ) ;
78
+ if queue_length == 0 {
79
+ break ;
80
+ }
83
81
84
- contributing += 1 ;
85
- new_color. 0 += source[ 0 ] as u16 ;
86
- new_color. 1 += source[ 1 ] as u16 ;
87
- new_color. 2 += source[ 2 ] as u16 ;
88
- } else if !visited. get ( x_source, y_source) {
89
- visited. set ( x_source, y_source) ;
90
- to_visit. push_back ( ( x_source, y_source) ) ;
82
+ let mut mutated_coords: Vec < ( u32 , u32 ) > = vec ! [ ( 0 , 0 ) ; queue_length] ;
83
+ for _ in 0 ..queue_length {
84
+ if let Some ( ( x, y) ) = to_visit. pop_front ( ) {
85
+ // Compute the average color from all surrounding pixels that are
86
+ // eligible to be sampled from.
87
+ let mut new_color = ( 0 , 0 , 0 ) ;
88
+ let mut contributing = 0 ;
89
+
90
+ for ( x_source, y_source) in adjacent_positions ( x, y) {
91
+ if can_be_sampled. get ( x_source, y_source) {
92
+ let source = img. get_pixel ( x_source, y_source) ;
93
+
94
+ contributing += 1 ;
95
+ new_color. 0 += source[ 0 ] as u16 ;
96
+ new_color. 1 += source[ 1 ] as u16 ;
97
+ new_color. 2 += source[ 2 ] as u16 ;
98
+ } else if !visited. get ( x_source, y_source) {
99
+ visited. set ( x_source, y_source) ;
100
+ to_visit. push_back ( ( x_source, y_source) ) ;
101
+ }
102
+ }
103
+
104
+ let denominator = u16:: max ( 1 , contributing) ;
105
+ let pixel = Rgba ( [
106
+ ( new_color. 0 / denominator) as u8 ,
107
+ ( new_color. 1 / denominator) as u8 ,
108
+ ( new_color. 2 / denominator) as u8 ,
109
+ 0 ,
110
+ ] ) ;
111
+
112
+ img. put_pixel ( x, y, pixel) ;
113
+ mutated_coords. push ( ( x, y) ) ;
91
114
}
92
115
}
93
116
94
- let pixel = Rgba ( [
95
- ( new_color. 0 / contributing) as u8 ,
96
- ( new_color. 1 / contributing) as u8 ,
97
- ( new_color. 2 / contributing) as u8 ,
98
- 0 ,
99
- ] ) ;
100
-
101
- img. put_pixel ( x, y, pixel) ;
102
-
103
- // Now that we've bled this pixel, it's eligible to be sampled from for
104
- // future iterations.
105
- can_be_sampled. set ( x, y) ;
117
+ for _ in 0 ..queue_length {
118
+ if let Some ( ( x, y) ) = mutated_coords. pop ( ) {
119
+ // Now that we've bled this pixel, it's eligible to be sampled from for
120
+ // future iterations.
121
+ can_be_sampled. set ( x, y) ;
122
+ }
123
+ }
106
124
}
107
125
}
108
126
0 commit comments