@@ -62,24 +62,11 @@ impl Triangle {
62
62
63
63
impl Primitive for Triangle {
64
64
fn is_inside_primitive ( & self , p : Point ) -> bool {
65
- let span_a = Point {
66
- x : self . b . x - self . a . x ,
67
- y : self . b . y - self . a . y ,
68
- } ;
69
- let span_b = Point {
70
- x : self . c . x - self . a . x ,
71
- y : self . c . y - self . a . y ,
72
- } ;
73
-
74
- let q = Point {
75
- x : p. x - self . a . x ,
76
- y : p. y - self . a . y ,
77
- } ;
78
-
79
- let s = q. cross_product ( span_b) as f32 * self . span_div ( ) ;
80
- let t = span_a. cross_product ( q) as f32 * self . span_div ( ) ;
81
-
82
- ( s >= 0.0 ) && ( t >= 0.0 ) && ( ( s + t) <= 1.0 )
65
+ return ( self . a . x - self . b . x ) * ( p. y - self . a . y ) -
66
+ ( self . a . y - self . b . y ) * ( p. x - self . a . x ) > 0 &&
67
+ ( self . b . x - self . c . x ) * ( p. y - self . b . y ) -
68
+ ( self . b . y - self . c . y ) * ( p. x - self . b . x ) > 0 &&
69
+ ( self . c . x - self . a . x ) * ( p. y - self . c . y ) - ( self . c . y - self . a . y ) * ( p. x - self . c . x ) > 0 ;
83
70
}
84
71
85
72
fn bounding_box ( & self ) -> BoundingBox {
@@ -178,11 +165,10 @@ impl Geometrify {
178
165
y : y as i32 ,
179
166
} ;
180
167
if primitive. is_inside_primitive ( p) {
181
- * image. get_pixel_mut ( x as u32 , y as u32 ) =
182
- Geometrify :: mix_color (
183
- primitive. get_color ( ) . expect ( "color of triangle not set" ) ,
184
- * image. get_pixel ( x as u32 , y as u32 ) ,
185
- ) ;
168
+ * image. get_pixel_mut ( x as u32 , y as u32 ) = Geometrify :: mix_color (
169
+ primitive. get_color ( ) . expect ( "color of triangle not set" ) ,
170
+ * image. get_pixel ( x as u32 , y as u32 ) ,
171
+ ) ;
186
172
}
187
173
}
188
174
}
@@ -203,93 +189,58 @@ impl Geometrify {
203
189
fn difference ( first : Rgba < u8 > , second : Rgba < u8 > ) -> u32 {
204
190
let ( r1, g1, b1, a1) = first. channels4 ( ) ;
205
191
let ( r2, g2, b2, a2) = second. channels4 ( ) ;
206
- let mut d = 0i32 ;
192
+ let mut d = 0 ;
207
193
208
- d += i32:: abs ( r1 as i32 - r2 as i32 ) ;
209
- d += i32:: abs ( g1 as i32 - g2 as i32 ) ;
210
- d += i32:: abs ( b1 as i32 - b2 as i32 ) ;
211
- d += i32:: abs ( a1 as i32 - a2 as i32 ) ;
194
+ d += i32:: abs ( r1 as i32 - r2 as i32 ) as u32 ;
195
+ d += i32:: abs ( g1 as i32 - g2 as i32 ) as u32 ;
196
+ d += i32:: abs ( b1 as i32 - b2 as i32 ) as u32 ;
197
+ d += i32:: abs ( a1 as i32 - a2 as i32 ) as u32 ;
212
198
213
- d as u32
199
+ d
214
200
}
215
201
216
- fn calculate_difference ( original : & RgbaImage ,
217
- current : & RgbaImage ,
218
- diff_lut : & [ u64 ] ,
219
- primitive : & Primitive )
220
- -> u64 {
202
+ fn calculate_difference (
203
+ original : & RgbaImage ,
204
+ current : & RgbaImage ,
205
+ total_difference : u64 ,
206
+ primitive : & Primitive ,
207
+ ) -> u64 {
221
208
let bb = primitive. bounding_box ( ) ;
222
-
223
- // Use LUT to calculate difference outside of the BB
224
- // TODO: Check whether indices are correct!
225
- let mut d = diff_lut[ diff_lut. len ( ) - 1 ] ;
226
- if bb. bottom_right . y > 0 && bb. bottom_right . x > 0 {
227
- d -= diff_lut[ ( ( bb. bottom_right . y - 1 ) as u32 * current. width ( ) +
228
- bb. bottom_right . x as u32 - 1 ) as usize ] ;
229
- }
230
- if bb. top_left . y > 0 && bb. bottom_right . x > 0 {
231
- d += diff_lut[ ( ( bb. top_left . y - 1 ) as u32 * current. width ( ) +
232
- bb. bottom_right . x as u32 - 1 ) as usize ] ;
233
- }
234
- if bb. bottom_right . y > 0 && bb. top_left . x > 0 {
235
- d += diff_lut[ ( ( bb. bottom_right . y - 1 ) as u32 * current. width ( ) +
236
- bb. top_left . x as u32 - 1 ) as usize ] ;
237
- }
238
- if bb. top_left . y > 0 && bb. top_left . x > 0 {
239
- d -= diff_lut[ ( ( bb. top_left . y - 1 ) as u32 * current. width ( ) +
240
- bb. top_left . x as u32 - 1 ) as usize ] ;
241
- }
209
+ let mut d: u64 = total_difference;
242
210
243
211
for y in bb. top_left . y ..bb. bottom_right . y {
244
212
for x in bb. top_left . x ..bb. bottom_right . x {
245
- let original_rgb = original. get_pixel ( x as u32 , y as u32 ) ;
246
- let result_rgb = if ( bb. top_left . x as u32 <= x as u32 ) &&
247
- ( x as u32 <= bb. bottom_right . x as u32 ) &&
248
- ( bb. top_left . y as u32 <= y as u32 ) &&
249
- ( y as u32 <= bb. bottom_right . y as u32 ) &&
250
- ( primitive. is_inside_primitive (
251
- Point {
252
- x : x as i32 ,
253
- y : y as i32 ,
254
- }
255
- ) ) {
256
- Geometrify :: mix_color (
257
- * current. get_pixel ( x as u32 , y as u32 ) ,
258
- primitive. get_color ( ) . expect ( "triangle color not " ) ,
259
- )
260
- } else {
261
- * current. get_pixel ( x as u32 , y as u32 )
262
- } ;
263
-
264
- d += Geometrify :: difference ( * original_rgb, result_rgb) as u64 ;
213
+ let source_color = original. get_pixel ( x as u32 , y as u32 ) ;
214
+ let current_color = current. get_pixel ( x as u32 , y as u32 ) ;
215
+
216
+ if primitive. is_inside_primitive ( Point { x : x, y : y } ) {
217
+ let old_difference = Geometrify :: difference ( * source_color, * current_color) ;
218
+ d -= old_difference as u64 ;
219
+
220
+ let new_color = Geometrify :: mix_color (
221
+ * current_color,
222
+ primitive. get_color ( ) . expect ( "triangle color not set." ) ,
223
+ ) ;
224
+ let new_difference = Geometrify :: difference ( * source_color, new_color) ;
225
+ d += new_difference as u64 ;
226
+ }
265
227
}
266
228
}
267
229
268
- d
230
+ d as u64
269
231
}
270
232
271
- fn calculate_difference_lut ( a : & RgbaImage , b : & RgbaImage ) -> Vec < u64 > {
272
- let mut result = Vec :: new ( ) ;
233
+ fn calculate_difference_image ( a : & RgbaImage , b : & RgbaImage ) -> u64 {
234
+ let mut difference = 0u64 ;
273
235
274
236
for y in 0 ..a. height ( ) {
275
237
for x in 0 ..a. width ( ) {
276
- let mut ldiff = Geometrify :: difference ( * a. get_pixel ( x, y) , * b. get_pixel ( x, y) ) as
277
- u64 ;
278
- if x > 0 {
279
- ldiff += result[ ( y * a. width ( ) + x - 1 ) as usize ] ;
280
- }
281
- if y > 0 {
282
- ldiff += result[ ( ( y - 1 ) * a. width ( ) + x) as usize ] ;
283
- }
284
- if x > 0 && y > 0 {
285
- ldiff -= result[ ( ( y - 1 ) * a. width ( ) + x - 1 ) as usize ] ;
286
- }
287
-
288
- result. push ( ldiff) ;
238
+ let ldiff = Geometrify :: difference ( * a. get_pixel ( x, y) , * b. get_pixel ( x, y) ) as u64 ;
239
+ difference += ldiff;
289
240
}
290
241
}
291
242
292
- result
243
+ difference
293
244
}
294
245
}
295
246
@@ -298,40 +249,36 @@ impl Filter for Geometrify {
298
249
progress. init ( self . iterations as u64 ) ;
299
250
300
251
let mut destination = RgbaImage :: new ( image. width ( ) , image. height ( ) ) ;
252
+ let mut total_difference = Geometrify :: calculate_difference_image ( & image, & destination) ;
301
253
302
254
for _ in 0 ..self . iterations {
303
- let difference_lut = Geometrify :: calculate_difference_lut ( & image, & destination) ;
304
-
305
255
let primitives = ( 0 ..self . samples )
306
256
. map ( |_| self . generate_primitive ( image. width ( ) , image. height ( ) ) )
307
- . map (
308
- |mut p| {
309
- p. span_div_save ( ) ;
310
- p
311
- }
312
- )
257
+ . map ( |mut p| {
258
+ p. span_div_save ( ) ;
259
+ p
260
+ } )
313
261
. collect :: < Vec < Triangle > > ( ) ;
314
262
let min_primitive = primitives
315
263
. par_iter ( )
316
- . map (
317
- |primitive| {
318
- let mut prim = * primitive ;
319
- prim . color = Some ( Geometrify :: calculate_color ( & image , & prim ) ) ;
320
- ( prim,
321
- Geometrify :: calculate_difference (
264
+ . map ( |primitive| {
265
+ let mut prim = * primitive ;
266
+ prim. color = Some ( Geometrify :: calculate_color ( & image , & prim ) ) ;
267
+ (
268
+ prim,
269
+ Geometrify :: calculate_difference (
322
270
& image,
323
271
& destination,
324
- & difference_lut ,
272
+ total_difference ,
325
273
& prim,
326
- ) )
327
- }
328
- )
274
+ ) ,
275
+ )
276
+ } )
329
277
. min_by_key ( |tup| tup. 1 ) ;
330
278
331
- Geometrify :: add_to_image (
332
- & mut destination,
333
- & min_primitive. expect ( "no fitting triangle found" ) . 0 ,
334
- ) ;
279
+ let ( bestprimitive, bestscore) = min_primitive. expect ( "no fitting triangle found" ) ;
280
+ Geometrify :: add_to_image ( & mut destination, & bestprimitive) ;
281
+ total_difference = bestscore;
335
282
progress. step ( ) ;
336
283
}
337
284
progress. finish ( ) ;
0 commit comments