rx0/src/decode_tile.rs
2024-04-10 12:16:10 -07:00

62 lines
1.5 KiB
Rust

use std::io::Read;
use crate::protocol::{ProtocolReader, ProtocolReaderResult};
pub fn decode_tile<R: Read>(
data: &mut [u8; 256],
quality: u8,
reader: &mut ProtocolReader<R>
) -> ProtocolReaderResult<()> {
let mut coefs = [0_i32; 256];
for _ in 0..quality {
let ix = reader.read_u8()?;
let val = decode_value(reader.read_u8()?);
coefs[ix as usize] = val;
}
let mut transform = |zero: usize, stride: usize| {
let mut ixs = [0; 16];
ixs[0] = zero;
for i in 1..16 { ixs[i] = ixs[i - 1] + stride; }
for bit in [8, 4, 2, 1] {
for i in 0..16 {
if i & bit == 0 {
let j = i | bit;
let ival = coefs[ixs[i]];
let jval = coefs[ixs[j]];
coefs[ixs[i]] = ival.wrapping_add(jval);
coefs[ixs[j]] = ival.wrapping_sub(jval);
}
}
}
for i in 0..16 {
coefs[ixs[i]] /= 16;
}
};
for row in 0..16 { transform(row * 16, 1); }
for col in 0..16 { transform(col, 16); }
for i in 0..256 {
data[i] = coefs[i].max(0).min(255) as u8;
}
Ok(())
}
pub fn decode_value(enc: u8) -> i32 {
// mu law
let sign = enc & 0x80 != 0;
let exponent = (enc >> 4) & 0x7;
let mantissa = enc & 0xf;
let magnitude = ((((mantissa as i32) << 1) | 0b100001) << exponent) - 33;
let value = if sign { -magnitude } else {magnitude };
// unquantize
return value * 32;
}