jxl_vardct/
dct_select.rs

1/// Varblock transform types.
2#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
3#[repr(u8)]
4pub enum TransformType {
5    Dct8 = 0,
6    Hornuss,
7    Dct2,
8    Dct4,
9    Dct16,
10    Dct32,
11    Dct16x8,
12    Dct8x16,
13    Dct32x8,
14    Dct8x32,
15    Dct32x16,
16    Dct16x32,
17    Dct4x8,
18    Dct8x4,
19    Afv0,
20    Afv1,
21    Afv2,
22    Afv3,
23    Dct64,
24    Dct64x32,
25    Dct32x64,
26    Dct128,
27    Dct128x64,
28    Dct64x128,
29    Dct256,
30    Dct256x128,
31    Dct128x256,
32}
33
34impl TryFrom<u8> for TransformType {
35    type Error = jxl_bitstream::Error;
36
37    fn try_from(value: u8) -> jxl_bitstream::Result<Self> {
38        if value <= TransformType::Dct128x256 as u8 {
39            // SAFETY: TransformType is repr(u8) and all value <= Dct128x256 is valid
40            Ok(unsafe { std::mem::transmute::<u8, Self>(value) })
41        } else {
42            Err(jxl_bitstream::Error::InvalidEnum {
43                name: "TransformType",
44                value: value as u32,
45            })
46        }
47    }
48}
49
50impl TransformType {
51    /// Returns the size of the transform type, in 8x8 blocks.
52    pub fn dct_select_size(self) -> (u32, u32) {
53        use TransformType::*;
54
55        match self {
56            Dct8 | Hornuss | Dct2 | Dct4 | Dct4x8 | Dct8x4 | Afv0 | Afv1 | Afv2 | Afv3 => (1, 1),
57            Dct16 => (2, 2),
58            Dct32 => (4, 4),
59            Dct16x8 => (1, 2),
60            Dct8x16 => (2, 1),
61            Dct32x8 => (1, 4),
62            Dct8x32 => (4, 1),
63            Dct32x16 => (2, 4),
64            Dct16x32 => (4, 2),
65            Dct64 => (8, 8),
66            Dct64x32 => (4, 8),
67            Dct32x64 => (8, 4),
68            Dct128 => (16, 16),
69            Dct128x64 => (8, 16),
70            Dct64x128 => (16, 8),
71            Dct256 => (32, 32),
72            Dct256x128 => (16, 32),
73            Dct128x256 => (32, 16),
74        }
75    }
76
77    pub(crate) fn dequant_matrix_param_index(self) -> u32 {
78        use TransformType::*;
79
80        match self {
81            Dct8 => 0,
82            Hornuss => 1,
83            Dct2 => 2,
84            Dct4 => 3,
85            Dct16 => 4,
86            Dct32 => 5,
87            Dct16x8 | Dct8x16 => 6,
88            Dct32x8 | Dct8x32 => 7,
89            Dct32x16 | Dct16x32 => 8,
90            Dct4x8 | Dct8x4 => 9,
91            Afv0 | Afv1 | Afv2 | Afv3 => 10,
92            Dct64 => 11,
93            Dct64x32 | Dct32x64 => 12,
94            Dct128 => 13,
95            Dct128x64 | Dct64x128 => 14,
96            Dct256 => 15,
97            Dct256x128 | Dct128x256 => 16,
98        }
99    }
100
101    pub(crate) fn dequant_matrix_size(self) -> (u32, u32) {
102        use TransformType::*;
103
104        match self {
105            Dct8 | Hornuss | Dct2 | Dct4 | Dct4x8 | Dct8x4 | Afv0 | Afv1 | Afv2 | Afv3 => (8, 8),
106            Dct16 => (16, 16),
107            Dct32 => (32, 32),
108            Dct16x8 | Dct8x16 => (16, 8),
109            Dct32x8 | Dct8x32 => (32, 8),
110            Dct32x16 | Dct16x32 => (32, 16),
111            Dct64 => (64, 64),
112            Dct64x32 | Dct32x64 => (64, 32),
113            Dct128 => (128, 128),
114            Dct128x64 | Dct64x128 => (128, 64),
115            Dct256 => (256, 256),
116            Dct256x128 | Dct128x256 => (256, 128),
117        }
118    }
119
120    pub(crate) fn order_id(self) -> u32 {
121        use TransformType::*;
122
123        match self {
124            Dct8 => 0,
125            Hornuss | Dct2 | Dct4 | Dct4x8 | Dct8x4 | Afv0 | Afv1 | Afv2 | Afv3 => 1,
126            Dct16 => 2,
127            Dct32 => 3,
128            Dct16x8 | Dct8x16 => 4,
129            Dct32x8 | Dct8x32 => 5,
130            Dct32x16 | Dct16x32 => 6,
131            Dct64 => 7,
132            Dct64x32 | Dct32x64 => 8,
133            Dct128 => 9,
134            Dct128x64 | Dct64x128 => 10,
135            Dct256 => 11,
136            Dct256x128 | Dct128x256 => 12,
137        }
138    }
139
140    /// Returns whether DCT coefficients should be transposed.
141    #[inline]
142    pub fn need_transpose(&self) -> bool {
143        use TransformType::*;
144
145        if matches!(
146            self,
147            Hornuss | Dct2 | Dct4 | Dct4x8 | Dct8x4 | Afv0 | Afv1 | Afv2 | Afv3
148        ) {
149            false
150        } else {
151            let (w, h) = self.dct_select_size();
152            h >= w
153        }
154    }
155}