mirror of
https://github.com/Dangoware/sqp.git
synced 2025-04-19 07:12:55 -05:00
Finished ability to encode and decode multiple channels
This commit is contained in:
parent
9a639974a2
commit
cb80fc9f7d
4 changed files with 41 additions and 31 deletions
|
@ -141,12 +141,21 @@ pub fn dequantize(input: &[i16], quant_matrix: [u16; 64]) -> Vec<f32> {
|
||||||
pub fn dct_compress(input: &[u8], width: u32, height: u32, parameters: DctParameters) -> DctImage {
|
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_width = width as usize + (8 - width % 8) as usize;
|
||||||
let new_height = height as usize + (8 - height % 8) as usize;
|
let new_height = height as usize + (8 - height % 8) as usize;
|
||||||
let mut img_2d: Vec<Vec<u8>> = 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();
|
let mut dct_image = Vec::new();
|
||||||
for _ in 0..1 {
|
dbg!(input.len());
|
||||||
|
for ch in 0..parameters.format.channels() {
|
||||||
|
let channel: Vec<u8> = input.iter()
|
||||||
|
.skip(ch as usize)
|
||||||
|
.step_by(parameters.format.channels() as usize)
|
||||||
|
.copied()
|
||||||
|
.collect();
|
||||||
|
dbg!(channel.len());
|
||||||
|
|
||||||
|
let mut img_2d: Vec<Vec<u8>> = 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();
|
let mut dct_channel = Vec::new();
|
||||||
for h in 0..new_height / 8 {
|
for h in 0..new_height / 8 {
|
||||||
for w in 0..new_width / 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.
|
/// Parameters to pass to the [`dct_compress`] function.
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct DctParameters {
|
pub struct DctParameters {
|
||||||
/// A quality level from 1-100. Higher values provide better results.
|
/// A quality level from 1-100. Higher values provide better results.
|
||||||
/// Default value is 80.
|
/// Default value is 80.
|
||||||
|
|
|
@ -32,6 +32,7 @@ impl Header {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum ColorFormat {
|
pub enum ColorFormat {
|
||||||
/// RGBA, 8 bits per channel
|
/// RGBA, 8 bits per channel
|
||||||
Rgba32,
|
Rgba32,
|
||||||
|
|
51
src/main.rs
51
src/main.rs
|
@ -8,18 +8,12 @@ mod operations;
|
||||||
pub mod picture;
|
pub mod picture;
|
||||||
|
|
||||||
use header::ColorFormat;
|
use header::ColorFormat;
|
||||||
use picture::DangoPicture;
|
use compression::dct::{dct_compress, dequantize, idct, quantization_matrix, DctParameters};
|
||||||
use std::{
|
|
||||||
fs::File,
|
|
||||||
io::{BufReader, BufWriter, Write},
|
|
||||||
time::Instant,
|
|
||||||
};
|
|
||||||
use compression::{dct::{dct, dct_compress, dequantize, idct, quantization_matrix, quantize, DctParameters}, lossless};
|
|
||||||
|
|
||||||
use image::{GenericImage, GrayImage, Luma};
|
use image::{GenericImage, GrayImage, Luma, RgbaImage};
|
||||||
|
|
||||||
fn main() {
|
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();
|
input.save("original.png").unwrap();
|
||||||
|
|
||||||
let dct_result = dct_compress(
|
let dct_result = dct_compress(
|
||||||
|
@ -27,31 +21,38 @@ fn main() {
|
||||||
input.width(),
|
input.width(),
|
||||||
input.height(),
|
input.height(),
|
||||||
DctParameters {
|
DctParameters {
|
||||||
quality: 100,
|
quality: 30,
|
||||||
format: ColorFormat::Rgba32,
|
format: ColorFormat::Rgba32,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut decoded_image = GrayImage::new(dct_result.width, dct_result.height);
|
let mut final_img = vec![0u8; (dct_result.width as usize * dct_result.height as usize) * 4];
|
||||||
for (i, chunk) in dct_result.channels[0].windows(64).step_by(64).enumerate() {
|
for (chan_num, channel) in dct_result.channels.iter().enumerate() {
|
||||||
let dequantized_dct = dequantize(chunk, quantization_matrix(100));
|
let mut decoded_image = GrayImage::new(dct_result.width, dct_result.height);
|
||||||
let original = idct(&dequantized_dct, 8, 8);
|
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
|
// Write rows of blocks
|
||||||
let start_x = (i * 8) % dct_result.width as usize;
|
let start_x = (i * 8) % dct_result.width as usize;
|
||||||
let start_y = ((i * 8) / dct_result.width as usize) * 8;
|
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);
|
let mut sub = decoded_image.sub_image(start_x as u32, start_y as u32, 8, 8);
|
||||||
for y in 0..8 {
|
for y in 0..8 {
|
||||||
for x in 0..8 {
|
for x in 0..8 {
|
||||||
let value = original[(y as usize * 8) + x as usize];
|
let value = original[(y as usize * 8) + x as usize];
|
||||||
sub.put_pixel(x, y, Luma([value]))
|
sub.put_pixel(x, y, Luma([value]))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
final_img.iter_mut().skip(chan_num).step_by(4).zip(decoded_image.iter()).for_each(|(c, n)| *c = *n);
|
||||||
decoded_image.save(format!("test.png")).unwrap();
|
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
|
// Reverse the DCT
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
use image::{DynamicImage, GrayImage};
|
|
||||||
|
|
||||||
pub fn line_diff(width: u32, height: u32, data: &[u8]) -> Vec<u8> {
|
pub fn line_diff(width: u32, height: u32, data: &[u8]) -> Vec<u8> {
|
||||||
let mut output_buf = Vec::with_capacity((width * height * 4) as usize);
|
let mut output_buf = Vec::with_capacity((width * height * 4) as usize);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue