use std::fmt;
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum UnsupportedFeature {
ProgressiveJpeg,
ExtendedSequentialJpeg,
ArithmeticCodedJpeg,
LosslessJpeg,
HierarchicalJpeg,
JpegPrecision {
bits: u8,
},
JpegComponentCount {
components: u8,
},
JpegChromaSubsampling,
}
impl fmt::Display for UnsupportedFeature {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::ProgressiveJpeg => write!(f, "progressive JPEG (SOF2)"),
Self::ExtendedSequentialJpeg => {
write!(f, "extended sequential JPEG (SOF1)")
}
Self::ArithmeticCodedJpeg => write!(
f,
"arithmetic-coded JPEG (SOF9/SOF10/SOF11/SOF13/SOF14/SOF15)"
),
Self::LosslessJpeg => write!(f, "lossless JPEG (SOF3)"),
Self::HierarchicalJpeg => write!(f, "hierarchical JPEG (SOF5/SOF6/SOF7)"),
Self::JpegPrecision { bits } => {
write!(f, "JPEG sample precision {bits} (only 8-bit is supported)")
}
Self::JpegComponentCount { components } => {
write!(
f,
"JPEG component count {components} (only 1 or 3 are supported)"
)
}
Self::JpegChromaSubsampling => {
write!(f, "JPEG chroma subsampling that exceeds luma sampling rate")
}
}
}
}
#[derive(Debug)]
pub enum CodecError {
InsufficientCapacity {
image: (usize, usize),
tensor: (usize, usize),
},
UnsupportedDtype(edgefirst_tensor::DType),
UnsupportedFormat(edgefirst_tensor::PixelFormat),
Unsupported(UnsupportedFeature),
InvalidData(String),
Io(std::io::Error),
Tensor(edgefirst_tensor::Error),
}
impl fmt::Display for CodecError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::InsufficientCapacity { image, tensor } => write!(
f,
"image dimensions {}×{} exceed tensor capacity {}×{}",
image.0, image.1, tensor.0, tensor.1,
),
Self::UnsupportedDtype(dt) => {
write!(f, "unsupported tensor dtype {dt:?} for image decode")
}
Self::UnsupportedFormat(pf) => {
write!(f, "unsupported pixel format {pf:?} for image decode")
}
Self::Unsupported(feat) => write!(f, "unsupported image feature: {feat}"),
Self::InvalidData(msg) => write!(f, "invalid image data: {msg}"),
Self::Io(e) => write!(f, "I/O error: {e}"),
Self::Tensor(e) => write!(f, "tensor error: {e}"),
}
}
}
impl std::error::Error for CodecError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::Io(e) => Some(e),
Self::Tensor(e) => Some(e),
_ => None,
}
}
}
impl From<std::io::Error> for CodecError {
fn from(e: std::io::Error) -> Self {
Self::Io(e)
}
}
impl From<edgefirst_tensor::Error> for CodecError {
fn from(e: edgefirst_tensor::Error) -> Self {
Self::Tensor(e)
}
}
impl From<zune_png::error::PngDecodeErrors> for CodecError {
fn from(e: zune_png::error::PngDecodeErrors) -> Self {
Self::InvalidData(format!("PNG: {e}"))
}
}