Skip to main content

j2k_codec_math/
dwt.rs

1//! JPEG 2000 discrete wavelet transform constants.
2
3mod linearized53;
4pub use linearized53::{
5    linearized_dwt53_row, Dwt53Band, Dwt53LinearRow, Dwt53LinearTap, DWT53_MAX_HIGH_LINEAR_TAPS,
6    DWT53_MAX_LINEAR_TAPS,
7};
8
9/// Return the maximum number of DWT decomposition levels supported by an
10/// image geometry.
11///
12/// The shared encoder policy is `floor(log2(min(width, height)))`; a zero or
13/// unit-length axis supports no decomposition levels.
14#[must_use]
15pub const fn max_decomposition_levels(width: u32, height: u32) -> u8 {
16    j2k_types::encode_geometry::maximum_decomposition_levels(width, height)
17}
18
19/// Forward irreversible 9/7 lifting step alpha, rounded for existing CPU/GPU paths.
20pub const DWT97_ALPHA_F32: f32 = -1.586_134_3;
21/// Forward irreversible 9/7 lifting step beta, rounded for existing CPU/GPU paths.
22pub const DWT97_BETA_F32: f32 = -0.052_980_117;
23/// Forward irreversible 9/7 lifting step gamma, rounded for existing CPU/GPU paths.
24pub const DWT97_GAMMA_F32: f32 = 0.882_911_1;
25/// Forward irreversible 9/7 lifting step delta, rounded for existing CPU/GPU paths.
26pub const DWT97_DELTA_F32: f32 = 0.443_506_87;
27/// Irreversible 9/7 scaling factor, rounded for existing CPU/GPU paths.
28pub const DWT97_KAPPA_F32: f32 = 1.230_174_1;
29/// Inverse irreversible 9/7 scaling factor, computed the same way as existing paths.
30pub const DWT97_INV_KAPPA_F32: f32 = 1.0 / DWT97_KAPPA_F32;
31/// Historical high-pass synthesis scale used by `OpenJPEG`.
32///
33/// `OpenJPEG` pairs this value with uncompensated irreversible subband step
34/// sizes.  The product is intentionally not identical to `2 / KAPPA`.
35pub const IDWT97_OPENJPEG_TWO_INV_KAPPA_F32: f32 = 1.625_732_4;
36
37/// Inverse 9/7 alpha step used by synthesis paths.
38pub const IDWT97_NEG_ALPHA_F32: f32 = -DWT97_ALPHA_F32;
39/// Inverse 9/7 beta step used by synthesis paths.
40pub const IDWT97_NEG_BETA_F32: f32 = -DWT97_BETA_F32;
41/// Inverse 9/7 gamma step used by synthesis paths.
42pub const IDWT97_NEG_GAMMA_F32: f32 = -DWT97_GAMMA_F32;
43/// Inverse 9/7 delta step used by synthesis paths.
44pub const IDWT97_NEG_DELTA_F32: f32 = -DWT97_DELTA_F32;
45
46/// Forward irreversible 9/7 lifting step alpha at f64 precision.
47pub const DWT97_ALPHA_F64: f64 = -1.586_134_342_059_924;
48/// Forward irreversible 9/7 lifting step beta at f64 precision.
49pub const DWT97_BETA_F64: f64 = -0.052_980_118_572_961;
50/// Forward irreversible 9/7 lifting step gamma at f64 precision.
51pub const DWT97_GAMMA_F64: f64 = 0.882_911_075_530_934;
52/// Forward irreversible 9/7 lifting step delta at f64 precision.
53pub const DWT97_DELTA_F64: f64 = 0.443_506_852_043_971;
54/// Irreversible 9/7 scaling factor at f64 precision.
55pub const DWT97_KAPPA_F64: f64 = 1.230_174_104_914_001;
56/// Inverse irreversible 9/7 scaling factor at f64 precision.
57pub const DWT97_INV_KAPPA_F64: f64 = 1.0 / DWT97_KAPPA_F64;
58
59#[cfg(test)]
60mod tests {
61    use super::*;
62
63    const MAX_LEVELS_FOR_U32_GEOMETRY: u8 = max_decomposition_levels(u32::MAX, u32::MAX);
64
65    #[test]
66    fn maximum_decomposition_level_compatibility_export_is_const() {
67        assert_eq!(MAX_LEVELS_FOR_U32_GEOMETRY, 31);
68    }
69
70    #[test]
71    fn f32_constants_match_existing_backend_rounding() {
72        assert_eq!(DWT97_ALPHA_F32.to_bits(), (-1.586_134_3f32).to_bits());
73        assert_eq!(DWT97_BETA_F32.to_bits(), (-0.052_980_117f32).to_bits());
74        assert_eq!(DWT97_GAMMA_F32.to_bits(), 0.882_911_1f32.to_bits());
75        assert_eq!(DWT97_DELTA_F32.to_bits(), 0.443_506_87f32.to_bits());
76        assert_eq!(DWT97_KAPPA_F32.to_bits(), 1.230_174_1f32.to_bits());
77        assert_eq!(
78            DWT97_INV_KAPPA_F32.to_bits(),
79            (1.0f32 / 1.230_174_1f32).to_bits()
80        );
81    }
82
83    #[test]
84    fn inverse_constants_are_exact_negations_of_forward_steps() {
85        assert_eq!(IDWT97_NEG_ALPHA_F32.to_bits(), (-DWT97_ALPHA_F32).to_bits());
86        assert_eq!(IDWT97_NEG_BETA_F32.to_bits(), (-DWT97_BETA_F32).to_bits());
87        assert_eq!(IDWT97_NEG_GAMMA_F32.to_bits(), (-DWT97_GAMMA_F32).to_bits());
88        assert_eq!(IDWT97_NEG_DELTA_F32.to_bits(), (-DWT97_DELTA_F32).to_bits());
89    }
90}