1use std::fmt;
7
8#[non_exhaustive]
14#[derive(Debug, Clone, PartialEq, Eq)]
15pub enum UnsupportedFeature {
16 ProgressiveJpeg,
18 ExtendedSequentialJpeg,
20 ArithmeticCodedJpeg,
23 LosslessJpeg,
25 HierarchicalJpeg,
27 JpegPrecision {
29 bits: u8,
31 },
32 JpegComponentCount {
35 components: u8,
37 },
38 PngNotEnabled,
40 JpegChromaSubsampling,
44}
45
46impl fmt::Display for UnsupportedFeature {
47 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
48 match self {
49 Self::ProgressiveJpeg => write!(f, "progressive JPEG (SOF2)"),
50 Self::ExtendedSequentialJpeg => {
51 write!(f, "extended sequential JPEG (SOF1)")
52 }
53 Self::ArithmeticCodedJpeg => write!(
54 f,
55 "arithmetic-coded JPEG (SOF9/SOF10/SOF11/SOF13/SOF14/SOF15)"
56 ),
57 Self::LosslessJpeg => write!(f, "lossless JPEG (SOF3)"),
58 Self::HierarchicalJpeg => write!(f, "hierarchical JPEG (SOF5/SOF6/SOF7)"),
59 Self::JpegPrecision { bits } => {
60 write!(f, "JPEG sample precision {bits} (only 8-bit is supported)")
61 }
62 Self::JpegComponentCount { components } => {
63 write!(
64 f,
65 "JPEG component count {components} (only 1 or 3 are supported)"
66 )
67 }
68 Self::PngNotEnabled => write!(
69 f,
70 "PNG decoding is not enabled in this build (enable the `png` feature)"
71 ),
72 Self::JpegChromaSubsampling => {
73 write!(f, "JPEG chroma subsampling that exceeds luma sampling rate")
74 }
75 }
76 }
77}
78
79#[derive(Debug)]
81pub enum CodecError {
82 InsufficientCapacity {
84 image: (usize, usize),
86 tensor: (usize, usize),
88 },
89 UnsupportedDtype(edgefirst_tensor::DType),
91 UnsupportedFormat(edgefirst_tensor::PixelFormat),
93 Unsupported(UnsupportedFeature),
98 InvalidData(String),
100 Io(std::io::Error),
102 Tensor(edgefirst_tensor::Error),
104}
105
106impl fmt::Display for CodecError {
107 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
108 match self {
109 Self::InsufficientCapacity { image, tensor } => write!(
110 f,
111 "image dimensions {}×{} exceed tensor capacity {}×{}",
112 image.0, image.1, tensor.0, tensor.1,
113 ),
114 Self::UnsupportedDtype(dt) => {
115 write!(f, "unsupported tensor dtype {dt:?} for image decode")
116 }
117 Self::UnsupportedFormat(pf) => {
118 write!(f, "unsupported pixel format {pf:?} for image decode")
119 }
120 Self::Unsupported(feat) => write!(f, "unsupported image feature: {feat}"),
121 Self::InvalidData(msg) => write!(f, "invalid image data: {msg}"),
122 Self::Io(e) => write!(f, "I/O error: {e}"),
123 Self::Tensor(e) => write!(f, "tensor error: {e}"),
124 }
125 }
126}
127
128impl std::error::Error for CodecError {
129 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
130 match self {
131 Self::Io(e) => Some(e),
132 Self::Tensor(e) => Some(e),
133 _ => None,
134 }
135 }
136}
137
138impl From<std::io::Error> for CodecError {
139 fn from(e: std::io::Error) -> Self {
140 Self::Io(e)
141 }
142}
143
144impl From<edgefirst_tensor::Error> for CodecError {
145 fn from(e: edgefirst_tensor::Error) -> Self {
146 Self::Tensor(e)
147 }
148}
149
150#[cfg(feature = "png")]
151impl From<zune_png::error::PngDecodeErrors> for CodecError {
152 fn from(e: zune_png::error::PngDecodeErrors) -> Self {
153 Self::InvalidData(format!("PNG: {e}"))
154 }
155}