From 89cb8eead70c41758a6f2efb49eba093148afb91 Mon Sep 17 00:00:00 2001 From: Nyeogmi Date: Wed, 10 Apr 2024 12:16:10 -0700 Subject: [PATCH] Well, it kinda works --- inputs/lohikar.png | Bin 0 -> 30584 bytes src/decode_tile.rs | 9 ++++--- src/encode_tile.rs | 61 ++++++--------------------------------------- src/main.rs | 3 ++- src/png_utils.rs | 1 - src/protocol.rs | 1 - 6 files changed, 15 insertions(+), 60 deletions(-) create mode 100644 inputs/lohikar.png diff --git a/inputs/lohikar.png b/inputs/lohikar.png new file mode 100644 index 0000000000000000000000000000000000000000..2422fb0ce5ad9f066c410bbcd5069cde50cfaf42 GIT binary patch literal 30584 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 E07C%&Z2$lO literal 0 HcmV?d00001 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 {