33use colorgrad:: { Color , Gradient as ColorGradient } ;
44use cosmic_bg_config:: Gradient ;
55use image:: Rgb32FImage ;
6+ use rayon:: prelude:: * ;
67
78/// Generate a background image from a color.
89pub fn single ( color : [ f32 ; 3 ] , width : u32 , height : u32 ) -> Rgb32FImage {
9- let mut imgbuf = Rgb32FImage :: new ( width, height) ;
10-
1110 let pixel = image:: Rgb ( color) ;
12-
13- for x in 0 ..width {
14- for y in 0 ..height {
15- imgbuf. put_pixel ( x, y, pixel) ;
16- }
17- }
18-
19- imgbuf
11+ image:: ImageBuffer :: from_pixel ( width, height, pixel)
2012}
2113
2214/// Generate a background image from a gradient.
@@ -26,14 +18,8 @@ pub fn gradient(
2618 height : u32 ,
2719) -> Result < Rgb32FImage , colorgrad:: GradientBuilderError > {
2820 let mut colors = Vec :: with_capacity ( gradient. colors . len ( ) ) ;
29-
3021 for & [ r, g, b] in & * gradient. colors {
31- colors. push ( colorgrad:: Color :: from_linear_rgba (
32- f32:: from ( r) ,
33- f32:: from ( g) ,
34- f32:: from ( b) ,
35- 1.0 ,
36- ) ) ;
22+ colors. push ( colorgrad:: Color :: from_linear_rgba ( r, g, b, 1.0 ) ) ;
3723 }
3824
3925 let grad = colorgrad:: GradientBuilder :: new ( )
@@ -42,45 +28,44 @@ pub fn gradient(
4228 . build :: < colorgrad:: LinearGradient > ( ) ?;
4329
4430 let mut imgbuf = image:: ImageBuffer :: new ( width, height) ;
45-
46- let width = f64:: from ( width) ;
47- let height = f64:: from ( height) ;
31+ let width = width as f32 ;
32+ let height = height as f32 ;
33+ let orientation = gradient. radius as u16 ;
34+
35+ let ( dmin, dmax) = grad. domain ( ) ;
36+ let angle = gradient. radius . to_radians ( ) ;
37+ let cos = f32:: cos ( angle) ;
38+ let sin = f32:: sin ( angle) ;
39+ const SCALE : f32 = 0.015 ;
40+ let w_scale = width / SCALE ;
41+ let h_scale = height / SCALE ;
4842
4943 // Map t which is in range [a, b] to range [c, d]
50- #[ allow( clippy:: items_after_statements) ]
51- fn remap ( t : f64 , a : f64 , b : f64 , c : f64 , d : f64 ) -> f64 {
44+ fn remap ( t : f32 , a : f32 , b : f32 , c : f32 , d : f32 ) -> f32 {
5245 ( t - a) * ( ( d - c) / ( b - a) ) + c
5346 }
5447
55- #[ allow( clippy:: items_after_statements) ]
56- const SCALE : f64 = 0.015 ;
57-
58- let positioner: Box < dyn Fn ( u32 , u32 ) -> f64 > = match gradient. radius as u16 {
59- 0 => Box :: new ( |_x, y| 1.0 - ( y as f64 / height) ) ,
60- 90 => Box :: new ( |x, _y| x as f64 / width) ,
61- 180 => Box :: new ( |_x, y| y as f64 / height) ,
62- 270 => Box :: new ( |x, _y| 1.0 - ( x as f64 / width) ) ,
63- _ => Box :: new ( |x, y| {
64- let ( dmin, dmax) = grad. domain ( ) ;
65- let angle = f64:: from ( gradient. radius . to_radians ( ) ) ;
66- let ( x, y) = ( f64:: from ( x) - width / SCALE , f64:: from ( y) - height / SCALE ) ;
67-
68- remap (
69- x * f64:: cos ( angle) - y * f64:: sin ( angle) ,
70- -width / SCALE ,
71- width / SCALE ,
72- f64:: from ( dmin) ,
73- f64:: from ( dmax) ,
74- )
75- } ) ,
76- } ;
77-
78- #[ allow( clippy:: cast_possible_truncation) ]
79- for ( x, y, pixel) in imgbuf. enumerate_pixels_mut ( ) {
80- let Color { r, g, b, .. } = grad. at ( positioner ( x, y) as f32 ) ;
81-
82- * pixel = image:: Rgb ( [ r as f32 , g as f32 , b as f32 ] ) ;
83- }
48+ imgbuf. par_enumerate_pixels_mut ( ) . for_each ( |( x, y, pixel) | {
49+ let x_f = x as f32 ;
50+ let y_f = y as f32 ;
51+
52+ let pos = match orientation {
53+ 0 => 1.0 - ( y_f / height) ,
54+ 90 => x_f / width,
55+ 180 => y_f / height,
56+ 270 => 1.0 - ( x_f / width) ,
57+ _ => remap (
58+ ( x_f - w_scale) * cos - ( y_f - h_scale) * sin,
59+ -w_scale,
60+ w_scale,
61+ dmin,
62+ dmax,
63+ ) ,
64+ } ;
65+
66+ let Color { r, g, b, .. } = grad. at ( pos) ;
67+ * pixel = image:: Rgb ( [ r, g, b] ) ;
68+ } ) ;
8469
8570 Ok ( imgbuf)
8671}
0 commit comments