Let's call this canonical for now

This commit is contained in:
Pyrex 2024-04-10 12:45:38 -07:00
parent bab78aa61a
commit 7d12da32c8
5 changed files with 4 additions and 134 deletions

BIN
inputs/kapu.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View File

@ -11,8 +11,7 @@ pub fn decode_tile<R: Read>(
for _ in 0..quality { for _ in 0..quality {
let ix = reader.read_u8()?; let ix = reader.read_u8()?;
let val = decode_value(reader.read_u16()?); coefs[ix as usize] = reader.read_u16()? as i16 as i32 * 256;
coefs[ix as usize] = val;
} }
let mut transform = |zero: usize, stride: usize| { let mut transform = |zero: usize, stride: usize| {
@ -33,33 +32,13 @@ pub fn decode_tile<R: Read>(
} }
} }
} }
for i in 0..16 {
coefs[ixs[i]] /= 16;
}
}; };
for row in 0..16 { transform(row * 16, 1); } for row in 0..16 { transform(row * 16, 1); }
for col in 0..16 { transform(col, 16); } for col in 0..16 { transform(col, 16); }
for i in 0..256 { for i in 0..256 {
data[i] = coefs[i].max(0).min(255) as u8; data[i] = (coefs[i] / 256).max(0).min(255) as u8;
} }
Ok(()) Ok(())
} }
pub fn decode_value(enc: u16) -> i32 {
return (enc as i16) as i32 * 16;
/*
// 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;
*/
}

View File

@ -57,51 +57,7 @@ pub fn encode_tile<W: Write>(
for i in 0..quality { for i in 0..quality {
let ix = indices[i as usize]; let ix = indices[i as usize];
writer.write_u8(ix as u8)?; writer.write_u8(ix as u8)?;
writer.write_u16(encode_value(coefs[ix]))?; writer.write_u16((coefs[ix] / 256) as i16 as u16)?;
}; };
Ok(()) Ok(())
} }
pub fn encode_value(value: i32) -> u16 {
return ((value / 16) as i16) as u16;
/*
// quantize
let value = value / 32;
// mu law
let sign = value < 0;
let mut rescaled = value.abs() + 33;
let mut exponent = 0;
while rescaled > 64 {
exponent += 1;
rescaled >>= 1;
}
assert!(exponent <= 7);
let mantissa = (rescaled >> 1) & 0xf;
return (
if sign { 128 } else { 0 } |
exponent << 4 |
mantissa
) as u8;
}
#[cfg(test)]
mod test {
use quickcheck_macros::quickcheck;
use crate::decode_tile::decode_value;
use super::encode_value;
#[quickcheck]
fn test_encode_value(val: u16) -> bool {
let val = (val & (0x8000 | 0x3fff)) as i16;
let canon = decode_value(encode_value(val as i32));
canon == decode_value(encode_value(canon as i32))
}
*/
}

View File

@ -12,6 +12,7 @@ mod protocol;
fn main() { fn main() {
// run_for("zonked".to_string(), 9, 2, Some(330000)); // run_for("zonked".to_string(), 9, 2, Some(330000));
run_for("kapu".to_string());
run_for("lohikar".to_string()); run_for("lohikar".to_string());
run_for("zonked".to_string()); run_for("zonked".to_string());
run_for("avatar2".to_string()); run_for("avatar2".to_string());

View File

@ -1,66 +0,0 @@
// Ported from:
// - https://colab.research.google.com/drive/1WjtKwUcqxWafAumFO9ET74RsckZSsw6n#scrollTo=e3r9-RBpcgwH
// Specialized for:
//
// - Input domain: 0-255
// - Tile size: 16x16
//
// Rather than dividing by 16 at the end of a decode phase,
// we divide by 16 at the end of the _encode_ phase
//
// The normal range would be something like -255 * 256 to 255 * 256
// (-65280 to 65280) but this reduces it (now it's something like -4080 to 4080)
//
// This simplifies the decoder (which can be i16) and means it can be written
// using i16s instead of i32s
//
// We could probably shrink the range more by recentering to -128-127, but does
// it even matter? Reasonable encodings like A-law and mu-law can handle both.
//
// (Take my opinions on the range with a grain of salt: I've calculated it but I
// haven't measured it)
//
struct Transform<'d> {
data: &'d mut [i32],
zero: usize,
stride: usize,
}
impl<'d> Transform<'d> {
pub fn encode(&mut self) {
self.transform();
self.divide(16);
}
pub fn decode(&mut self) {
self.transform();
}
pub fn ix(&self, i: usize) -> usize {
self.zero + t * self.stride
}
fn transform(&mut self) {
for bit in [8, 4, 2, 1] {
for i in 0..16 {
if i & bit == 0 {
let j = i | bit;
let ival = self.data[self.ix(i)];
let jval = self.data[self.ix(j)];
self.data[self.ix(i)] = ival.wrapping_add(jval);
self.data[self.ix(j)] = ival.wrapping_sub(jval);
}
}
}
}
fn divide(&mut self, divisor: i32) {
for i in 0..16 {
self.data[self.ix(i)] = self.data[self.ix(j)] / divisor;
}
}
}