62 lines
1.5 KiB
Rust
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;
|
|
} |