// 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.
/// Cached natural coefficient orders per transform type. /// Each entry is computed lazily on first access, avoiding computation /// of orders for large transforms that are never used. static NATURAL_COEFF_ORDERS: [OnceLock<Vec<u32>>; NUM_ORDERS] = [
OnceLock::new(),
OnceLock::new(),
OnceLock::new(),
OnceLock::new(),
OnceLock::new(),
OnceLock::new(),
OnceLock::new(),
OnceLock::new(),
OnceLock::new(),
OnceLock::new(),
OnceLock::new(),
OnceLock::new(),
OnceLock::new(),
];
/// Get cached natural coefficient order for a transform type index. /// Computes the order lazily on first access. fn get_natural_coeff_order(idx: usize) -> &'static Vec<u32> {
NATURAL_COEFF_ORDERS[idx].get_or_init(|| natural_coeff_order(TRANSFORM_TYPE_LUT[idx]))
}
pubfn natural_coeff_order(transform: HfTransformType) -> Vec<u32> { let cx = covered_blocks_x(transform) as usize; let cy = covered_blocks_y(transform) as usize; let xsize: usize = cx * BLOCK_DIM;
assert!(cx >= cy); // We compute the zigzag order for a cx x cx block, then discard all the // lines that are not multiple of the ratio between cx and cy. let xs = cx / cy; let xsm = xs - 1; let xss = xs.ceil_log2(); letmut out: Vec<u32> = vec![0; cx * cy * BLOCK_SIZE]; // First half of the block letmut cur = cx * cy; for i in0..xsize { for j in0..(i + 1) { letmut x = j; letmut y = i - j; if i % 2 != 0 {
mem::swap(&mut x, &mut y);
} if (y & xsm) != 0 { continue;
}
y >>= xss; let val; if x < cx && y < cy {
val = y * cx + x;
} else {
val = cur;
cur += 1;
}
out[val] = (y * xsize + x) as u32;
}
} // Second half for ir in1..xsize { let ip = xsize - ir; let i = ip - 1; for j in0..(i + 1) { letmut x = xsize - 1 - (i - j); letmut y = xsize - 1 - j; if !i.is_multiple_of(2) {
mem::swap(&mut x, &mut y);
} if (y & xsm) != 0 { continue;
}
y >>= xss; let val = cur;
cur += 1;
out[val] = (y * xsize + x) as u32;
}
}
out
}
pubfn decode_coeff_orders(used_orders: u32, br: &mut BitReader) -> Result<Vec<Permutation>> { // Use cached natural coefficient orders instead of recomputing let all_component_orders = 3 * NUM_ORDERS; letmut permutations: Vec<Permutation> = (0..all_component_orders)
.map(|o| Permutation(Cow::Borrowed(get_natural_coeff_order(o / 3))))
.collect(); if used_orders == 0 { return Ok(permutations);
} let histograms = Histograms::decode(NUM_PERMUTATION_CONTEXTS, br, true)?; letmut reader = SymbolReader::new(&histograms, br, None)?; for (ord, transform_type) in TRANSFORM_TYPE_LUT.iter().enumerate() { if used_orders & (1 << ord) == 0 { continue;
}
debug!(?transform_type); let num_blocks = covered_blocks_x(*transform_type) * covered_blocks_y(*transform_type); for c in0..3 { let size = num_blocks * BLOCK_SIZE as u32; let permutation = Permutation::decode(size, num_blocks, &histograms, br, &mut reader)?; let index = 3 * ord + c;
permutations[index].compose(&permutation);
}
}
reader.check_final_state(&histograms, br)?;
Ok(permutations)
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.