diff --git a/src/structs/lepton_decoder.rs b/src/structs/lepton_decoder.rs index ae2caf88..99d86e03 100644 --- a/src/structs/lepton_decoder.rs +++ b/src/structs/lepton_decoder.rs @@ -475,7 +475,7 @@ fn decode_edge( decode_one_edge::( model_per_color, bool_reader, - &curr_horiz_pred.to_array(), + &curr_horiz_pred, here_mut, qt, pt, @@ -486,7 +486,7 @@ fn decode_edge( decode_one_edge::( model_per_color, bool_reader, - &curr_vert_pred.to_array(), + &curr_vert_pred, here_mut, qt, pt, @@ -504,7 +504,7 @@ fn decode_edge( fn decode_one_edge( model_per_color: &mut ModelPerColor, bool_reader: &mut VPXBoolReader, - pred: &[i32; 8], + pred: &i32x8, here_mut: &mut AlignedBlock, qt: &QuantizationTables, pt: &ProbabilityTables, @@ -529,13 +529,13 @@ fn decode_one_edge( let mut coord_tr = delta; - for _lane in 0..7 { + for lane in 1..8 { if num_non_zeros_edge == 0 { break; } let best_prior = - pt.calc_coefficient_context8_lak::(qt, coord_tr, pred); + pt.calc_coefficient_context8_lak::(qt, lane, pred); let coef = model_per_color.read_edge_coefficient( bool_reader, diff --git a/src/structs/lepton_encoder.rs b/src/structs/lepton_encoder.rs index 71e4db6a..2f7fa476 100644 --- a/src/structs/lepton_encoder.rs +++ b/src/structs/lepton_encoder.rs @@ -500,7 +500,7 @@ fn encode_edge( here_tr, model_per_color, bool_writer, - &curr_horiz_pred.to_array(), + &curr_horiz_pred, qt, pt, num_non_zeros_bin, @@ -512,7 +512,7 @@ fn encode_edge( here_tr, model_per_color, bool_writer, - &curr_vert_pred.to_array(), + &curr_vert_pred, qt, pt, num_non_zeros_bin, @@ -538,7 +538,7 @@ fn encode_one_edge( block: &AlignedBlock, model_per_color: &mut ModelPerColor, bool_writer: &mut VPXBoolWriter, - pred: &[i32; 8], + pred: &i32x8, qt: &QuantizationTables, pt: &ProbabilityTables, num_non_zeros_bin: u8, @@ -586,13 +586,13 @@ fn encode_one_edge( let mut coord_tr = delta; - for _lane in 0..7 { + for lane in 1..8 { if num_non_zeros_edge == 0 { break; } let best_prior = - pt.calc_coefficient_context8_lak::(qt, coord_tr, pred); + pt.calc_coefficient_context8_lak::(qt, lane, pred); let coef = block.get_coefficient(coord_tr); diff --git a/src/structs/probability_tables.rs b/src/structs/probability_tables.rs index 8c0f18df..db1ee8b7 100644 --- a/src/structs/probability_tables.rs +++ b/src/structs/probability_tables.rs @@ -208,8 +208,8 @@ impl ProbabilityTables { pub fn calc_coefficient_context8_lak( &self, qt: &QuantizationTables, - coefficient_tr: usize, - pred: &[i32; 8], + lane: usize, + pred: &i32x8, ) -> i32 { if !ALL_PRESENT && ((HORIZONTAL && !self.above_present) || (!HORIZONTAL && !self.left_present)) @@ -217,14 +217,7 @@ impl ProbabilityTables { return 0; } - let mut best_prior: i32 = pred[if HORIZONTAL { - coefficient_tr >> 3 - } else { - coefficient_tr - }]; - best_prior /= (qt.get_quantization_table_transposed()[coefficient_tr] as i32) << 13; - - best_prior + pred.as_array_ref()[lane] / qt.get_quantization_table_divisors::()[lane].get() } pub fn adv_predict_dc_pix( diff --git a/src/structs/quantization_tables.rs b/src/structs/quantization_tables.rs index 34093b6f..fe15713f 100644 --- a/src/structs/quantization_tables.rs +++ b/src/structs/quantization_tables.rs @@ -4,6 +4,8 @@ * This software incorporates material from third parties. See NOTICE.txt for details. *--------------------------------------------------------------------------------------------*/ +use std::num::NonZeroI32; + use crate::consts::*; use crate::helpers::*; @@ -11,7 +13,18 @@ use super::jpeg_header::JPegHeader; pub struct QuantizationTables { quantization_table: [u16; 64], + + /// transposed version of quantization table quantization_table_transposed: [u16; 64], + + /// precalculated divisors * 8192 for the top row of the quantization table for final step of lak calculation + /// compiler sees non-zero to avoid having to check for division-by-zero + quantization_table_divisors_horiz: [NonZeroI32; 8], + + /// precalculated divisors * 8192 for the left column of the quantization table for final step of lak calculation + /// compiler sees non-zero to avoid having to check for division-by-zero + quantization_table_divisors_vert: [NonZeroI32; 8], + // Values for discrimination between "regular" and "noise" part of // edge AC coefficients, used in `read/write_edge_coefficient`. // Calculated using approximate maximal magnitudes @@ -31,6 +44,8 @@ impl QuantizationTables { quantization_table: [0; 64], quantization_table_transposed: [0; 64], min_noise_threshold: [0; 14], + quantization_table_divisors_horiz: [NonZeroI32::new(1).unwrap(); 8], + quantization_table_divisors_vert: [NonZeroI32::new(1).unwrap(); 8], }; for pixel_row in 0..8 { @@ -41,6 +56,16 @@ impl QuantizationTables { retval.quantization_table[coord] = q; retval.quantization_table_transposed[coord_tr] = q; + + if pixel_row == 0 { + retval.quantization_table_divisors_horiz[pixel_column] = + NonZeroI32::new(i32::from(q) << 13).unwrap(); + } + + if pixel_column == 0 { + retval.quantization_table_divisors_vert[pixel_row] = + NonZeroI32::new(i32::from(q) << 13).unwrap(); + } } } @@ -70,6 +95,13 @@ impl QuantizationTables { &self.quantization_table_transposed } + pub fn get_quantization_table_divisors(&self) -> &[NonZeroI32; 8] { + if HORIZONTAL { + &self.quantization_table_divisors_horiz + } else { + &self.quantization_table_divisors_vert + } + } pub fn get_min_noise_threshold(&self, coef: usize) -> u8 { self.min_noise_threshold[coef] }