// Copyright (c) the JPEG XL Project Authors. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. use super::channel::decode_modular_channel; use crate::{ bit_reader::BitReader, entropy_coding::decode::SymbolReader, error::{Error, Result}, frame::modular::{ModularChannel, Tree, transforms::apply::meta_apply_local_transforms}, headers::{JxlHeader, modular::GroupHeader}, }; // This function will decode a header and apply local transforms if a header is not given. // The intended use of passing a header is for the DcGlobal section. pub fn decode_modular_subbitstream( buffers: Vec<&mut ModularChannel>, stream_id: usize, header: Option, global_tree: &Option, br: &mut BitReader, ) -> Result<()> { // Skip decoding if all grids are zero-sized. let is_empty = buffers .iter() .all(|buffer| matches!(buffer.data.size(), (0, _) | (_, 0))); if is_empty { return Ok(()); } let mut transform_steps = vec![]; let mut buffer_storage = vec![]; let buffers = buffers.into_iter().collect::>(); let (header, mut buffers) = match header { Some(h) => (h, buffers), None => { let h = GroupHeader::read(br)?; if !h.transforms.is_empty() { // Note: reassigning to `buffers` here convinces the borrow checker that the borrow of // `buffer_storage` ought to outlive `buffers[..]`'s lifetime, which obviously breaks // applying transforms later. let new_bufs; (new_bufs, transform_steps) = meta_apply_local_transforms(buffers, &mut buffer_storage, &h)?; (h, new_bufs) } else { (h, buffers) } } }; if header.use_global_tree && global_tree.is_none() { return Err(Error::NoGlobalTree); } let local_tree = if !header.use_global_tree { let num_local_samples = buffers .iter() .map(|buf| { let (width, height) = buf.channel_info().size; width * height }) .sum::(); let size_limit = (1024 + num_local_samples).min(1 << 20); Some(Tree::read(br, size_limit)?) } else { None }; let tree = if header.use_global_tree { global_tree.as_ref().unwrap() } else { local_tree.as_ref().unwrap() }; let image_width = buffers .iter() .map(|info| info.channel_info().size.0) .max() .unwrap_or(0); let mut reader = SymbolReader::new(&tree.histograms, br, Some(image_width))?; for i in 0..buffers.len() { decode_modular_channel(&mut buffers, i, stream_id, &header, tree, &mut reader, br)?; } reader.check_final_state(&tree.histograms, br)?; drop(buffers); for step in transform_steps.iter().rev() { step.local_apply(&mut buffer_storage)?; } Ok(()) }