Skip to main content

zenjxl_decoder/
error.rs

1// Copyright (c) the JPEG XL Project Authors. All rights reserved.
2//
3// Use of this source code is governed by a BSD-style
4// license that can be found in the LICENSE file.
5
6use 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    // FrameHeader format errors
105    #[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    // Generic arithmetic overflow. Prefer using other errors if possible.
136    #[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>;