jxl_coding/
permutation.rs

1use jxl_bitstream::Bitstream;
2
3/// Read a permutation from the entropy encoded stream.
4pub fn read_permutation(
5    bitstream: &mut Bitstream,
6    decoder: &mut crate::Decoder,
7    size: u32,
8    skip: u32,
9) -> crate::CodingResult<Vec<usize>> {
10    let end = decoder.read_varint(bitstream, get_context(size))?;
11    if end > size - skip {
12        tracing::error!(size, skip, end, "Invalid permutation");
13        return Err(crate::Error::InvalidPermutation);
14    }
15
16    let mut lehmer = vec![0u32; end as usize];
17    let mut prev_val = 0u32;
18    for (idx, val) in lehmer.iter_mut().enumerate() {
19        let idx = idx as u32;
20        *val = decoder.read_varint(bitstream, get_context(prev_val))?;
21        if *val >= size - skip - idx {
22            tracing::error!(idx = idx + skip, size, lehmer = *val, "Invalid permutation");
23            return Err(crate::Error::InvalidPermutation);
24        }
25        prev_val = *val;
26    }
27
28    let mut temp = ((skip as usize)..(size as usize)).collect::<Vec<_>>();
29    let mut permutation = Vec::with_capacity(size as usize);
30    for idx in 0..skip {
31        permutation.push(idx as usize);
32    }
33    for idx in lehmer {
34        permutation.push(temp.remove(idx as usize));
35    }
36    permutation.extend(temp);
37
38    Ok(permutation)
39}
40
41fn get_context(x: u32) -> u32 {
42    crate::add_log2_ceil(x).min(7)
43}