Skip to main content

j2k_types/packetization/
progression.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2
3//! Packet progression order and descriptor ordering.
4
5use super::J2kPacketizationPacketDescriptor;
6
7/// JPEG 2000 packet progression order.
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum J2kPacketizationProgressionOrder {
10    /// Layer-resolution-component-position progression.
11    Lrcp,
12    /// Resolution-layer-component-position progression.
13    Rlcp,
14    /// Resolution-position-component-layer progression.
15    Rpcl,
16    /// Position-component-resolution-layer progression.
17    Pcrl,
18    /// Component-position-resolution-layer progression.
19    Cprl,
20}
21
22impl J2kPacketizationProgressionOrder {
23    /// Return the JPEG 2000 COD progression-order byte for this order.
24    pub const fn codestream_order_code(self) -> u8 {
25        match self {
26            Self::Lrcp => 0x00,
27            Self::Rlcp => 0x01,
28            Self::Rpcl => 0x02,
29            Self::Pcrl => 0x03,
30            Self::Cprl => 0x04,
31        }
32    }
33}
34
35/// Sort explicit packet descriptors according to a JPEG 2000 progression order.
36///
37/// Position-major orders require precinct indices with a common spatial order
38/// across the compared components and resolutions. This helper has no geometry
39/// with which to map differing precinct grids onto the reference grid.
40pub fn sort_packet_descriptors_for_progression(
41    descriptors: &mut [J2kPacketizationPacketDescriptor],
42    progression_order: J2kPacketizationProgressionOrder,
43) {
44    match progression_order {
45        J2kPacketizationProgressionOrder::Lrcp => descriptors.sort_by_key(|descriptor| {
46            (
47                descriptor.layer,
48                descriptor.resolution,
49                descriptor.component,
50                descriptor.precinct,
51            )
52        }),
53        J2kPacketizationProgressionOrder::Rlcp => descriptors.sort_by_key(|descriptor| {
54            (
55                descriptor.resolution,
56                descriptor.layer,
57                descriptor.component,
58                descriptor.precinct,
59            )
60        }),
61        J2kPacketizationProgressionOrder::Rpcl => descriptors.sort_by_key(|descriptor| {
62            (
63                descriptor.resolution,
64                descriptor.precinct,
65                descriptor.component,
66                descriptor.layer,
67            )
68        }),
69        J2kPacketizationProgressionOrder::Pcrl => descriptors.sort_by_key(|descriptor| {
70            (
71                descriptor.precinct,
72                descriptor.component,
73                descriptor.resolution,
74                descriptor.layer,
75            )
76        }),
77        J2kPacketizationProgressionOrder::Cprl => descriptors.sort_by_key(|descriptor| {
78            (
79                descriptor.component,
80                descriptor.precinct,
81                descriptor.resolution,
82                descriptor.layer,
83            )
84        }),
85    }
86}
87
88#[cfg(test)]
89mod tests {
90    use super::{
91        sort_packet_descriptors_for_progression, J2kPacketizationPacketDescriptor,
92        J2kPacketizationProgressionOrder,
93    };
94
95    fn descriptors() -> [J2kPacketizationPacketDescriptor; 3] {
96        [
97            J2kPacketizationPacketDescriptor {
98                packet_index: 0,
99                state_index: 0,
100                layer: 1,
101                resolution: 0,
102                component: 2,
103                precinct: 1,
104            },
105            J2kPacketizationPacketDescriptor {
106                packet_index: 1,
107                state_index: 1,
108                layer: 0,
109                resolution: 1,
110                component: 1,
111                precinct: 0,
112            },
113            J2kPacketizationPacketDescriptor {
114                packet_index: 2,
115                state_index: 2,
116                layer: 0,
117                resolution: 0,
118                component: 0,
119                precinct: 2,
120            },
121        ]
122    }
123
124    #[test]
125    fn progression_order_codes_match_codestream_values() {
126        assert_eq!(
127            J2kPacketizationProgressionOrder::Lrcp.codestream_order_code(),
128            0
129        );
130        assert_eq!(
131            J2kPacketizationProgressionOrder::Rlcp.codestream_order_code(),
132            1
133        );
134        assert_eq!(
135            J2kPacketizationProgressionOrder::Rpcl.codestream_order_code(),
136            2
137        );
138        assert_eq!(
139            J2kPacketizationProgressionOrder::Pcrl.codestream_order_code(),
140            3
141        );
142        assert_eq!(
143            J2kPacketizationProgressionOrder::Cprl.codestream_order_code(),
144            4
145        );
146    }
147
148    #[test]
149    fn packet_descriptor_sort_uses_requested_progression_order() {
150        let mut lrcp = descriptors();
151        sort_packet_descriptors_for_progression(&mut lrcp, J2kPacketizationProgressionOrder::Lrcp);
152        assert_eq!(lrcp.map(|descriptor| descriptor.packet_index), [2, 1, 0]);
153
154        let mut pcrl = descriptors();
155        sort_packet_descriptors_for_progression(&mut pcrl, J2kPacketizationProgressionOrder::Pcrl);
156        assert_eq!(pcrl.map(|descriptor| descriptor.packet_index), [1, 0, 2]);
157    }
158}