use super::paeth;
use crate::compat;
use crate::time;
fn slow_abs(x: isize) -> isize {
if x < 0 {
return -x;
}
x
}
fn slow_paeth(a: u8, b: u8, c: u8) -> u8 {
let p = a as isize + b as isize - c as isize;
let pa = slow_abs(p - a as isize);
let pb = slow_abs(p - b as isize);
let pc = slow_abs(p - c as isize);
if pa <= pb && pa <= pc {
return a;
} else if pb <= pc {
return b;
}
c
}
fn slow_filter_paeth(cdat: &mut [u8], pdat: &[u8], bytes_per_pixel: usize) {
for i in 0..bytes_per_pixel {
cdat[i] = cdat[i].wrapping_add(paeth::paeth(0, pdat[i], 0));
}
for i in bytes_per_pixel..cdat.len() {
cdat[i] = cdat[i].wrapping_add(paeth::paeth(
cdat[i - bytes_per_pixel],
pdat[i],
pdat[i - bytes_per_pixel],
));
}
}
#[test]
fn test_paeth() {
let mut a = 0;
while a < 256 {
let mut b = 0;
while b < 256 {
let mut c = 0;
while c < 256 {
let got = paeth::paeth(a as u8, b as u8, c as u8);
let want = slow_paeth(a as u8, b as u8, c as u8);
assert_eq!(
got, want,
"a, b, c = {}, {}, {}: got {}, want {}",
a, b, c, got, want
);
c += 15
}
b += 15
}
a += 15
}
}
#[test]
fn test_paeth_decode() {
let mut pdat0 = [0_u8; 32];
let mut pdat1 = [0_u8; 32];
let mut pdat2 = [0_u8; 32];
let mut cdat0 = [0_u8; 32];
let mut cdat1 = [0_u8; 32];
let mut cdat2 = [0_u8; 32];
for bytes_per_pixel in 1..=8 {
for _i in 0..100 {
for j in 0..pdat0.len() {
pdat0[j] = (time::now().nanosecond() & 0xff) as u8;
cdat0[j] = ((time::now().nanosecond() % 11) & 0xff) as u8;
}
compat::copy(&mut pdat1, &pdat0);
compat::copy(&mut pdat1, &pdat0);
compat::copy(&mut pdat2, &pdat0);
compat::copy(&mut cdat1, &cdat0);
compat::copy(&mut cdat2, &cdat0);
{
let cdat: &mut [u8] = &mut cdat1;
let pdat: &[u8] = &pdat1;
for i in 0..bytes_per_pixel {
let mut a = 0;
let mut c = 0;
let mut j = i;
while j < cdat.len() {
let b = pdat[j] as isize;
let mut pa = b - c;
let mut pb = a - c;
let pc = paeth::abs(pa + pb);
pa = paeth::abs(pa);
pb = paeth::abs(pb);
if pa <= pb && pa <= pc {
} else if pb <= pc {
a = b
} else {
a = c
}
a += cdat[j] as isize;
a &= 0xff;
cdat[j] = a as u8;
c = b;
j += bytes_per_pixel;
}
}
};
slow_filter_paeth(&mut cdat2, &pdat2, bytes_per_pixel);
assert_eq!(
cdat1, cdat2,
"bytes_per_pixel: {}\npdat0: {:?}\ncdat0: {:?}\ngot: {:?}\nwant: {:?}",
bytes_per_pixel, pdat0, cdat0, cdat1, cdat2
);
}
}
}