Coverage Report

Created: 2026-05-16 07:04

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