1 use std::error::Error; 2 use std::fmt; 3 use std::io; 4 use std::string; 5 6 use crate::decoder::ifd::Value; 7 use crate::tags::{ 8 CompressionMethod, PhotometricInterpretation, PlanarConfiguration, SampleFormat, Tag, 9 }; 10 use crate::ColorType; 11 use miniz_oxide::inflate::TINFLStatus; 12 13 /// Tiff error kinds. 14 #[derive(Debug)] 15 pub enum TiffError { 16 /// The Image is not formatted properly. 17 FormatError(TiffFormatError), 18 19 /// The Decoder does not support features required by the image. 20 UnsupportedError(TiffUnsupportedError), 21 22 /// An I/O Error occurred while decoding the image. 23 IoError(io::Error), 24 25 /// The Limits of the Decoder is exceeded. 26 LimitsExceeded, 27 28 /// An integer conversion to or from a platform size failed, either due to 29 /// limits of the platform size or limits of the format. 30 IntSizeError, 31 } 32 33 /// The image is not formatted properly. 34 /// 35 /// This indicates that the encoder producing the image might behave incorrectly or that the input 36 /// file has been corrupted. 37 /// 38 /// The list of variants may grow to incorporate errors of future features. Matching against this 39 /// exhaustively is not covered by interface stability guarantees. 40 #[derive(Debug, Clone, PartialEq)] 41 pub enum TiffFormatError { 42 TiffSignatureNotFound, 43 TiffSignatureInvalid, 44 ImageFileDirectoryNotFound, 45 InconsistentSizesEncountered, 46 UnexpectedCompressedData { 47 actual_bytes: usize, 48 required_bytes: usize, 49 }, 50 InconsistentStripSamples { 51 actual_samples: usize, 52 required_samples: usize, 53 }, 54 InvalidTag, 55 InvalidTagValueType(Tag), 56 RequiredTagNotFound(Tag), 57 UnknownPredictor(u16), 58 ByteExpected(Value), 59 UnsignedIntegerExpected(Value), 60 SignedIntegerExpected(Value), 61 InflateError(InflateError), 62 Format(String), 63 RequiredTagEmpty(Tag), 64 #[doc(hidden)] 65 /// Do not match against this variant. It may get removed. 66 __NonExhaustive, 67 } 68 69 impl fmt::Display for TiffFormatError { 70 fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { 71 use self::TiffFormatError::*; 72 match *self { 73 TiffSignatureNotFound => write!(fmt, "TIFF signature not found."), 74 TiffSignatureInvalid => write!(fmt, "TIFF signature invalid."), 75 ImageFileDirectoryNotFound => write!(fmt, "Image file directory not found."), 76 InconsistentSizesEncountered => write!(fmt, "Inconsistent sizes encountered."), 77 UnexpectedCompressedData { 78 actual_bytes, 79 required_bytes, 80 } => { 81 write!( 82 fmt, 83 "Decompression returned different amount of bytes than expected: got {}, expected {}.", 84 actual_bytes, required_bytes 85 ) 86 } 87 InconsistentStripSamples { 88 actual_samples, 89 required_samples, 90 } => { 91 write!( 92 fmt, 93 "Inconsistent elements in strip: got {}, expected {}.", 94 actual_samples, required_samples 95 ) 96 } 97 InvalidTag => write!(fmt, "Image contains invalid tag."), 98 InvalidTagValueType(ref tag) => { 99 write!(fmt, "Tag `{:?}` did not have the expected value type.", tag) 100 } 101 RequiredTagNotFound(ref tag) => write!(fmt, "Required tag `{:?}` not found.", tag), 102 UnknownPredictor(ref predictor) => { 103 write!(fmt, "Unknown predictor “{}” encountered", predictor) 104 } 105 ByteExpected(ref val) => write!(fmt, "Expected byte, {:?} found.", val), 106 UnsignedIntegerExpected(ref val) => { 107 write!(fmt, "Expected unsigned integer, {:?} found.", val) 108 } 109 SignedIntegerExpected(ref val) => { 110 write!(fmt, "Expected signed integer, {:?} found.", val) 111 } 112 InflateError(_) => write!(fmt, "Failed to decode inflate data."), 113 Format(ref val) => write!(fmt, "Invalid format: {:?}.", val), 114 RequiredTagEmpty(ref val) => write!(fmt, "Required tag {:?} was empty.", val), 115 __NonExhaustive => unreachable!(), 116 } 117 } 118 } 119 120 /// Decompression failed due to faulty compressed data. 121 #[derive(Debug, Clone, PartialEq, Eq, Hash)] 122 pub struct InflateError { 123 status: TINFLStatus, 124 } 125 126 impl InflateError { 127 pub(crate) fn new(status: TINFLStatus) -> Self { 128 Self { status } 129 } 130 } 131 132 impl TiffError { 133 pub(crate) fn from_inflate_status(status: TINFLStatus) -> Self { 134 TiffError::FormatError(TiffFormatError::InflateError(InflateError::new(status))) 135 } 136 } 137 138 /// The Decoder does not support features required by the image. 139 /// 140 /// This only captures known failures for which the standard either does not require support or an 141 /// implementation has been planned but not yet completed. Some variants may become unused over 142 /// time and will then get deprecated before being removed. 143 /// 144 /// The list of variants may grow. Matching against this exhaustively is not covered by interface 145 /// stability guarantees. 146 #[derive(Debug, Clone, PartialEq, Eq, Hash)] 147 pub enum TiffUnsupportedError { 148 HorizontalPredictor(ColorType), 149 InterpretationWithBits(PhotometricInterpretation, Vec<u8>), 150 UnknownInterpretation, 151 UnknownCompressionMethod, 152 UnsupportedCompressionMethod(CompressionMethod), 153 UnsupportedSampleDepth(u8), 154 UnsupportedSampleFormat(Vec<SampleFormat>), 155 UnsupportedColorType(ColorType), 156 UnsupportedBitsPerChannel(u8), 157 UnsupportedPlanarConfig(Option<PlanarConfiguration>), 158 UnsupportedDataType, 159 #[doc(hidden)] 160 /// Do not match against this variant. It may get removed. 161 __NonExhaustive, 162 } 163 164 impl fmt::Display for TiffUnsupportedError { 165 fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { 166 use self::TiffUnsupportedError::*; 167 match *self { 168 HorizontalPredictor(color_type) => write!( 169 fmt, 170 "Horizontal predictor for {:?} is unsupported.", 171 color_type 172 ), 173 InterpretationWithBits(ref photometric_interpretation, ref bits_per_sample) => write!( 174 fmt, 175 "{:?} with {:?} bits per sample is unsupported", 176 photometric_interpretation, bits_per_sample 177 ), 178 UnknownInterpretation => write!( 179 fmt, 180 "The image is using an unknown photometric interpretation." 181 ), 182 UnknownCompressionMethod => write!(fmt, "Unknown compression method."), 183 UnsupportedCompressionMethod(method) => { 184 write!(fmt, "Compression method {:?} is unsupported", method) 185 } 186 UnsupportedSampleDepth(samples) => { 187 write!(fmt, "{} samples per pixel is unsupported.", samples) 188 } 189 UnsupportedSampleFormat(ref formats) => { 190 write!(fmt, "Sample format {:?} is unsupported.", formats) 191 } 192 UnsupportedColorType(color_type) => { 193 write!(fmt, "Color type {:?} is unsupported", color_type) 194 } 195 UnsupportedBitsPerChannel(bits) => { 196 write!(fmt, "{} bits per channel not supported", bits) 197 } 198 UnsupportedPlanarConfig(config) => { 199 write!(fmt, "Unsupported planar configuration “{:?}”.", config) 200 } 201 UnsupportedDataType => write!(fmt, "Unsupported data type."), 202 __NonExhaustive => unreachable!(), 203 } 204 } 205 } 206 207 impl fmt::Display for TiffError { 208 fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { 209 match *self { 210 TiffError::FormatError(ref e) => write!(fmt, "Format error: {}", e), 211 TiffError::UnsupportedError(ref f) => write!( 212 fmt, 213 "The Decoder does not support the \ 214 image format `{}`", 215 f 216 ), 217 TiffError::IoError(ref e) => e.fmt(fmt), 218 TiffError::LimitsExceeded => write!(fmt, "The Decoder limits are exceeded"), 219 TiffError::IntSizeError => write!(fmt, "Platform or format size limits exceeded"), 220 } 221 } 222 } 223 224 impl Error for TiffError { 225 fn description(&self) -> &str { 226 match *self { 227 TiffError::FormatError(..) => "Format error", 228 TiffError::UnsupportedError(..) => "Unsupported error", 229 TiffError::IoError(..) => "IO error", 230 TiffError::LimitsExceeded => "Decoder limits exceeded", 231 TiffError::IntSizeError => "Platform or format size limits exceeded", 232 } 233 } 234 235 fn cause(&self) -> Option<&dyn Error> { 236 match *self { 237 TiffError::IoError(ref e) => Some(e), 238 _ => None, 239 } 240 } 241 } 242 243 impl From<io::Error> for TiffError { 244 fn from(err: io::Error) -> TiffError { 245 TiffError::IoError(err) 246 } 247 } 248 249 impl From<string::FromUtf8Error> for TiffError { 250 fn from(_err: string::FromUtf8Error) -> TiffError { 251 TiffError::FormatError(TiffFormatError::InvalidTag) 252 } 253 } 254 255 impl From<TiffFormatError> for TiffError { 256 fn from(err: TiffFormatError) -> TiffError { 257 TiffError::FormatError(err) 258 } 259 } 260 261 impl From<TiffUnsupportedError> for TiffError { 262 fn from(err: TiffUnsupportedError) -> TiffError { 263 TiffError::UnsupportedError(err) 264 } 265 } 266 267 impl From<std::num::TryFromIntError> for TiffError { 268 fn from(_err: std::num::TryFromIntError) -> TiffError { 269 TiffError::IntSizeError 270 } 271 } 272 273 /// Result of an image decoding/encoding process 274 pub type TiffResult<T> = Result<T, TiffError>; 275