1 use { 2 crate::{ 3 display::W, 4 errors::ProgramError, 5 }, 6 ansi_colours, 7 crossterm::{ 8 style::{ 9 Color, 10 Colors, 11 Print, 12 SetColors, 13 }, 14 QueueableCommand, 15 }, 16 image::Rgba, 17 termimad::fill_bg, 18 }; 19 20 const UPPER_HALF_BLOCK: char = '▀'; 21 22 /// A "double line" normaly contains two lines of pixels 23 /// which are displayed as one line of characters, the 24 /// UPPER_HALF_BLOCK foreground for the upper pixel and 25 /// the background of the char for the lower pixel. 26 /// It acts as a buffer which is dumped to screen when 27 /// full or when the image is totally read. 28 pub struct DoubleLine { 29 img_width: usize, 30 pixels: Vec<Color>, // size twice img_width 31 true_colors: bool, 32 } 33 34 impl DoubleLine { new(img_width: usize, true_colors: bool) -> Self35 pub fn new(img_width: usize, true_colors: bool) -> Self { 36 Self { 37 img_width, 38 pixels: Vec::with_capacity(2 * img_width), 39 true_colors, 40 } 41 } push(&mut self, rgba: Rgba<u8>)42 pub fn push(&mut self, rgba: Rgba<u8>) { 43 self.pixels.push( 44 if self.true_colors { 45 Color::Rgb { 46 r: rgba[0], 47 g: rgba[1], 48 b: rgba[2], 49 } 50 } else { 51 Color::AnsiValue(ansi_colours::ansi256_from_rgb(( 52 rgba[0], 53 rgba[1], 54 rgba[2], 55 ))) 56 } 57 ); 58 } is_empty(&self) -> bool59 pub fn is_empty(&self) -> bool { 60 self.pixels.is_empty() 61 } is_full(&self) -> bool62 pub fn is_full(&self) -> bool { 63 self.pixels.len() == 2 * self.img_width 64 } write( &mut self, w: &mut W, left_margin: usize, right_margin: usize, bg: Color, ) -> Result<(), ProgramError>65 pub fn write( 66 &mut self, 67 w: &mut W, 68 left_margin: usize, 69 right_margin: usize, 70 bg: Color, 71 ) -> Result<(), ProgramError> { 72 debug_assert!( 73 self.pixels.len() == self.img_width || self.pixels.len() == 2 * self.img_width 74 ); 75 // we may have either one or two lines 76 let simple = self.pixels.len() < 2 * self.img_width; 77 fill_bg(w, left_margin, bg)?; 78 for i in 0..self.img_width { 79 let foreground_color = self.pixels[i]; 80 let background_color = if simple { 81 bg 82 } else { 83 self.pixels[i + self.img_width] 84 }; 85 w.queue(SetColors(Colors::new( 86 foreground_color, 87 background_color, 88 )))?; 89 w.queue(Print(UPPER_HALF_BLOCK))?; 90 } 91 fill_bg(w, right_margin, bg)?; 92 self.pixels.clear(); 93 Ok(()) 94 } 95 } 96 97