1use std::collections::TryReserveError;
7
8use thiserror::Error;
9
10use crate::{
11 api::{JxlColorType, JxlDataFormat},
12 entropy_coding::huffman::HUFFMAN_MAX_BITS,
13 features::spline::Point,
14 image::DataTypeTag,
15};
16
17#[derive(Error, Debug)]
18#[non_exhaustive]
19pub enum Error {
20 #[error("Invalid raw quantization table")]
21 InvalidRawQuantTable,
22 #[error("Invalid distance band {0}: {1}")]
23 InvalidDistanceBand(usize, f32),
24 #[error("Invalid AFV bands")]
25 InvalidAFVBands,
26 #[error("Invalid quantization table weight: {0}")]
27 InvalidQuantizationTableWeight(f32),
28 #[error("Read out of bounds; size hint: {0}")]
29 OutOfBounds(usize),
30 #[error("Section is too short")]
31 SectionTooShort,
32 #[error("Non-zero padding bits")]
33 NonZeroPadding,
34 #[error("Invalid signature")]
35 InvalidSignature,
36 #[error("Invalid exponent_bits_per_sample: {0}")]
37 InvalidExponent(u32),
38 #[error("Invalid mantissa_bits: {0}")]
39 InvalidMantissa(i32),
40 #[error("Invalid bits_per_sample: {0}")]
41 InvalidBitsPerSample(u32),
42 #[error("Invalid enum value {0} for {1}")]
43 InvalidEnum(u32, String),
44 #[error("Value of dim_shift {0} is too large")]
45 DimShiftTooLarge(u32),
46 #[error("Float is NaN or Inf")]
47 FloatNaNOrInf,
48 #[error("Invalid gamma value: {0}")]
49 InvalidGamma(f32),
50 #[error("Invalid color encoding: no ICC and unknown TF / ColorSpace")]
51 InvalidColorEncoding,
52 #[error("Invalid color space: should be one of RGB, Gray or XYB")]
53 InvalidColorSpace,
54 #[error("Only perceptual rendering intent implemented for XYB ICC profile.")]
55 InvalidRenderingIntent,
56 #[error("Invalid intensity_target: {0}")]
57 InvalidIntensityTarget(f32),
58 #[error("Invalid min_nits: {0}")]
59 InvalidMinNits(f32),
60 #[error("Invalid linear_below {1}, relative_to_max_display is {0}")]
61 InvalidLinearBelow(bool, f32),
62 #[error("Overflow when computing a bitstream size")]
63 SizeOverflow,
64 #[error("Invalid ISOBMMF container")]
65 InvalidBox,
66 #[error("ICC is too large")]
67 IccTooLarge,
68 #[error("Invalid ICC stream: unexpected end of stream")]
69 IccEndOfStream,
70 #[error("Invalid ICC stream")]
71 InvalidIccStream,
72 #[error("Invalid HybridUintConfig: {0} {1} {2:?}")]
73 InvalidUintConfig(u32, u32, Option<u32>),
74 #[error("LZ77 enabled when explicitly disallowed")]
75 Lz77Disallowed,
76 #[error("LZ77 repeat symbol encountered without decoding any symbols")]
77 UnexpectedLz77Repeat,
78 #[error("Huffman alphabet too large: {0}, max is {max}", max = 1 << HUFFMAN_MAX_BITS)]
79 AlphabetTooLargeHuff(usize),
80 #[error("Invalid Huffman code")]
81 InvalidHuffman,
82 #[error("Invalid ANS histogram")]
83 InvalidAnsHistogram,
84 #[error("ANS stream checksum mismatch")]
85 AnsChecksumMismatch,
86 #[error("Integer too large: nbits {0} > 29")]
87 IntegerTooLarge(u32),
88 #[error("Invalid context map: context id {0} > 255")]
89 InvalidContextMap(u32),
90 #[error("Invalid context map: number of histogram {0}, number of distinct histograms {1}")]
91 InvalidContextMapHole(u32, u32),
92 #[error(
93 "Invalid permutation: skipped elements {skip} and encoded elements {end} don't fit in permutation of size {size}"
94 )]
95 InvalidPermutationSize { size: u32, skip: u32, end: u32 },
96 #[error(
97 "Invalid permutation: Lehmer code {lehmer} out of bounds in permutation of size {size} at index {idx}"
98 )]
99 InvalidPermutationLehmerCode { size: u32, idx: u32, lehmer: u32 },
100 #[error("Invalid quant encoding mode")]
101 InvalidQuantEncodingMode,
102 #[error("Invalid quant encoding with mode {mode} and required size {required_size}")]
103 InvalidQuantEncoding { mode: u8, required_size: usize },
104 #[error("Invalid extra channel upsampling: upsampling: {0} dim_shift: {1} ec_upsampling: {2}")]
106 InvalidEcUpsampling(u32, u32, u32),
107 #[error("Patches with mixed upsampling not supported: color {0}, ec {1}")]
108 PatchesUnsupportedMixedUpsampling(u32, u32),
109 #[error("Invalid lf level in UseLFFrame frame: {0}")]
110 InvalidLfLevel(u32),
111 #[error("Num_ds: {0} should be smaller than num_passes: {1}")]
112 NumPassesTooLarge(u32, u32),
113 #[error("Passes::downsample is non-decreasing")]
114 PassesDownsampleNonDecreasing,
115 #[error("Passes::last_pass is non-increasing")]
116 PassesLastPassNonIncreasing,
117 #[error("Passes::last_pass has too large elements")]
118 PassesLastPassTooLarge,
119 #[error("Non-patch reference frame with a crop")]
120 NonPatchReferenceWithCrop,
121 #[error("Non-444 chroma subsampling is not allowed when adaptive DC smoothing is enabled")]
122 Non444ChromaSubsampling,
123 #[error("Non-444 chroma subsampling is not allowed for bigger than 8x8 transforms")]
124 InvalidBlockSizeForChromaSubsampling,
125 #[error("Out of memory: {0}")]
126 OutOfMemory(#[from] TryReserveError),
127 #[error("Out of memory when allocating image of byte size {0}x{1}")]
128 ImageOutOfMemory(usize, usize),
129 #[error("Image size too large: {0}x{1}")]
130 ImageSizeTooLarge(usize, usize),
131 #[error("Image dimension too large: {0}")]
132 ImageDimensionTooLarge(u64),
133 #[error("Invalid image size: {0}x{1}")]
134 InvalidImageSize(usize, usize),
135 #[error("Arithmetic overflow")]
137 ArithmeticOverflow,
138 #[error(
139 "Pipeline channel type mismatch: stage {0} channel {1}, expected {2:?} but found {3:?}"
140 )]
141 PipelineChannelTypeMismatch(String, usize, DataTypeTag, DataTypeTag),
142 #[error("Invalid stage {0} after extend stage")]
143 PipelineInvalidStageAfterExtend(String),
144 #[error("Trying to copy rects of different size, src: {0}x{1} dst {2}x{3}")]
145 CopyOfDifferentSize(usize, usize, usize, usize),
146 #[error("LF quantization factor is too small: {0}")]
147 LfQuantFactorTooSmall(f32),
148 #[error("HF quantization factor is too small: {0}")]
149 HfQuantFactorTooSmall(f32),
150 #[error("Invalid modular mode predictor: {0}")]
151 InvalidPredictor(u32),
152 #[error("Invalid modular mode property: {0}")]
153 InvalidProperty(u32),
154 #[error("Invalid alpha channel for blending: {0}, limit is {1}")]
155 InvalidBlendingAlphaChannel(usize, usize),
156 #[error("Invalid alpha channel for blending: {0}, limit is {1}")]
157 PatchesInvalidAlphaChannel(usize, usize),
158 #[error("Invalid patch blend mode: {0}, limit is {1}")]
159 PatchesInvalidBlendMode(u8, u8),
160 #[error("Invalid Patch: negative {0}-coordinate: {1} base {0}, {2} delta {0}")]
161 PatchesInvalidDelta(String, usize, i32),
162 #[error(
163 "Invalid position specified in reference frame in {0}-coordinate: {0}0 + {0}size = {1} + {2} > {3} = reference_frame {0}size"
164 )]
165 PatchesInvalidPosition(String, usize, usize, usize),
166 #[error("Patches invalid reference frame at index {0}")]
167 PatchesInvalidReference(usize),
168 #[error("Invalid Patch {0}: at {1} + {2} > {3}")]
169 PatchesOutOfBounds(String, usize, usize, usize),
170 #[error("Patches cannot use frames saved post color transforms")]
171 PatchesPostColorTransform(),
172 #[error("Too many {0}: {1}, limit is {2}")]
173 PatchesTooMany(String, usize, usize),
174 #[error("Reference too large: {0}, limit is {1}")]
175 PatchesRefTooLarge(usize, usize),
176 #[error("Point list is empty")]
177 PointListEmpty,
178 #[error("Too large area for spline: {0}, limit is {1}")]
179 SplinesAreaTooLarge(u64, u64),
180 #[error("Too large manhattan_distance reached: {0}, limit is {1}")]
181 SplinesDistanceTooLarge(u64, u64),
182 #[error("Too many splines: {0}, limit is {1}")]
183 SplinesTooMany(u32, u32),
184 #[error("Spline has adjacent coinciding control points: point[{0}]: {1:?}, point[{2}]: {3:?}")]
185 SplineAdjacentCoincidingControlPoints(usize, Point, usize, Point),
186 #[error("Too many control points for splines: {0}, limit is {1}")]
187 SplinesTooManyControlPoints(u32, u32),
188 #[error(
189 "Spline point outside valid bounds: coordinates: {0:?}, out of bounds: {1}, bounds: {2:?}"
190 )]
191 SplinesPointOutOfRange(Point, i32, std::ops::Range<i32>),
192 #[error("Spline coordinates out of bounds: {0}, limit is {1}")]
193 SplinesCoordinatesLimit(isize, isize),
194 #[error("Spline delta-delta is out of bounds: {0}, limit is {1}")]
195 SplinesDeltaLimit(i64, i64),
196 #[error("Modular tree too large: {0}, limit is {1}")]
197 TreeTooLarge(usize, usize),
198 #[error("Modular tree too tall: {0}, limit is {1}")]
199 TreeTooTall(usize, usize),
200 #[error("Modular tree multiplier too large: {0}, limit is {1}")]
201 TreeMultiplierTooLarge(u32, u32),
202 #[error("Modular tree multiplier too large: {0}, multiplier log is {1}")]
203 TreeMultiplierBitsTooLarge(u32, u32),
204 #[error(
205 "Modular tree splits on property {0} at value {1}, which is outside the possible range of [{2}, {3}]"
206 )]
207 TreeSplitOnEmptyRange(u8, i32, i32, i32),
208 #[error("Modular stream requested a global tree but there isn't one")]
209 NoGlobalTree,
210 #[error("Invalid transform id")]
211 InvalidTransformId,
212 #[error("Invalid RCT type {0}")]
213 InvalidRCT(u32),
214 #[error("Invalid channel range: {0}..{1}, {2} total channels")]
215 InvalidChannelRange(usize, usize, usize),
216 #[error("Invalid transform: mixing different channels (different shape or different shift)")]
217 MixingDifferentChannels,
218 #[error("Invalid transform: squeezing meta-channels needs an in-place transform")]
219 MetaSqueezeRequiresInPlace,
220 #[error("Invalid transform: too many squeezes (shift > 30)")]
221 TooManySqueezes,
222 #[error("Invalid BlockConextMap: too big: num_lf_context: {0}, num_qf_thresholds: {1}")]
223 BlockContextMapSizeTooBig(usize, usize),
224 #[error("Invalid BlockConextMap: too many distinct contexts.")]
225 TooManyBlockContexts,
226 #[error("Base color correlation out of range.")]
227 BaseColorCorrelationOutOfRange,
228 #[error("Invalid EPF sharpness param {0}")]
229 InvalidEpfValue(i32),
230 #[error("Invalid VarDCT transform type {0}")]
231 InvalidVarDCTTransform(usize),
232 #[error("Invalid VarDCT transform map")]
233 InvalidVarDCTTransformMap,
234 #[error("VarDCT transform overflows HF group")]
235 HFBlockOutOfBounds,
236 #[error("Invalid AC: nonzeros {0} is too large for {1} 8x8 blocks")]
237 InvalidNumNonZeros(usize, usize),
238 #[error("Invalid AC: {0} nonzeros after decoding block")]
239 EndOfBlockResidualNonZeros(usize),
240 #[error("Unknown transfer function for ICC profile")]
241 TransferFunctionUnknown,
242 #[error("Attempting to write out of Bounds when writing ICC")]
243 IccWriteOutOfBounds,
244 #[error("Invalid tag string when writing ICC: {0}")]
245 IccInvalidTagString(String),
246 #[error("Invalid text for ICC MLuc string, not ascii: {0}")]
247 IccMlucTextNotAscii(String),
248 #[error("ICC value is out of range / NaN: {0}")]
249 IccValueOutOfRangeS15Fixed16(f32),
250 #[error("Y value is too small: {0}")]
251 IccInvalidWhitePointY(f32),
252 #[error("{2}: wx: {0}, wy: {1}")]
253 IccInvalidWhitePoint(f32, f32, String),
254 #[error("Determinant is zero or too small, matrix is close to singular: |det| = {0}.")]
255 MatrixInversionFailed(f64),
256 #[error("Unsupported transfer function when writing ICC")]
257 IccUnsupportedTransferFunction,
258 #[error("Table size too large when writing ICC: {0}")]
259 IccTableSizeExceeded(usize),
260 #[error("Invalid CMS configuration: requested ICC but no CMS is configured")]
261 ICCOutputNoCMS,
262 #[error("Non-XYB image requires CMS to convert to different output color profile")]
263 NonXybOutputNoCMS,
264 #[error("I/O error: {0}")]
265 IOError(#[from] std::io::Error),
266 #[error("Wrong buffer count: {0} buffers given, {1} buffers expected")]
267 WrongBufferCount(usize, usize),
268 #[error("Image is not grayscale, but grayscale output was requested")]
269 NotGrayscale,
270 #[error("Invalid output buffer byte size {0}x{1} for {2}x{3} image with type {4:?} {5:?}")]
271 InvalidOutputBufferSize(usize, usize, usize, usize, JxlColorType, JxlDataFormat),
272 #[error("Attempting to save channels with different downsample amounts: {0:?} and {1:?}")]
273 SaveDifferentDownsample((u8, u8), (u8, u8)),
274 #[error("Image has {0} extra channels, more than the maximum of 256")]
275 TooManyExtraChannels(usize),
276 #[error(
277 "CMS transform increases channel count from {in_channels} to {out_channels}, which is not supported"
278 )]
279 CmsChannelCountIncrease {
280 in_channels: usize,
281 out_channels: usize,
282 },
283 #[error(
284 "Cannot output extra channel {channel_index} ({channel_type:?}): it was consumed by CMS color conversion"
285 )]
286 CmsConsumedChannelRequested {
287 channel_index: usize,
288 channel_type: String,
289 },
290 #[error("CMS error: {0}")]
291 CmsError(String),
292 #[error("Security limit exceeded: {resource} is {actual}, limit is {limit}")]
293 LimitExceeded {
294 resource: &'static str,
295 actual: u64,
296 limit: u64,
297 },
298 #[error("Decoding cancelled")]
299 Cancelled,
300 #[cfg(feature = "jpeg")]
301 #[error("Invalid JBRD box: {0}")]
302 InvalidJbrd(String),
303 #[error("Invalid gain map bundle (jhgm): {0}")]
304 InvalidGainMap(String),
305}
306
307impl From<enough::StopReason> for Error {
308 fn from(reason: enough::StopReason) -> Self {
309 match reason {
310 enough::StopReason::Cancelled | enough::StopReason::TimedOut | _ => Error::Cancelled,
311 }
312 }
313}
314
315pub type Result<T, E = Error> = std::result::Result<T, E>;