1use crate::{
2 maps::{black, mode, white, Mode, EDFB_HALF},
3 BitWriter, Color, Transitions,
4};
5
6fn absdiff(a: u16, b: u16) -> u16 {
7 if a > b {
8 a - b
9 } else {
10 b - a
11 }
12}
13
14pub struct Encoder<W> {
15 writer: W,
16 reference: Vec<u16>,
17 current: Vec<u16>,
18}
19fn encode_color<W: BitWriter>(writer: &mut W, color: Color, mut n: u16) -> Result<(), W::Error> {
20 let table = match color {
21 Color::White => &white::ENTRIES,
22 Color::Black => &black::ENTRIES,
23 };
24 let mut write = |n: u16| {
25 let idx = if n >= 64 { 63 + n / 64 } else { n } as usize;
26 let (v, bits) = table[idx];
27 assert_eq!(v, n);
28 writer.write(bits)
30 };
31
32 while n >= 2560 {
33 write(2560)?;
34 n -= 2560;
35 }
36 if n >= 64 {
37 let d = n & !63;
38 write(d)?;
39 n -= d;
40 }
41
42 write(n)
43}
44impl<W: BitWriter> Encoder<W> {
45 pub fn new(writer: W) -> Self {
46 Encoder {
47 writer,
48 reference: vec![],
49 current: vec![],
50 }
51 }
52 pub fn encode_line(
53 &mut self,
54 pels: impl Iterator<Item = Color>,
55 width: u16,
56 ) -> Result<(), W::Error> {
57 let mut color = Color::White;
58 let mut transitions = Transitions::new(&self.reference);
59 let mut a0 = 0;
60 let mut start_of_line = true;
61 let mut pels = pels
62 .enumerate()
63 .scan(Color::White, |state, (i, c)| {
64 Some(if c != *state {
65 debug!(" {i} {c:?}");
66 *state = c;
67 Some(i as u16)
68 } else {
69 None
70 })
71 })
72 .filter_map(|x| x);
73 let writer = &mut self.writer;
74 self.current.clear();
75
76 while a0 < width {
77 let a1;
78 if let Some(a1_) = pels.next() {
79 self.current.push(a1_);
80 a1 = a1_;
81 } else {
82 a1 = width;
83 }
84 loop {
85 transitions.seek_back(a0);
86 let b1 = transitions
87 .next_color(a0, !color, start_of_line)
88 .unwrap_or(width);
89 let b2 = transitions.peek();
90 start_of_line = false;
91 debug!(" a0={a0}, a1={a1}, b1={:?}, b2={:?}", b1, b2);
92 match (b1, b2) {
93 (_b1, Some(b2)) if b2 < a1 => {
94 debug!(" Pass");
95 let bits = mode::encode(Mode::Pass).unwrap();
96 writer.write(bits)?;
97 transitions.skip(1);
98 a0 = b2;
99 continue;
100 }
101 (b1, _) if absdiff(a1, b1) <= 3 => {
102 let delta = a1 as i16 - b1 as i16;
103 debug!(" Vertical({})", delta);
104 let bits = mode::encode(Mode::Vertical(delta as i8)).unwrap();
105 writer.write(bits)?;
106 a0 = a1;
107 color = !color;
108 }
109 _ => {
110 let a2 = match pels.next() {
111 Some(a2) => {
112 self.current.push(a2);
113 a2
114 }
115 None => width,
116 };
117 let a0a1 = a1.saturating_sub(a0);
118 let a1a2 = a2.saturating_sub(a1);
119 debug!(" Horizontal({}, {}) color={color:?}", a0a1, a1a2);
120 let bits = mode::encode(Mode::Horizontal).unwrap();
121 writer.write(bits)?;
122 let c = if a0 + a1 == 0 { Color::White } else { color };
123 encode_color(writer, c, a0a1)?;
124 encode_color(writer, !c, a1a2)?;
125 a0 = a2;
126 }
127 }
128 break;
129 }
130 }
131
132 std::mem::swap(&mut self.reference, &mut self.current);
133 debug!("next line");
134 Ok(())
135 }
136 pub fn finish(mut self) -> Result<W, W::Error> {
137 self.writer.write(EDFB_HALF)?;
138 self.writer.write(EDFB_HALF)?;
139 Ok(self.writer)
140 }
141}