This commit is contained in:
		
							parent
							
								
									3006141cc0
								
							
						
					
					
						commit
						4f31b4d8fd
					
				
					 4 changed files with 49 additions and 32 deletions
				
			
		
							
								
								
									
										22
									
								
								README.md
									
										
									
									
									
								
							
							
						
						
									
										22
									
								
								README.md
									
										
									
									
									
								
							|  | @ -71,11 +71,13 @@ Stream the default source to the display. On Linux Wayland, this pops up a scree | ||||||
| Usage: servicepoint-cli stream screen [OPTIONS] | Usage: servicepoint-cli stream screen [OPTIONS] | ||||||
| 
 | 
 | ||||||
| Options: | Options: | ||||||
|   -p, --pointer    Show mouse pointer in video feed |   -p, --pointer     Show mouse pointer in video feed | ||||||
|       --no-hist    Disable histogram correction |       --no-hist     Disable histogram correction | ||||||
|       --no-blur    Disable blur |       --no-blur     Disable blur | ||||||
|       --no-sharp   Disable sharpening |       --no-sharp    Disable sharpening | ||||||
|       --no-dither  Disable dithering. Brightness will be adjusted so that around half of the pixels are on. |       --no-dither   Disable dithering. Brightness will be adjusted so that around half of the pixels are on. | ||||||
|  |       --no-spacers  Do not remove the spacers from the image. | ||||||
|  |       --no-aspect   Do not keep aspect ratio when resizing. | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| #### Stdin | #### Stdin | ||||||
|  | @ -127,10 +129,12 @@ Arguments: | ||||||
|   <FILE_NAME>   |   <FILE_NAME>   | ||||||
| 
 | 
 | ||||||
| Options: | Options: | ||||||
|       --no-hist    Disable histogram correction |       --no-hist     Disable histogram correction | ||||||
|       --no-blur    Disable blur |       --no-blur     Disable blur | ||||||
|       --no-sharp   Disable sharpening |       --no-sharp    Disable sharpening | ||||||
|       --no-dither  Disable dithering. Brightness will be adjusted so that around half of the pixels are on. |       --no-dither   Disable dithering. Brightness will be adjusted so that around half of the pixels are on. | ||||||
|  |       --no-spacers  Do not remove the spacers from the image. | ||||||
|  |       --no-aspect   Do not keep aspect ratio when resizing. | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| ## Contributing | ## Contributing | ||||||
|  |  | ||||||
|  | @ -154,6 +154,9 @@ pub struct ImageProcessingOptions { | ||||||
| 
 | 
 | ||||||
|     #[arg(long, help = "Do not remove the spacers from the image.")] |     #[arg(long, help = "Do not remove the spacers from the image.")] | ||||||
|     pub no_spacers: bool, |     pub no_spacers: bool, | ||||||
|  | 
 | ||||||
|  |     #[arg(long, help = "Do not keep aspect ratio when resizing.")] | ||||||
|  |     pub no_aspect: bool, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(clap::Parser, std::fmt::Debug, Clone)] | #[derive(clap::Parser, std::fmt::Debug, Clone)] | ||||||
|  |  | ||||||
|  | @ -12,7 +12,7 @@ use std::{default::Default, time::Instant}; | ||||||
| pub struct ImageProcessingPipeline { | pub struct ImageProcessingPipeline { | ||||||
|     options: ImageProcessingOptions, |     options: ImageProcessingOptions, | ||||||
|     resizer: Resizer, |     resizer: Resizer, | ||||||
|     render_size: (usize, usize), |     render_size: (u32, u32), | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| const SPACER_HEIGHT: usize = TILE_SIZE / 2; | const SPACER_HEIGHT: usize = TILE_SIZE / 2; | ||||||
|  | @ -21,16 +21,17 @@ impl ImageProcessingPipeline { | ||||||
|     pub fn new(options: ImageProcessingOptions) -> Self { |     pub fn new(options: ImageProcessingOptions) -> Self { | ||||||
|         debug!("Creating image pipeline: {:?}", options); |         debug!("Creating image pipeline: {:?}", options); | ||||||
| 
 | 
 | ||||||
|         let spacers_height = if options.no_spacers { |         let height = PIXEL_HEIGHT | ||||||
|             0 |             + if options.no_spacers { | ||||||
|         } else { |                 0 | ||||||
|             SPACER_HEIGHT * (TILE_HEIGHT - 1) |             } else { | ||||||
|         }; |                 SPACER_HEIGHT * (TILE_HEIGHT - 1) | ||||||
|  |             }; | ||||||
| 
 | 
 | ||||||
|         Self { |         Self { | ||||||
|             options, |             options, | ||||||
|             resizer: Resizer::new(), |             resizer: Resizer::new(), | ||||||
|             render_size: (PIXEL_WIDTH, PIXEL_HEIGHT + spacers_height), |             render_size: (PIXEL_WIDTH as u32, height as u32), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -52,7 +53,11 @@ impl ImageProcessingPipeline { | ||||||
|     fn resize_grayscale(&mut self, frame: DynamicImage) -> GrayImage { |     fn resize_grayscale(&mut self, frame: DynamicImage) -> GrayImage { | ||||||
|         let start_time = Instant::now(); |         let start_time = Instant::now(); | ||||||
| 
 | 
 | ||||||
|         let (scaled_width, scaled_height) = self.fit_size((frame.width(), frame.height())); |         let (scaled_width, scaled_height) = if self.options.no_aspect { | ||||||
|  |             self.render_size | ||||||
|  |         } else { | ||||||
|  |             self.calc_scaled_size_keep_aspect((frame.width(), frame.height())) | ||||||
|  |         }; | ||||||
|         let mut dst_image = DynamicImage::new(scaled_width, scaled_height, frame.color()); |         let mut dst_image = DynamicImage::new(scaled_width, scaled_height, frame.color()); | ||||||
| 
 | 
 | ||||||
|         self.resizer |         self.resizer | ||||||
|  | @ -106,20 +111,13 @@ impl ImageProcessingPipeline { | ||||||
|     fn remove_spacers(source: Bitmap) -> Bitmap { |     fn remove_spacers(source: Bitmap) -> Bitmap { | ||||||
|         let start_time = Instant::now(); |         let start_time = Instant::now(); | ||||||
| 
 | 
 | ||||||
|         let full_tile_rows_with_spacers = source.height() / (TILE_SIZE + SPACER_HEIGHT); |         let width = source.width(); | ||||||
|         let remaining_pixel_rows = source.height() % (TILE_SIZE + SPACER_HEIGHT); |         let result_height = Self::calc_height_without_spacers(source.height()); | ||||||
|         let total_spacer_height = full_tile_rows_with_spacers * SPACER_HEIGHT |         let mut result = Bitmap::new(width, result_height); | ||||||
|             + remaining_pixel_rows.saturating_sub(TILE_SIZE); |  | ||||||
|         let height_without_spacers = source.height() - total_spacer_height; |  | ||||||
|         trace!( |  | ||||||
|             "spacers take up {total_spacer_height}, resulting in height {height_without_spacers}" |  | ||||||
|         ); |  | ||||||
| 
 |  | ||||||
|         let mut result = Bitmap::new(source.width(), height_without_spacers); |  | ||||||
| 
 | 
 | ||||||
|         let mut source_y = 0; |         let mut source_y = 0; | ||||||
|         for result_y in 0..result.height() { |         for result_y in 0..result_height { | ||||||
|             for x in 0..result.width() { |             for x in 0..width { | ||||||
|                 result.set(x, result_y, source.get(x, source_y)); |                 result.set(x, result_y, source.get(x, source_y)); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|  | @ -133,10 +131,22 @@ impl ImageProcessingPipeline { | ||||||
|         result |         result | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn fit_size(&self, source: (u32, u32)) -> (u32, u32) { |     fn calc_height_without_spacers(height: usize) -> usize { | ||||||
|  |         let full_tile_rows_with_spacers = height / (TILE_SIZE + SPACER_HEIGHT); | ||||||
|  |         let remaining_pixel_rows = height % (TILE_SIZE + SPACER_HEIGHT); | ||||||
|  |         let total_spacer_height = full_tile_rows_with_spacers * SPACER_HEIGHT | ||||||
|  |             + remaining_pixel_rows.saturating_sub(TILE_SIZE); | ||||||
|  |         let height_without_spacers = height - total_spacer_height; | ||||||
|  |         trace!( | ||||||
|  |             "spacers take up {total_spacer_height}, resulting in final height {height_without_spacers}" | ||||||
|  |         ); | ||||||
|  |         height_without_spacers | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn calc_scaled_size_keep_aspect(&self, source: (u32, u32)) -> (u32, u32) { | ||||||
|         let (source_width, source_height) = source; |         let (source_width, source_height) = source; | ||||||
|         let (target_width, target_height) = self.render_size; |         let (target_width, target_height) = self.render_size; | ||||||
|         debug_assert_eq!(target_width % TILE_SIZE, 0); |         debug_assert_eq!(target_width % TILE_SIZE as u32, 0); | ||||||
| 
 | 
 | ||||||
|         let width_scale = target_width as f32 / source_width as f32; |         let width_scale = target_width as f32 / source_width as f32; | ||||||
|         let height_scale = target_height as f32 / source_height as f32; |         let height_scale = target_height as f32 / source_height as f32; | ||||||
|  |  | ||||||
|  | @ -215,7 +215,7 @@ fn ostromoukhov_dither_pixel( | ||||||
| ) { | ) { | ||||||
|     let (destination_value, error) = gray_to_bit(source[position], bias); |     let (destination_value, error) = gray_to_bit(source[position], bias); | ||||||
|     destination.set(position, destination_value); |     destination.set(position, destination_value); | ||||||
|     
 | 
 | ||||||
|     let mut diffuse = |to: usize, mat: i16| { |     let mut diffuse = |to: usize, mat: i16| { | ||||||
|         let diffuse_value = source[to] as i16 + mat; |         let diffuse_value = source[to] as i16 + mat; | ||||||
|         source[to] = diffuse_value.clamp(u8::MIN.into(), u8::MAX.into()) as u8; |         source[to] = diffuse_value.clamp(u8::MIN.into(), u8::MAX.into()) as u8; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Vinzenz Schroeter
						Vinzenz Schroeter