1use jxl_bitstream::{Bitstream, U};
2use jxl_grid::AllocTracker;
3use jxl_modular::{ChannelShift, MaConfig, Modular, ModularParams, Sample};
4use jxl_oxide_common::{define_bundle, Bundle};
5
6use crate::Result;
7
8define_bundle! {
9 #[derive(Debug)]
11 pub struct LfChannelDequantization error(crate::Error) {
12 all_default: ty(Bool) default(true),
13 pub m_x_lf: ty(F16) cond(!all_default) default(1.0 / 32.0),
14 pub m_y_lf: ty(F16) cond(!all_default) default(1.0 / 4.0),
15 pub m_b_lf: ty(F16) cond(!all_default) default(1.0 / 2.0),
16 }
17
18 #[derive(Debug)]
20 pub struct Quantizer error(crate::Error) {
21 pub global_scale: ty(U32(1 + u(11), 2049 + u(11), 4097 + u(12), 8193 + u(16))),
22 pub quant_lf: ty(U32(16, 1 + u(5), 1 + u(8), 1 + u(16))),
23 }
24
25 #[derive(Debug)]
27 pub struct LfChannelCorrelation error(crate::Error) {
28 all_default: ty(Bool) default(true),
29 pub colour_factor: ty(U32(84, 256, 2 + u(8), 258 + u(16))) cond(!all_default) default(84),
30 pub base_correlation_x: ty(F16) cond(!all_default) default(0.0),
31 pub base_correlation_b: ty(F16) cond(!all_default) default(1.0),
32 pub x_factor_lf: ty(u(8)) cond(!all_default) default(128),
33 pub b_factor_lf: ty(u(8)) cond(!all_default) default(128),
34 }
35}
36
37impl LfChannelDequantization {
38 #[inline]
39 pub fn m_x_lf_unscaled(&self) -> f32 {
40 self.m_x_lf / 128.0
41 }
42
43 #[inline]
44 pub fn m_y_lf_unscaled(&self) -> f32 {
45 self.m_y_lf / 128.0
46 }
47
48 #[inline]
49 pub fn m_b_lf_unscaled(&self) -> f32 {
50 self.m_b_lf / 128.0
51 }
52}
53
54#[derive(Debug, Default)]
56pub struct HfBlockContext {
57 pub qf_thresholds: Vec<u32>,
58 pub lf_thresholds: [Vec<i32>; 3],
59 pub block_ctx_map: Vec<u8>,
60 pub num_block_clusters: u32,
61}
62
63impl<Ctx> Bundle<Ctx> for HfBlockContext {
64 type Error = crate::Error;
65
66 fn parse(bitstream: &mut Bitstream, _: Ctx) -> crate::Result<Self> {
67 let mut qf_thresholds = Vec::new();
68 let mut lf_thresholds = [Vec::new(), Vec::new(), Vec::new()];
69 let (num_block_clusters, block_ctx_map) = if bitstream.read_bool()? {
70 (
71 15,
72 vec![
73 0, 1, 2, 2, 3, 3, 4, 5, 6, 6, 6, 6, 6, 7, 8, 9, 9, 10, 11, 12, 13, 14, 14, 14,
74 14, 14, 7, 8, 9, 9, 10, 11, 12, 13, 14, 14, 14, 14, 14,
75 ],
76 )
77 } else {
78 let mut bsize = 1;
79 for thr in &mut lf_thresholds {
80 let num_lf_thresholds = bitstream.read_bits(4)?;
81 bsize *= num_lf_thresholds + 1;
82 for _ in 0..num_lf_thresholds {
83 let t = bitstream.read_u32(U(4), 16 + U(8), 272 + U(16), 65808 + U(32))?;
84 let t = jxl_bitstream::unpack_signed(t);
85 thr.push(t);
86 }
87 }
88 let num_qf_thresholds = bitstream.read_bits(4)?;
89 bsize *= num_qf_thresholds + 1;
90 for _ in 0..num_qf_thresholds {
91 let t = bitstream.read_u32(U(2), 4 + U(3), 12 + U(5), 44 + U(8))?;
92 qf_thresholds.push(1 + t);
93 }
94
95 if bsize > 64 {
96 tracing::warn!(bsize, "bsize > 64");
97 }
98
99 let (num_clusters, ctx_map) = jxl_coding::read_clusters(bitstream, bsize * 39)?;
100 if num_clusters > 16 {
101 tracing::warn!(num_clusters, "num_clusters > 16");
102 }
103
104 (num_clusters, ctx_map)
105 };
106
107 Ok(Self {
108 qf_thresholds,
109 lf_thresholds,
110 block_ctx_map,
111 num_block_clusters,
112 })
113 }
114}
115
116#[derive(Debug)]
118pub struct LfCoeffParams<'ma, 'pool, 'tracker> {
119 pub lf_group_idx: u32,
120 pub lf_width: u32,
121 pub lf_height: u32,
122 pub jpeg_upsampling: [u32; 3],
123 pub bits_per_sample: u32,
124 pub global_ma_config: Option<&'ma MaConfig>,
125 pub allow_partial: bool,
126 pub tracker: Option<&'tracker AllocTracker>,
127 pub pool: &'pool jxl_threadpool::JxlThreadPool,
128}
129
130#[derive(Debug)]
132pub struct LfCoeff<S: Sample> {
133 pub extra_precision: u8,
134 pub lf_quant: Modular<S>,
135 pub partial: bool,
136}
137
138impl<S: Sample> Bundle<LfCoeffParams<'_, '_, '_>> for LfCoeff<S> {
139 type Error = crate::Error;
140
141 fn parse(bitstream: &mut Bitstream, params: LfCoeffParams) -> Result<Self> {
142 let LfCoeffParams {
143 lf_group_idx,
144 lf_width,
145 lf_height,
146 jpeg_upsampling,
147 bits_per_sample,
148 global_ma_config,
149 allow_partial,
150 tracker,
151 pool,
152 } = params;
153
154 let extra_precision = bitstream.read_bits(2)? as u8;
155
156 let width = (lf_width + 7) / 8;
157 let height = (lf_height + 7) / 8;
158 let channel_shifts = [1, 0, 2]
159 .into_iter()
160 .map(|idx| ChannelShift::from_jpeg_upsampling(jpeg_upsampling, idx))
161 .collect();
162 let lf_quant_params = ModularParams::new(
163 width,
164 height,
165 0,
166 bits_per_sample,
167 channel_shifts,
168 global_ma_config,
169 tracker,
170 );
171 let mut lf_quant = Modular::parse(bitstream, lf_quant_params)?;
172 let image = lf_quant.image_mut().unwrap();
173 let mut subimage = image.prepare_subimage()?;
174 subimage.decode(bitstream, 1 + lf_group_idx, allow_partial)?;
175 let complete = subimage.finish(pool);
176 Ok(Self {
177 extra_precision,
178 lf_quant,
179 partial: !complete,
180 })
181 }
182}