@@ -105,6 +105,7 @@ enum Message {
105105 UseSentryPositionCheckboxToggled ( bool ) ,
106106 IntensityChanged ( f32 ) ,
107107 RadiusChanged ( f32 ) ,
108+ DesaturateChanged ( f32 ) ,
108109 ProcessDemosDone ( TimedResult < Vec < DemoProcessingOutput > > ) ,
109110 ExportImagePressed ,
110111 ImageNameSelected ( Option < PathBuf > ) ,
@@ -231,6 +232,8 @@ struct SettingsPane {
231232 intensity : f32 ,
232233 radius_state : slider:: State ,
233234 radius : f32 ,
235+ desaturate_state : slider:: State ,
236+ desaturate : f32 ,
234237}
235238
236239impl Default for SettingsPane {
@@ -258,6 +261,8 @@ impl Default for SettingsPane {
258261 intensity : 50.0 ,
259262 radius_state : Default :: default ( ) ,
260263 radius : 50.0 ,
264+ desaturate_state : Default :: default ( ) ,
265+ desaturate : 0.0 ,
261266 }
262267 }
263268}
@@ -339,6 +344,9 @@ impl SettingsPane {
339344 let radius_slider = Slider :: new ( & mut self . radius_state , 1.0 ..=100.0 , self . radius , Message :: RadiusChanged ) . style ( self . theme ) ;
340345 heatmap_options = heatmap_options. push ( radius_label) . push ( radius_slider) ;
341346 }
347+ let desaturate_label = Row :: new ( ) . spacing ( 10 ) . push ( Text :: new ( & format ! ( "Desaturate level overview: {:.0}%" , self . desaturate) ) ) ;
348+ let desaturate_slider = Slider :: new ( & mut self . desaturate_state , 0.0 ..=100.0 , self . desaturate , Message :: DesaturateChanged ) . style ( self . theme ) ;
349+ heatmap_options = heatmap_options. push ( desaturate_label) . push ( desaturate_slider) ;
342350 let use_sentry_position_checkbox =
343351 Checkbox :: new ( self . use_sentry_position , "Use sentry position for sentry kills" , Message :: UseSentryPositionCheckboxToggled ) . style ( self . theme ) ;
344352 heatmap_options = heatmap_options. push ( use_sentry_position_checkbox) ;
@@ -644,6 +652,11 @@ impl Application for App {
644652 settings_pane. radius = radius;
645653 self . try_generate_heatmap ( ) ;
646654 }
655+ Message :: DesaturateChanged ( desaturate) => {
656+ let settings_pane = self . get_settings_pane_mut ( ) ;
657+ settings_pane. desaturate = desaturate;
658+ self . try_generate_heatmap ( ) ;
659+ }
647660 Message :: ProcessDemosDone ( mut timed_result) => {
648661 let mut demo_count = 0 ;
649662 let mut death_count = 0 ;
@@ -893,11 +906,11 @@ impl App {
893906 }
894907 fn try_generate_heatmap ( & mut self ) {
895908 let preview_pane = self . get_preview_pane ( ) ;
909+ let settings_pane = self . get_settings_pane ( ) ;
896910 let image = match & preview_pane. heatmap_image {
897- Some ( image) => image. image . clone ( ) ,
911+ Some ( image) => apply_image_transformations ( & image. image , settings_pane . desaturate ) ,
898912 None => return ,
899913 } ;
900- let settings_pane = self . get_settings_pane ( ) ;
901914 if let ( Some ( pos_x) , Some ( pos_y) , Some ( scale) ) = ( settings_pane. x_pos , settings_pane. y_pos , settings_pane. scale ) {
902915 let coords_type = settings_pane. coords_type ;
903916 let heatmap_type = settings_pane. heatmap_type ;
@@ -935,10 +948,43 @@ impl App {
935948 }
936949 _ => unreachable ! ( ) ,
937950 } ;
951+ } else {
952+ // We can't generate the heatmap yet but we should still apply the desaturation on the level overview
953+ match & mut self . get_preview_pane_mut ( ) . heatmap_image {
954+ Some ( heatmap_image) => {
955+ heatmap_image. handle = image_to_handle ( & image) ;
956+ heatmap_image. image_with_heatmap_overlay = image;
957+ }
958+ _ => unreachable ! ( ) ,
959+ } ;
938960 }
939961 }
940962}
941963
964+ // just desaturate for now
965+ fn apply_image_transformations ( image : & ImageBuffer < Rgb < u8 > , Vec < u8 > > , desaturate : f32 ) -> ImageBuffer < Rgb < u8 > , Vec < u8 > > {
966+ let desaturate = desaturate / 100.0 ;
967+ let mut output_image = ImageBuffer :: new ( image. width ( ) , image. height ( ) ) ;
968+
969+ for ( x, y, pixel) in image. enumerate_pixels ( ) {
970+ let Rgb ( data) = * pixel;
971+
972+ // Convert the pixel to grayscale
973+ let gray_value = ( 0.3 * data[ 0 ] as f32 + 0.59 * data[ 1 ] as f32 + 0.11 * data[ 2 ] as f32 ) as u8 ;
974+
975+ // Linearly interpolate between the original pixel and the grayscale value
976+ let new_pixel = Rgb ( [
977+ ( ( 1.0 - desaturate) * data[ 0 ] as f32 + desaturate * gray_value as f32 ) as u8 ,
978+ ( ( 1.0 - desaturate) * data[ 1 ] as f32 + desaturate * gray_value as f32 ) as u8 ,
979+ ( ( 1.0 - desaturate) * data[ 2 ] as f32 + desaturate * gray_value as f32 ) as u8 ,
980+ ] ) ;
981+
982+ output_image. put_pixel ( x, y, new_pixel) ;
983+ }
984+
985+ output_image
986+ }
987+
942988fn image_to_handle ( image : & ImageBuffer < Rgb < u8 > , Vec < u8 > > ) -> Handle {
943989 Handle :: from_pixels (
944990 image. width ( ) ,
0 commit comments