From cb80fc9f7d2a1da3b5937ff50ad62535d1b87a28 Mon Sep 17 00:00:00 2001 From: G2-Games Date: Fri, 26 Jul 2024 17:36:42 -0500 Subject: [PATCH] Finished ability to encode and decode multiple channels --- src/compression/dct.rs | 18 +++++++++++---- src/header.rs | 1 + src/main.rs | 51 +++++++++++++++++++++--------------------- src/operations.rs | 2 -- 4 files changed, 41 insertions(+), 31 deletions(-) diff --git a/src/compression/dct.rs b/src/compression/dct.rs index 06e21b7..a9840f0 100644 --- a/src/compression/dct.rs +++ b/src/compression/dct.rs @@ -141,12 +141,21 @@ pub fn dequantize(input: &[i16], quant_matrix: [u16; 64]) -> Vec { pub fn dct_compress(input: &[u8], width: u32, height: u32, parameters: DctParameters) -> DctImage { let new_width = width as usize + (8 - width % 8) as usize; let new_height = height as usize + (8 - height % 8) as usize; - let mut img_2d: Vec> = input.windows(width as usize).step_by(width as usize).map(|r| r.to_vec()).collect(); - img_2d.iter_mut().for_each(|r| r.resize(new_width, 0)); - img_2d.resize(new_height, vec![0u8; new_width]); let mut dct_image = Vec::new(); - for _ in 0..1 { + dbg!(input.len()); + for ch in 0..parameters.format.channels() { + let channel: Vec = input.iter() + .skip(ch as usize) + .step_by(parameters.format.channels() as usize) + .copied() + .collect(); + dbg!(channel.len()); + + let mut img_2d: Vec> = channel.windows(width as usize).step_by(width as usize).map(|r| r.to_vec()).collect(); + img_2d.iter_mut().for_each(|r| r.resize(new_width, 0)); + img_2d.resize(new_height, vec![0u8; new_width]); + let mut dct_channel = Vec::new(); for h in 0..new_height / 8 { for w in 0..new_width / 8 { @@ -174,6 +183,7 @@ pub fn dct_compress(input: &[u8], width: u32, height: u32, parameters: DctParame } /// Parameters to pass to the [`dct_compress`] function. +#[derive(Debug, Clone, Copy)] pub struct DctParameters { /// A quality level from 1-100. Higher values provide better results. /// Default value is 80. diff --git a/src/header.rs b/src/header.rs index 245d8c3..f18cc3f 100644 --- a/src/header.rs +++ b/src/header.rs @@ -32,6 +32,7 @@ impl Header { } } +#[derive(Debug, Clone, Copy)] pub enum ColorFormat { /// RGBA, 8 bits per channel Rgba32, diff --git a/src/main.rs b/src/main.rs index 23f844b..9bd1029 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,18 +8,12 @@ mod operations; pub mod picture; use header::ColorFormat; -use picture::DangoPicture; -use std::{ - fs::File, - io::{BufReader, BufWriter, Write}, - time::Instant, -}; -use compression::{dct::{dct, dct_compress, dequantize, idct, quantization_matrix, quantize, DctParameters}, lossless}; +use compression::dct::{dct_compress, dequantize, idct, quantization_matrix, DctParameters}; -use image::{GenericImage, GrayImage, Luma}; +use image::{GenericImage, GrayImage, Luma, RgbaImage}; fn main() { - let input = image::open("test_input.png").unwrap().to_luma8(); + let input = image::open("shit.png").unwrap().to_rgba8(); input.save("original.png").unwrap(); let dct_result = dct_compress( @@ -27,31 +21,38 @@ fn main() { input.width(), input.height(), DctParameters { - quality: 100, + quality: 30, format: ColorFormat::Rgba32, } ); - let mut decoded_image = GrayImage::new(dct_result.width, dct_result.height); - for (i, chunk) in dct_result.channels[0].windows(64).step_by(64).enumerate() { - let dequantized_dct = dequantize(chunk, quantization_matrix(100)); - let original = idct(&dequantized_dct, 8, 8); + let mut final_img = vec![0u8; (dct_result.width as usize * dct_result.height as usize) * 4]; + for (chan_num, channel) in dct_result.channels.iter().enumerate() { + let mut decoded_image = GrayImage::new(dct_result.width, dct_result.height); + for (i, chunk) in channel.windows(64).step_by(64).enumerate() { + let dequantized_dct = dequantize(chunk, quantization_matrix(30)); + let original = idct(&dequantized_dct, 8, 8); - // Write rows of blocks - let start_x = (i * 8) % dct_result.width as usize; - let start_y = ((i * 8) / dct_result.width as usize) * 8; + // Write rows of blocks + let start_x = (i * 8) % dct_result.width as usize; + let start_y = ((i * 8) / dct_result.width as usize) * 8; - let mut sub = decoded_image.sub_image(start_x as u32, start_y as u32, 8, 8); - for y in 0..8 { - for x in 0..8 { - let value = original[(y as usize * 8) + x as usize]; - sub.put_pixel(x, y, Luma([value])) + let mut sub = decoded_image.sub_image(start_x as u32, start_y as u32, 8, 8); + for y in 0..8 { + for x in 0..8 { + let value = original[(y as usize * 8) + x as usize]; + sub.put_pixel(x, y, Luma([value])) + } } } - - decoded_image.save(format!("test.png")).unwrap(); + final_img.iter_mut().skip(chan_num).step_by(4).zip(decoded_image.iter()).for_each(|(c, n)| *c = *n); + decoded_image.save(format!("dct-{chan_num}.png")).unwrap(); } - decoded_image.save(format!("test.png")).unwrap(); + RgbaImage::from_raw( + dct_result.width, + dct_result.height, + final_img + ).unwrap().save("dct.png").unwrap(); /* // Reverse the DCT diff --git a/src/operations.rs b/src/operations.rs index d3eacf3..6072f61 100644 --- a/src/operations.rs +++ b/src/operations.rs @@ -1,5 +1,3 @@ -use image::{DynamicImage, GrayImage}; - pub fn line_diff(width: u32, height: u32, data: &[u8]) -> Vec { let mut output_buf = Vec::with_capacity((width * height * 4) as usize);