Skip to content

Commit

Permalink
jpeg/encoder: Fix DQT ordering
Browse files Browse the repository at this point in the history
  • Loading branch information
sophie-h committed Dec 31, 2024
1 parent 643be70 commit af67a20
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 7 deletions.
13 changes: 7 additions & 6 deletions gufo-jpeg/src/encoder.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
use crate::Error;
use gufo_common::math::*;
use jpeg_encoder::QuantizationTableType;

use crate::Error;

impl crate::Jpeg {
pub fn encoder<W: jpeg_encoder::JfifWrite>(
&self,
w: W,
) -> Result<jpeg_encoder::Encoder<W>, EncoderError> {
let mut encoder = jpeg_encoder::Encoder::new(w, 50);

encoder.set_sampling_factor(self.sampling_factor()?);
let mut encoder = jpeg_encoder::Encoder::new(w, 100);

let (luma, chroma) = self.quantization_tables()?;

Expand Down Expand Up @@ -61,11 +61,12 @@ impl crate::Jpeg {

let luma_parameters = self.components_specification_parameters(0)?;
let luma_table = dqts.get(&luma_parameters.tq).ok_or(Error::MissingDqt)?;
let luma = jpeg_encoder::QuantizationTableType::Custom(Box::new(luma_table.qk()));
let luma = jpeg_encoder::QuantizationTableType::Custom(Box::new(luma_table.qk_ordered()));

let chroma_parameters = self.components_specification_parameters(1)?;
let chroma_table = dqts.get(&chroma_parameters.tq).ok_or(Error::MissingDqt)?;
let chroma = jpeg_encoder::QuantizationTableType::Custom(Box::new(chroma_table.qk()));
let chroma: QuantizationTableType =
jpeg_encoder::QuantizationTableType::Custom(Box::new(chroma_table.qk_ordered()));

Ok((luma, chroma))
}
Expand Down
29 changes: 28 additions & 1 deletion gufo-jpeg/src/segments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ impl Dqt {

/// Quantization table elements in 16 bit
///
/// This resturns the data in 16 bit, even if defined as 8 bit.
/// This resturns the data in 16 bit, even if defined as 8 bit. The 8-bit
/// data is not scaled to 16-bit.
pub fn qk(&self) -> [u16; 64] {
match self {
Self::Dqt8(dqt) => {
Expand All @@ -43,6 +44,32 @@ impl Dqt {
}
}

/// Quantization table in non-zig-zag order
///
/// Otherwise same as `qk()`
pub fn qk_ordered(&self) -> [u16; 64] {
const IDX: [[usize; 8]; 8] = [
[0, 1, 5, 6, 14, 15, 27, 28],
[2, 4, 7, 13, 16, 26, 29, 42],
[3, 8, 12, 17, 25, 30, 41, 43],
[9, 11, 18, 24, 31, 40, 44, 53],
[10, 19, 23, 32, 39, 45, 52, 54],
[20, 22, 33, 38, 46, 51, 55, 60],
[21, 34, 37, 47, 50, 56, 59, 61],
[35, 36, 48, 49, 57, 58, 62, 63],
];

let qk = self.qk();

let mut qk_ordered = [0; 64];

for (i, n) in IDX.into_iter().flatten().enumerate() {
qk_ordered[i] = qk[n];
}

qk_ordered
}

pub fn from_data(mut value: &[u8]) -> Result<Vec<Self>, Error> {
let mut dqts = Vec::new();
while !value.is_empty() {
Expand Down

0 comments on commit af67a20

Please sign in to comment.