diff --git a/inputs/lohikar.png b/inputs/lohikar.png new file mode 100644 index 0000000..2422fb0 Binary files /dev/null and b/inputs/lohikar.png differ diff --git a/src/decode_tile.rs b/src/decode_tile.rs index 41c1833..f222092 100644 --- a/src/decode_tile.rs +++ b/src/decode_tile.rs @@ -11,7 +11,7 @@ pub fn decode_tile( for _ in 0..quality { let ix = reader.read_u8()?; - let val = reader.read_u16()? as i32; + let val = decode_value(reader.read_u8()?); coefs[ix as usize] = val; } @@ -49,11 +49,14 @@ pub fn decode_tile( } 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; - if sign { return -magnitude * 16 } - return magnitude * 16; + let value = if sign { -magnitude } else {magnitude }; + + // unquantize + return value * 32; } \ No newline at end of file diff --git a/src/encode_tile.rs b/src/encode_tile.rs index 590149e..085a003 100644 --- a/src/encode_tile.rs +++ b/src/encode_tile.rs @@ -57,13 +57,16 @@ pub fn encode_tile( for i in 0..quality { let ix = indices[i as usize]; writer.write_u8(ix as u8)?; - writer.write_u16(coefs[ix] as u16)?; + writer.write_u8(encode_value(coefs[ix]))?; }; Ok(()) } pub fn encode_value(value: i32) -> u8 { - let value = value / 16; + // quantize + let value = value / 32; + + // mu law let sign = value < 0; let mut rescaled = value.abs() + 33; let mut exponent = 0; @@ -72,6 +75,7 @@ pub fn encode_value(value: i32) -> u8 { exponent += 1; rescaled >>= 1; } + assert!(exponent <= 7); let mantissa = (rescaled >> 1) & 0xf; @@ -91,61 +95,10 @@ mod test { use super::encode_value; #[quickcheck] - fn test_encode_value_2(val: u16) -> bool { + 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)) } - - #[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))); - } } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 5f7440a..12da4ab 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,13 +12,14 @@ mod protocol; fn main() { // run_for("zonked".to_string(), 9, 2, Some(330000)); + run_for("lohikar".to_string()); run_for("zonked".to_string()); run_for("avatar2".to_string()); } fn run_for(name: String) { let image = png_utils::load_image( format!("inputs/{}.png", name), - [5, 6, 5, 0] + [5, 5, 5, 1] ).unwrap(); let mut writer = ProtocolWriter::new(vec![]); diff --git a/src/png_utils.rs b/src/png_utils.rs index 972e42c..bb52ec3 100644 --- a/src/png_utils.rs +++ b/src/png_utils.rs @@ -13,7 +13,6 @@ pub fn load_image(filename: String, quality: [u8; 4]) -> Result ProtocolWriter { self.writer.write_all(&value.to_le_bytes())?; Ok(()) } - } impl ProtocolReader { pub fn new(reader: R) -> Self {