1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
use {
    crate::{
        display::{fill_bg, W},
        errors::ProgramError,
    },
    ansi_colours::self,
    crossterm::{
        style::{
            Color,
            Colors,
            Print,
            SetColors,
        },
        QueueableCommand,
    },
    image::Rgba,
};

const UPPER_HALF_BLOCK: char = '▀';

/// A "double line" normaly contains two lines of pixels
/// which are displayed as one line of characters, the
/// UPPER_HALF_BLOCK foreground for the upper pixel and
/// the background of the char for the lower pixel.
/// It acts as a buffer which is dumped to screen when
/// full or when the image is totally read.
pub struct DoubleLine {
    img_width: usize,
    pixels: Vec<Color>, // size twice img_width
    true_colors: bool,
}

impl DoubleLine {
    pub fn new(img_width: usize, true_colors: bool) -> Self {
        Self {
            img_width,
            pixels: Vec::with_capacity(2 * img_width),
            true_colors,
        }
    }
    pub fn push(&mut self, rgba: Rgba<u8>) {
        self.pixels.push(
            if self.true_colors {
                Color::Rgb {
                    r: rgba[0],
                    g: rgba[1],
                    b: rgba[2],
                }
            } else {
                Color::AnsiValue(ansi_colours::ansi256_from_rgb((
                    rgba[0],
                    rgba[1],
                    rgba[2],
                )))
            }
        );
    }
    pub fn is_empty(&self) -> bool {
        self.pixels.is_empty()
    }
    pub fn is_full(&self) -> bool {
        self.pixels.len() == 2 * self.img_width
    }
    pub fn write(
        &mut self,
        w: &mut W,
        left_margin: usize,
        right_margin: usize,
        bg: Color,
    ) -> Result<(), ProgramError> {
        debug_assert!(self.pixels.len()==self.img_width || self.pixels.len() == 2*self.img_width);
        // we may have either one or two lines
        let simple = self.pixels.len() < 2 * self.img_width;
        fill_bg(w, left_margin, bg)?;
        for i in 0..self.img_width {
            let foreground_color = self.pixels[i];
            let background_color = if simple {
                bg
            } else {
                self.pixels[i + self.img_width]
            };
            w.queue(SetColors(Colors::new(
                foreground_color,
                background_color,
            )))?;
            w.queue(Print(UPPER_HALF_BLOCK))?;
        }
        fill_bg(w, right_margin, bg)?;
        self.pixels.clear();
        Ok(())
    }
}