Skip to main content

dicom_toolkit_jpeg2000/
error.rs

1//! Error types for JPEG 2000 decoding.
2
3use core::fmt;
4
5/// The main error type for JPEG 2000 decoding operations.
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub enum DecodeError {
8    /// Errors related to JP2 file format and box parsing.
9    Format(FormatError),
10    /// Errors related to codestream markers.
11    Marker(MarkerError),
12    /// Errors related to tile processing.
13    Tile(TileError),
14    /// Errors related to image dimensions and validation.
15    Validation(ValidationError),
16    /// Errors related to decoding operations.
17    Decoding(DecodingError),
18    /// Errors related to color space and component handling.
19    Color(ColorError),
20}
21
22/// Errors related to JP2 file format and box parsing.
23#[derive(Debug, Clone, Copy, PartialEq, Eq)]
24pub enum FormatError {
25    /// Invalid JP2 signature.
26    InvalidSignature,
27    /// Invalid JP2 file type.
28    InvalidFileType,
29    /// Invalid or malformed JP2 box.
30    InvalidBox,
31    /// Missing codestream data.
32    MissingCodestream,
33    /// Unsupported JP2 image format.
34    Unsupported,
35}
36
37/// Errors related to codestream markers.
38#[derive(Debug, Clone, Copy, PartialEq, Eq)]
39pub enum MarkerError {
40    /// Invalid marker encountered.
41    Invalid,
42    /// Unsupported marker encountered.
43    Unsupported,
44    /// Expected a specific marker.
45    Expected(&'static str),
46    /// Missing a required marker.
47    Missing(&'static str),
48    /// Failed to read or parse a marker.
49    ParseFailure(&'static str),
50}
51
52/// Errors related to tile processing.
53#[derive(Debug, Clone, Copy, PartialEq, Eq)]
54pub enum TileError {
55    /// Invalid image tile was encountered.
56    Invalid,
57    /// Invalid tile index in tile-part header.
58    InvalidIndex,
59    /// Invalid tile or image offsets.
60    InvalidOffsets,
61    /// PPT marker present when PPM marker exists in main header.
62    PpmPptConflict,
63}
64
65/// Errors related to image dimensions and validation.
66#[derive(Debug, Clone, Copy, PartialEq, Eq)]
67pub enum ValidationError {
68    /// Invalid image dimensions.
69    InvalidDimensions,
70    /// Image dimensions exceed supported limits.
71    ImageTooLarge,
72    /// Image has too many channels.
73    TooManyChannels,
74    /// Invalid component metadata.
75    InvalidComponentMetadata,
76    /// Invalid progression order.
77    InvalidProgressionOrder,
78    /// Invalid transformation type.
79    InvalidTransformation,
80    /// Invalid quantization style.
81    InvalidQuantizationStyle,
82    /// Missing exponents for precinct sizes.
83    MissingPrecinctExponents,
84    /// Not enough exponents provided in header.
85    InsufficientExponents,
86    /// Missing exponent step size.
87    MissingStepSize,
88    /// Invalid quantization exponents.
89    InvalidExponents,
90}
91
92/// Errors related to decoding operations.
93#[derive(Debug, Clone, Copy, PartialEq, Eq)]
94pub enum DecodingError {
95    /// An error occurred while decoding a code-block.
96    CodeBlockDecodeFailure,
97    /// The codestream uses a feature that this decoder does not implement yet.
98    UnsupportedFeature(&'static str),
99    /// Number of bitplanes in a code-block is too large.
100    TooManyBitplanes,
101    /// A code-block contains too many coding passes.
102    TooManyCodingPasses,
103    /// Invalid number of bitplanes in a code-block.
104    InvalidBitplaneCount,
105    /// A precinct was invalid.
106    InvalidPrecinct,
107    /// A progression iterator ver invalid.
108    InvalidProgressionIterator,
109    /// Unexpected end of data.
110    UnexpectedEof,
111}
112
113/// Errors related to color space and component handling.
114#[derive(Debug, Clone, Copy, PartialEq, Eq)]
115pub enum ColorError {
116    /// Multi-component transform failed.
117    Mct,
118    /// Failed to resolve palette indices.
119    PaletteResolutionFailed,
120    /// Failed to convert from sYCC to RGB.
121    SyccConversionFailed,
122    /// Failed to convert from LAB to RGB.
123    LabConversionFailed,
124}
125
126impl fmt::Display for DecodeError {
127    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
128        match self {
129            Self::Format(e) => write!(f, "{e}"),
130            Self::Marker(e) => write!(f, "{e}"),
131            Self::Tile(e) => write!(f, "{e}"),
132            Self::Validation(e) => write!(f, "{e}"),
133            Self::Decoding(e) => write!(f, "{e}"),
134            Self::Color(e) => write!(f, "{e}"),
135        }
136    }
137}
138
139impl fmt::Display for FormatError {
140    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
141        match self {
142            Self::InvalidSignature => write!(f, "invalid JP2 signature"),
143            Self::InvalidFileType => write!(f, "invalid JP2 file type"),
144            Self::InvalidBox => write!(f, "invalid JP2 box"),
145            Self::MissingCodestream => write!(f, "missing codestream data"),
146            Self::Unsupported => write!(f, "unsupported JP2 image"),
147        }
148    }
149}
150
151impl fmt::Display for MarkerError {
152    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
153        match self {
154            Self::Invalid => write!(f, "invalid marker"),
155            Self::Unsupported => write!(f, "unsupported marker"),
156            Self::Expected(marker) => write!(f, "expected {marker} marker"),
157            Self::Missing(marker) => write!(f, "missing {marker} marker"),
158            Self::ParseFailure(marker) => write!(f, "failed to parse {marker} marker"),
159        }
160    }
161}
162
163impl fmt::Display for TileError {
164    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
165        match self {
166            Self::Invalid => write!(f, "image contains no tiles"),
167            Self::InvalidIndex => write!(f, "invalid tile index in tile-part header"),
168            Self::InvalidOffsets => write!(f, "invalid tile offsets"),
169            Self::PpmPptConflict => {
170                write!(
171                    f,
172                    "PPT marker present when PPM marker exists in main header"
173                )
174            }
175        }
176    }
177}
178
179impl fmt::Display for ValidationError {
180    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
181        match self {
182            Self::InvalidDimensions => write!(f, "invalid image dimensions"),
183            Self::ImageTooLarge => write!(f, "image is too large"),
184            Self::TooManyChannels => write!(f, "image has too many channels"),
185            Self::InvalidComponentMetadata => write!(f, "invalid component metadata"),
186            Self::InvalidProgressionOrder => write!(f, "invalid progression order"),
187            Self::InvalidTransformation => write!(f, "invalid transformation type"),
188            Self::InvalidQuantizationStyle => write!(f, "invalid quantization style"),
189            Self::MissingPrecinctExponents => {
190                write!(f, "missing exponents for precinct sizes")
191            }
192            Self::InsufficientExponents => {
193                write!(f, "not enough exponents provided in header")
194            }
195            Self::MissingStepSize => write!(f, "missing exponent step size"),
196            Self::InvalidExponents => write!(f, "invalid quantization exponents"),
197        }
198    }
199}
200
201impl fmt::Display for DecodingError {
202    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
203        match self {
204            Self::CodeBlockDecodeFailure => write!(f, "failed to decode code-block"),
205            Self::UnsupportedFeature(feature) => {
206                write!(f, "unsupported decoding feature: {feature}")
207            }
208            Self::TooManyBitplanes => write!(f, "number of bitplanes is too large"),
209            Self::TooManyCodingPasses => {
210                write!(f, "code-block contains too many coding passes")
211            }
212            Self::InvalidBitplaneCount => write!(f, "invalid number of bitplanes"),
213            Self::InvalidPrecinct => write!(f, "a precinct was invalid"),
214            Self::InvalidProgressionIterator => {
215                write!(f, "a progression iterator was invalid")
216            }
217            Self::UnexpectedEof => write!(f, "unexpected end of data"),
218        }
219    }
220}
221
222impl fmt::Display for ColorError {
223    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
224        match self {
225            Self::Mct => write!(f, "multi-component transform failed"),
226            Self::PaletteResolutionFailed => write!(f, "failed to resolve palette indices"),
227            Self::SyccConversionFailed => write!(f, "failed to convert from sYCC to RGB"),
228            Self::LabConversionFailed => write!(f, "failed to convert from LAB to RGB"),
229        }
230    }
231}
232
233impl core::error::Error for DecodeError {}
234impl core::error::Error for FormatError {}
235impl core::error::Error for MarkerError {}
236impl core::error::Error for TileError {}
237impl core::error::Error for ValidationError {}
238impl core::error::Error for DecodingError {}
239impl core::error::Error for ColorError {}
240
241impl From<FormatError> for DecodeError {
242    fn from(e: FormatError) -> Self {
243        Self::Format(e)
244    }
245}
246
247impl From<MarkerError> for DecodeError {
248    fn from(e: MarkerError) -> Self {
249        Self::Marker(e)
250    }
251}
252
253impl From<TileError> for DecodeError {
254    fn from(e: TileError) -> Self {
255        Self::Tile(e)
256    }
257}
258
259impl From<ValidationError> for DecodeError {
260    fn from(e: ValidationError) -> Self {
261        Self::Validation(e)
262    }
263}
264
265impl From<DecodingError> for DecodeError {
266    fn from(e: DecodingError) -> Self {
267        Self::Decoding(e)
268    }
269}
270
271impl From<ColorError> for DecodeError {
272    fn from(e: ColorError) -> Self {
273        Self::Color(e)
274    }
275}
276
277/// Result type for JPEG 2000 decoding operations.
278pub type Result<T> = core::result::Result<T, DecodeError>;
279
280macro_rules! bail {
281    ($err:expr) => {
282        return Err($err.into())
283    };
284}
285
286macro_rules! err {
287    ($err:expr) => {
288        Err($err.into())
289    };
290}
291
292pub(crate) use bail;
293pub(crate) use err;