Skip to content

Commit

Permalink
dequantizer
Browse files Browse the repository at this point in the history
  • Loading branch information
friendlymatthew committed Jun 16, 2024
1 parent d7e3bc2 commit c43b3b3
Show file tree
Hide file tree
Showing 7 changed files with 145 additions and 6 deletions.
64 changes: 63 additions & 1 deletion src/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,14 @@ use rayon::iter::ParallelIterator;

use crate::bitreader::BitReader;
use crate::coding::{CodingProcess, EntropyCoding};
use crate::dequantizer::Dequantizer;
use crate::entropy_decoder::EntropyDecoder;
use crate::frame_header::Component;
use crate::huffman_tree::HuffmanClass;
use crate::marker::{Marker, MarkerType};
use crate::parser::Parser;
use crate::sample_precision::SamplePrecision;
use crate::scan_header::ScanHeader;

type Marlen = (usize, usize); // offset, length

Expand Down Expand Up @@ -174,6 +177,15 @@ impl Decoder {
let frame_header = parser.parse_start_of_frame()?;
let (scan_header, encoded_image_start_index) = parser.parse_start_of_scan()?;
let compressed_image_data = parser.parse_image_data(encoded_image_start_index)?;
let ScanHeader {
scan_component_selectors,
..
} = &scan_header;

let scan_component_order = scan_component_selectors
.iter()
.map(|c| c.component_id)
.collect::<Vec<_>>();

// validation....
if frame_header.component_type != scan_header.component_type {
Expand Down Expand Up @@ -214,7 +226,57 @@ impl Decoder {
let decompressed_image_data = entropy_decoder.decode()?;
let mcus = entropy_decoder.zigzag(decompressed_image_data)?;

mcus.iter().for_each(|mcu| println!("{:?}", mcu));
// todo! refactor to this format inside entropy_decoder.
let mcus: Vec<_> = mcus
.into_iter()
.map(|mcu| {
let (mut res1, mut res2, mut res3) = ([0u8; 64], [0u8; 64], [0u8; 64]);

for (idx, &(c1, c2, c3)) in mcu.iter().enumerate() {
res1[idx] = c1;
res2[idx] = c2;
res3[idx] = c3;
}

(res1, res2, res3)
})
.collect();

let mut quantization_table_map = HashMap::new();

for component in &frame_header.components {
let Component {
component_id,
qt_table_id,
..
} = component;

let qt_table = *quantization_tables
.iter()
.find(|qt| qt.table_id == *qt_table_id)
.ok_or(anyhow!(format!(
"failed to find qt table id {}. \n{:?}",
qt_table_id, quantization_tables
)))?;

quantization_table_map.insert(*component_id, qt_table);
}

println!(
"frame: {:?}\nquantization tables {:?}\nquantization table keys: {:?}",
frame_header.components,
quantization_tables,
quantization_table_map.keys()
);

let mut dequantizer = Dequantizer::new(
&frame_header,
&mcus,
&scan_component_order,
quantization_table_map,
);

dequantizer.dequantize()?;
}
_ => todo!(),
}
Expand Down
77 changes: 77 additions & 0 deletions src/dequantizer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
use std::collections::HashMap;
use std::simd::Simd;

use anyhow::{anyhow, Result};
use rayon::iter::ParallelIterator;
use rayon::prelude::IntoParallelRefIterator;

use crate::frame_header::FrameHeader;
use crate::quantization_table::QuantizationTable;

pub(crate) struct Dequantizer<'a> {
frame_header: &'a FrameHeader,
data: &'a Vec<([u8; 64], [u8; 64], [u8; 64])>,
cursor: usize,
scan_component_order: &'a Vec<u8>,
quantization_table_map: HashMap<u8, QuantizationTable>,
}

impl<'a> Dequantizer<'a> {
pub(crate) fn new(
frame_header: &'a FrameHeader,
data: &'a Vec<([u8; 64], [u8; 64], [u8; 64])>,
scan_component_order: &'a Vec<u8>,
quantization_table_map: HashMap<u8, QuantizationTable>,
) -> Self {
Dequantizer {
frame_header,
data,
cursor: 0,
scan_component_order,
quantization_table_map,
}
}

pub(crate) fn dequantize(&mut self) -> Result<Vec<(Simd<u8, 64>, Simd<u8, 64>, Simd<u8, 64>)>> {
let mut idcts = vec![];

for mcu in self.data {
let (c1, c2, c3) = *mcu;
let idct: Result<Vec<_>> = self
.scan_component_order
.iter()
.zip(vec![c1, c2, c3].iter())
.map(|(component_id, mcu)| {
let QuantizationTable {
quantization_table_element,
..
} = *self
.quantization_table_map
.get(component_id)
.ok_or(anyhow!(format!(
"failed to find component id {}",
component_id
)))?;

Ok(Simd::from_array(*mcu) * quantization_table_element)
})
.collect();

let idct = idct?;
debug_assert_eq!(idct.len(), 3);
idcts.push((idct[0], idct[1], idct[2]))
}

Ok(idcts)
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_dequantizer() -> Result<()> {
Ok(())
}
}
1 change: 0 additions & 1 deletion src/entropy_decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,6 @@ impl<'a> EntropyDecoder<'a> {
self.cursor += 1;
}

println!("image data: {:?}", image_data.len());
Ok(image_data)
}
}
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ pub mod decoder;

mod bitreader;
mod coding;
mod dequantizer;
mod entropy_decoder;
pub(crate) mod frame_header;
pub(crate) mod huffman_tree;
Expand Down
4 changes: 2 additions & 2 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,10 @@ impl Parser {

// extract ht information
let qt_precisions_mask = Simd::splat(0b11110000);
let qt_precisions = qt_informations & qt_precisions_mask;
let qt_precisions = (qt_informations & qt_precisions_mask) >> 4;

let qt_ids_mask = Simd::splat(0b1111);
let qt_ids = (qt_informations & qt_ids_mask) >> 4;
let qt_ids = qt_informations & qt_ids_mask;

let qt_precisions = qt_precisions.to_array();
let qt_ids = qt_ids.to_array();
Expand Down
2 changes: 1 addition & 1 deletion src/quantization_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ enum TableType {
}

/// The set of 64 quantization values used to quantize the DCT coefficients
#[derive(Debug)]
#[derive(Debug, Copy, Clone)]
pub struct QuantizationTable {
/// Specifies the precision of the qk values. Value 0 indicates 8-bit Qk values; value 1
/// indicates 16-bit Qk values. Pq shall be zero for 8 bit sample precision P.
Expand Down
2 changes: 1 addition & 1 deletion src/scan_header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ pub struct ScanHeader {
pub(crate) point_transform: u8,
}

#[derive(Debug)]
#[derive(Debug, Copy, Clone)]
pub struct ScanComponentSelector {
pub(crate) component_id: u8,

Expand Down

0 comments on commit c43b3b3

Please sign in to comment.