use super::PredictionTransformImpl;
use crate::core::shared::{NdVector, Vector};
use crate::prelude::ByteWriter;
pub struct OctahedronOrthogonalTransform<const N: usize> {
out: Vec<NdVector<N, i32>>,
}
impl<const N: usize> OctahedronOrthogonalTransform<N> {
pub fn new(_cfg: super::Config) -> Self {
Self { out: Vec::new() }
}
}
impl<const N: usize> PredictionTransformImpl<N> for OctahedronOrthogonalTransform<N> {
fn map_with_tentative_metadata(
&mut self,
mut orig: NdVector<N, i32>,
mut pred: NdVector<N, i32>,
) where
NdVector<N, i32>: Vector<N, Component = i32>,
{
assert!(N == 2,);
let one = 255 / 2;
*pred.get_mut(0) -= one;
*pred.get_mut(1) -= one;
*orig.get_mut(0) -= one;
*orig.get_mut(1) -= one;
if pred.get(0).abs() + pred.get(1).abs() > one {
let pred0 = *pred.get(0);
let quadrant_sign = -(pred.get(0) * pred.get(1)).signum();
*pred.get_mut(0) = quadrant_sign * pred.get(1) + pred.get(0).signum() * one;
*pred.get_mut(1) = quadrant_sign * pred0 + pred.get(1).signum() * one;
let orig0 = *orig.get(0);
let quadrant_sign = -(orig.get(0) * orig.get(1)).signum();
*orig.get_mut(0) = quadrant_sign * orig.get(1) + orig.get(0).signum() * one;
*orig.get_mut(1) = quadrant_sign * orig0 + orig.get(1).signum() * one;
}
if pred != NdVector::<N, i32>::zero() {
while *pred.get(0) >= 0 || *pred.get(1) > 0 {
let tmp = *pred.get(0);
*pred.get_mut(0) = -pred.get(1);
*pred.get_mut(1) = tmp;
let tmp = *orig.get(0);
*orig.get_mut(0) = -orig.get(1);
*orig.get_mut(1) = tmp;
}
}
let mut corr = orig - pred;
for i in 0..N {
if *corr.get(i) < 0 {
*corr.get_mut(i) += 255;
}
}
self.out.push(corr);
}
fn squeeze<W>(self, writer: &mut W) -> Vec<NdVector<N, i32>>
where
W: ByteWriter,
{
writer.write_u32(255);
writer.write_u32(255 / 2);
self.out
}
}