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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
use Options;
use std::io::{self, Write};
pub trait Filter: for<'a> From<&'a Options> {
fn apply<W: Write>(&mut self, sink: W, line: &[u8])
-> io::Result<()>;
fn reset(&mut self, opts: &Options);
}
pub struct None;
impl<'a> From<&'a Options> for None {
fn from(_: &Options) -> Self { None }
}
impl Filter for None {
fn apply<W: Write>(&mut self, mut sink: W, line: &[u8])
-> io::Result<()>
{
sink.write_all(&[0])?;
sink.write_all(line)?;
Ok(())
}
fn reset(&mut self, _opts: &Options) {}
}
pub struct Standard {
bpp: usize,
len: usize,
buf: Vec<u8>,
}
impl<'a> From<&'a Options> for Standard {
fn from(opts: &Options) -> Self {
let len = opts.stride();
Self {
bpp: (opts.format.channels() * opts.depth as usize + 7) / 8,
len: len,
buf: vec![0; len * 6]
}
}
}
impl Filter for Standard {
fn apply<W: Write>(&mut self, mut sink: W, line: &[u8])
-> io::Result<()>
{
let funcs: [fn(u8, u8, u8) -> u8; 5] = [
|_, _, _| 0,
|a, _, _| a,
|_, b, _| b,
|a, b, _| ((a as u16 + b as u16) / 2) as u8,
|a, b, c| {
let (i, j, k) = (a as i16, b as i16, c as i16);
let (x, y) = (j - k, i - k);
let (pa, pb, pc) = (x.abs(), y.abs(), (x + y).abs());
if pa <= pb && pa <= pc { a }
else if pb <= pc { b }
else { c }
},
];
let mut scores: [usize; 5] = [0; 5];
for i in 0..line.len() {
let (b, d) = (self.buf[i], line[i]);
let (a, c) =
if self.bpp <= i {
(line[i - self.bpp], self.buf[i - self.bpp])
} else {
(0, 0)
};
for j in 0..5 {
let v = funcs[j](a, b, c);
let delta = d as isize - v as isize;
self.buf[(j + 1) * self.len + i] = delta as u8;
scores[j] += (delta * delta) as usize;
}
}
let mut best = 0;
for j in 1..5 {
if scores[j] < scores[best] {
best = j;
}
}
let start = (best + 1) * self.len;
sink.write_all(&[best as u8])?;
sink.write_all(&self.buf[start..start + self.len])?;
self.buf[..self.len].copy_from_slice(line);
Ok(())
}
fn reset(&mut self, opts: &Options) {
let len = opts.stride();
self.bpp = (opts.format.channels() * opts.depth as usize + 7) / 8;
self.len = len;
self.buf.clear();
self.buf.resize(len * 6, 0);
}
}