Well, it kinda works

This commit is contained in:
Pyrex 2024-04-10 12:16:10 -07:00
parent ea18938dcf
commit 89cb8eead7
6 changed files with 15 additions and 60 deletions

BIN
inputs/lohikar.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

View File

@ -11,7 +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 = reader.read_u16()? as i32; let val = decode_value(reader.read_u8()?);
coefs[ix as usize] = val; coefs[ix as usize] = val;
} }
@ -49,11 +49,14 @@ pub fn decode_tile<R: Read>(
} }
pub fn decode_value(enc: u8) -> i32 { pub fn decode_value(enc: u8) -> i32 {
// mu law
let sign = enc & 0x80 != 0; let sign = enc & 0x80 != 0;
let exponent = (enc >> 4) & 0x7; let exponent = (enc >> 4) & 0x7;
let mantissa = enc & 0xf; let mantissa = enc & 0xf;
let magnitude = ((((mantissa as i32) << 1) | 0b100001) << exponent) - 33; let magnitude = ((((mantissa as i32) << 1) | 0b100001) << exponent) - 33;
if sign { return -magnitude * 16 } let value = if sign { -magnitude } else {magnitude };
return magnitude * 16;
// unquantize
return value * 32;
} }

View File

@ -57,13 +57,16 @@ 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(coefs[ix] as u16)?; writer.write_u8(encode_value(coefs[ix]))?;
}; };
Ok(()) Ok(())
} }
pub fn encode_value(value: i32) -> u8 { pub fn encode_value(value: i32) -> u8 {
let value = value / 16; // quantize
let value = value / 32;
// mu law
let sign = value < 0; let sign = value < 0;
let mut rescaled = value.abs() + 33; let mut rescaled = value.abs() + 33;
let mut exponent = 0; let mut exponent = 0;
@ -72,6 +75,7 @@ pub fn encode_value(value: i32) -> u8 {
exponent += 1; exponent += 1;
rescaled >>= 1; rescaled >>= 1;
} }
assert!(exponent <= 7);
let mantissa = (rescaled >> 1) & 0xf; let mantissa = (rescaled >> 1) & 0xf;
@ -91,61 +95,10 @@ mod test {
use super::encode_value; use super::encode_value;
#[quickcheck] #[quickcheck]
fn test_encode_value_2(val: u16) -> bool { fn test_encode_value(val: u16) -> bool {
let val = (val & (0x8000 | 0x3fff)) as i16; let val = (val & (0x8000 | 0x3fff)) as i16;
let canon = decode_value(encode_value(val as i32)); let canon = decode_value(encode_value(val as i32));
canon == decode_value(encode_value(canon as i32)) canon == decode_value(encode_value(canon as i32))
} }
#[test]
fn test_encode_value_1() {
// ...01abcdx cases
assert_eq!(0b00001111, encode_value(0 + (0b111110 - 33)));
assert_eq!(0b00001110, encode_value(0 + (0b111100 - 33)));
assert_eq!(0b10001111, encode_value(0 - (0b111110 - 33)));
assert_eq!(0b10001110, encode_value(0 - (0b111100 - 33)));
// ...01abcdxx cases
assert_eq!(0b00011111, encode_value(0 + (0b1111101 - 33)));
assert_eq!(0b00011110, encode_value(0 + (0b1111001 - 33)));
assert_eq!(0b10011111, encode_value(0 - (0b1111101 - 33)));
assert_eq!(0b10011110, encode_value(0 - (0b1111001 - 33)));
// ...01abcdxxx cases
assert_eq!(0b00101111, encode_value(0 + (0b11111000 - 33)));
assert_eq!(0b00101110, encode_value(0 + (0b11110001 - 33)));
assert_eq!(0b10101111, encode_value(0 - (0b11111010 - 33)));
assert_eq!(0b10101110, encode_value(0 - (0b11110011 - 33)));
// ...01abcdxxxx cases
assert_eq!(0b00111111, encode_value(0 + (0b111110000 - 33)));
assert_eq!(0b00111110, encode_value(0 + (0b111100010 - 33)));
assert_eq!(0b10111111, encode_value(0 - (0b111110100 - 33)));
assert_eq!(0b10111110, encode_value(0 - (0b111100110 - 33)));
// ...01abcdxxxxx cases
assert_eq!(0b01001111, encode_value(0 + (0b1111100000 - 33)));
assert_eq!(0b01001110, encode_value(0 + (0b1111000100 - 33)));
assert_eq!(0b11001111, encode_value(0 - (0b1111101000 - 33)));
assert_eq!(0b11001110, encode_value(0 - (0b1111001100 - 33)));
// ...01abcdxxxxxx cases
assert_eq!(0b01011111, encode_value(0 + (0b11111000000 - 33)));
assert_eq!(0b01011110, encode_value(0 + (0b11110001000 - 33)));
assert_eq!(0b11011111, encode_value(0 - (0b11111010000 - 33)));
assert_eq!(0b11011110, encode_value(0 - (0b11110011000 - 33)));
// ...01abcdxxxxxxx cases
assert_eq!(0b01101111, encode_value(0 + (0b111110000000 - 33)));
assert_eq!(0b01101110, encode_value(0 + (0b111100010000 - 33)));
assert_eq!(0b11101111, encode_value(0 - (0b111110100000 - 33)));
assert_eq!(0b11101110, encode_value(0 - (0b111100110000 - 33)));
// ...01abcdxxxxxxx cases
assert_eq!(0b01111111, encode_value(0 + (0b1111100000000 - 33)));
assert_eq!(0b01111110, encode_value(0 + (0b1111000100001 - 33)));
assert_eq!(0b11111111, encode_value(0 - (0b1111101000010 - 33)));
assert_eq!(0b11111110, encode_value(0 - (0b1111001100011 - 33)));
}
} }

View File

@ -12,13 +12,14 @@ 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("lohikar".to_string());
run_for("zonked".to_string()); run_for("zonked".to_string());
run_for("avatar2".to_string()); run_for("avatar2".to_string());
} }
fn run_for(name: String) { fn run_for(name: String) {
let image = png_utils::load_image( let image = png_utils::load_image(
format!("inputs/{}.png", name), format!("inputs/{}.png", name),
[5, 6, 5, 0] [5, 5, 5, 1]
).unwrap(); ).unwrap();
let mut writer = ProtocolWriter::new(vec![]); let mut writer = ProtocolWriter::new(vec![]);

View File

@ -13,7 +13,6 @@ pub fn load_image(filename: String, quality: [u8; 4]) -> Result<Image, ImageErro
let bytes = &buf[..info.buffer_size()]; let bytes = &buf[..info.buffer_size()];
assert_eq!(BitDepth::Eight, reader.info().bit_depth); assert_eq!(BitDepth::Eight, reader.info().bit_depth);
assert_eq!(ColorType::Rgb, reader.info().color_type);
let width = reader.info().width; let width = reader.info().width;
let height = reader.info().height; let height = reader.info().height;

View File

@ -44,7 +44,6 @@ impl<W: Write> ProtocolWriter<W> {
self.writer.write_all(&value.to_le_bytes())?; self.writer.write_all(&value.to_le_bytes())?;
Ok(()) Ok(())
} }
} }
impl<R: Read> ProtocolReader<R> { impl<R: Read> ProtocolReader<R> {
pub fn new(reader: R) -> Self { pub fn new(reader: R) -> Self {