// Copyright (c) the JPEG XL Project Authors. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. use std::collections::TryReserveError; use thiserror::Error; use crate::{ api::{JxlColorType, JxlDataFormat}, entropy_coding::huffman::HUFFMAN_MAX_BITS, features::spline::Point, image::DataTypeTag, }; #[derive(Error, Debug)] #[non_exhaustive] pub enum Error { #[error("Invalid raw quantization table")] InvalidRawQuantTable, #[error("Invalid distance band {0}: {1}")] InvalidDistanceBand(usize, f32), #[error("Invalid AFV bands")] InvalidAFVBands, #[error("Invalid quantization table weight: {0}")] InvalidQuantizationTableWeight(f32), #[error("Read out of bounds; size hint: {0}")] OutOfBounds(usize), #[error("Section is too short")] SectionTooShort, #[error("Non-zero padding bits")] NonZeroPadding, #[error("Invalid signature")] InvalidSignature, #[error("Invalid exponent_bits_per_sample: {0}")] InvalidExponent(u32), #[error("Invalid mantissa_bits: {0}")] InvalidMantissa(i32), #[error("Invalid bits_per_sample: {0}")] InvalidBitsPerSample(u32), #[error("Invalid enum value {0} for {1}")] InvalidEnum(u32, String), #[error("Value of dim_shift {0} is too large")] DimShiftTooLarge(u32), #[error("Float is NaN or Inf")] FloatNaNOrInf, #[error("Invalid gamma value: {0}")] InvalidGamma(f32), #[error("Invalid color encoding: no ICC and unknown TF / ColorSpace")] InvalidColorEncoding, #[error("Invalid color space: should be one of RGB, Gray or XYB")] InvalidColorSpace, #[error("Only perceptual rendering intent implemented for XYB ICC profile.")] InvalidRenderingIntent, #[error("Invalid intensity_target: {0}")] InvalidIntensityTarget(f32), #[error("Invalid min_nits: {0}")] InvalidMinNits(f32), #[error("Invalid linear_below {1}, relative_to_max_display is {0}")] InvalidLinearBelow(bool, f32), #[error("Overflow when computing a bitstream size")] SizeOverflow, #[error("Invalid ISOBMMF container")] InvalidBox, #[error("ICC is too large")] IccTooLarge, #[error("Invalid ICC stream: unexpected end of stream")] IccEndOfStream, #[error("Invalid ICC stream")] InvalidIccStream, #[error("Invalid HybridUintConfig: {0} {1} {2:?}")] InvalidUintConfig(u32, u32, Option), #[error("LZ77 enabled when explicitly disallowed")] Lz77Disallowed, #[error("LZ77 repeat symbol encountered without decoding any symbols")] UnexpectedLz77Repeat, #[error("Huffman alphabet too large: {0}, max is {max}", max = 1 << HUFFMAN_MAX_BITS)] AlphabetTooLargeHuff(usize), #[error("Invalid Huffman code")] InvalidHuffman, #[error("Invalid ANS histogram")] InvalidAnsHistogram, #[error("ANS stream checksum mismatch")] AnsChecksumMismatch, #[error("Integer too large: nbits {0} > 29")] IntegerTooLarge(u32), #[error("Invalid context map: context id {0} > 255")] InvalidContextMap(u32), #[error("Invalid context map: number of histogram {0}, number of distinct histograms {1}")] InvalidContextMapHole(u32, u32), #[error( "Invalid permutation: skipped elements {skip} and encoded elements {end} don't fit in permutation of size {size}" )] InvalidPermutationSize { size: u32, skip: u32, end: u32 }, #[error( "Invalid permutation: Lehmer code {lehmer} out of bounds in permutation of size {size} at index {idx}" )] InvalidPermutationLehmerCode { size: u32, idx: u32, lehmer: u32 }, #[error("Invalid quant encoding mode")] InvalidQuantEncodingMode, #[error("Invalid quant encoding with mode {mode} and required size {required_size}")] InvalidQuantEncoding { mode: u8, required_size: usize }, // FrameHeader format errors #[error("Invalid extra channel upsampling: upsampling: {0} dim_shift: {1} ec_upsampling: {2}")] InvalidEcUpsampling(u32, u32, u32), #[error("Invalid lf level in UseLFFrame frame: {0}")] InvalidLfLevel(u32), #[error("Num_ds: {0} should be smaller than num_passes: {1}")] NumPassesTooLarge(u32, u32), #[error("Passes::downsample is non-decreasing")] PassesDownsampleNonDecreasing, #[error("Passes::last_pass is non-increasing")] PassesLastPassNonIncreasing, #[error("Passes::last_pass has too large elements")] PassesLastPassTooLarge, #[error("Non-patch reference frame with a crop")] NonPatchReferenceWithCrop, #[error("Non-444 chroma subsampling is not allowed when adaptive DC smoothing is enabled")] Non444ChromaSubsampling, #[error("Non-444 chroma subsampling is not allowed for bigger than 8x8 transforms")] InvalidBlockSizeForChromaSubsampling, #[error("Out of memory: {0}")] OutOfMemory(#[from] TryReserveError), #[error("Out of memory when allocating image of byte size {0}x{1}")] ImageOutOfMemory(usize, usize), #[error("Image size too large: {0}x{1}")] ImageSizeTooLarge(usize, usize), #[error("Image dimension too large: {0}")] ImageDimensionTooLarge(u64), #[error("Invalid image size: {0}x{1}")] InvalidImageSize(usize, usize), // Generic arithmetic overflow. Prefer using other errors if possible. #[error("Arithmetic overflow")] ArithmeticOverflow, #[error("Empty frame sequence")] NoFrames, #[error( "Pipeline channel type mismatch: stage {0} channel {1}, expected {2:?} but found {3:?}" )] PipelineChannelTypeMismatch(String, usize, DataTypeTag, DataTypeTag), #[error("Invalid stage {0} after extend stage")] PipelineInvalidStageAfterExtend(String), #[error("Channel {0} was not used in the render pipeline")] PipelineChannelUnused(usize), #[error("Trying to copy rects of different size, src: {0}x{1} dst {2}x{3}")] CopyOfDifferentSize(usize, usize, usize, usize), #[error("LF quantization factor is too small: {0}")] LfQuantFactorTooSmall(f32), #[error("HF quantization factor is too small: {0}")] HfQuantFactorTooSmall(f32), #[error("Invalid modular mode predictor: {0}")] InvalidPredictor(u32), #[error("Invalid modular mode property: {0}")] InvalidProperty(u32), #[error("Invalid alpha channel for blending: {0}, limit is {1}")] InvalidBlendingAlphaChannel(usize, usize), #[error("Invalid alpha channel for blending: {0}, limit is {1}")] PatchesInvalidAlphaChannel(usize, usize), #[error("Invalid patch blend mode: {0}, limit is {1}")] PatchesInvalidBlendMode(u8, u8), #[error("Invalid Patch: negative {0}-coordinate: {1} base {0}, {2} delta {0}")] PatchesInvalidDelta(String, usize, i32), #[error( "Invalid position specified in reference frame in {0}-coordinate: {0}0 + {0}size = {1} + {2} > {3} = reference_frame {0}size" )] PatchesInvalidPosition(String, usize, usize, usize), #[error("Patches invalid reference frame at index {0}")] PatchesInvalidReference(usize), #[error("Invalid Patch {0}: at {1} + {2} > {3}")] PatchesOutOfBounds(String, usize, usize, usize), #[error("Patches cannot use frames saved post color transforms")] PatchesPostColorTransform(), #[error("Too many {0}: {1}, limit is {2}")] PatchesTooMany(String, usize, usize), #[error("Reference too large: {0}, limit is {1}")] PatchesRefTooLarge(usize, usize), #[error("Point list is empty")] PointListEmpty, #[error("Too large area for spline: {0}, limit is {1}")] SplinesAreaTooLarge(u64, u64), #[error("Too large manhattan_distance reached: {0}, limit is {1}")] SplinesDistanceTooLarge(u64, u64), #[error("Too many splines: {0}, limit is {1}")] SplinesTooMany(u32, u32), #[error("Spline has adjacent coinciding control points: point[{0}]: {1:?}, point[{2}]: {3:?}")] SplineAdjacentCoincidingControlPoints(usize, Point, usize, Point), #[error("Too many control points for splines: {0}, limit is {1}")] SplinesTooManyControlPoints(u32, u32), #[error( "Spline point outside valid bounds: coordinates: {0:?}, out of bounds: {1}, bounds: {2:?}" )] SplinesPointOutOfRange(Point, i32, std::ops::Range), #[error("Spline coordinates out of bounds: {0}, limit is {1}")] SplinesCoordinatesLimit(isize, isize), #[error("Spline delta-delta is out of bounds: {0}, limit is {1}")] SplinesDeltaLimit(i64, i64), #[error("Modular tree too large: {0}, limit is {1}")] TreeTooLarge(usize, usize), #[error("Modular tree too tall: {0}, limit is {1}")] TreeTooTall(usize, usize), #[error("Modular tree multiplier too large: {0}, limit is {1}")] TreeMultiplierTooLarge(u32, u32), #[error("Modular tree multiplier too large: {0}, multiplier log is {1}")] TreeMultiplierBitsTooLarge(u32, u32), #[error( "Modular tree splits on property {0} at value {1}, which is outside the possible range of [{2}, {3}]" )] TreeSplitOnEmptyRange(u8, i32, i32, i32), #[error("Modular stream requested a global tree but there isn't one")] NoGlobalTree, #[error("Invalid transform id")] InvalidTransformId, #[error("Invalid RCT type {0}")] InvalidRCT(u32), #[error("Invalid channel range: {0}..{1}, {2} total channels")] InvalidChannelRange(usize, usize, usize), #[error("Invalid transform: mixing different channels (different shape or different shift)")] MixingDifferentChannels, #[error("Invalid transform: squeezing meta-channels needs an in-place transform")] MetaSqueezeRequiresInPlace, #[error("Invalid transform: too many squeezes (shift > 30)")] TooManySqueezes, #[error("Invalid BlockConextMap: too big: num_lf_context: {0}, num_qf_thresholds: {1}")] BlockContextMapSizeTooBig(usize, usize), #[error("Invalid BlockConextMap: too many distinct contexts.")] TooManyBlockContexts, #[error("Base color correlation out of range.")] BaseColorCorrelationOutOfRange, #[error("Invalid EPF sharpness param {0}")] InvalidEpfValue(i32), #[error("Invalid VarDCT transform type {0}")] InvalidVarDCTTransform(usize), #[error("Invalid VarDCT transform map")] InvalidVarDCTTransformMap, #[error("VarDCT transform overflows HF group")] HFBlockOutOfBounds, #[error("Invalid AC: nonzeros {0} is too large for {1} 8x8 blocks")] InvalidNumNonZeros(usize, usize), #[error("Invalid AC: {0} nonzeros after decoding block")] EndOfBlockResidualNonZeros(usize), #[error("Unknown transfer function for ICC profile")] TransferFunctionUnknown, #[error("Attempting to write out of Bounds when writing ICC")] IccWriteOutOfBounds, #[error("Invalid tag string when writing ICC: {0}")] IccInvalidTagString(String), #[error("Invalid text for ICC MLuc string, not ascii: {0}")] IccMlucTextNotAscii(String), #[error("ICC value is out of range / NaN: {0}")] IccValueOutOfRangeS15Fixed16(f32), #[error("Y value is too small: {0}")] IccInvalidWhitePointY(f32), #[error("{2}: wx: {0}, wy: {1}")] IccInvalidWhitePoint(f32, f32, String), #[error("Determinant is zero or too small, matrix is close to singular: |det| = {0}.")] MatrixInversionFailed(f64), #[error("Unsupported transfer function when writing ICC")] IccUnsupportedTransferFunction, #[error("Table size too large when writing ICC: {0}")] IccTableSizeExceeded(usize), #[error("Invalid CMS configuration: requested ICC but no CMS is configured")] ICCOutputNoCMS, #[error("Non-XYB image requires CMS to convert to different output color profile")] NonXybOutputNoCMS, #[error("I/O error: {0}")] IOError(#[from] std::io::Error), #[error("Wrong buffer count: {0} buffers given, {1} buffers expected")] WrongBufferCount(usize, usize), #[error("Image is not grayscale, but grayscale output was requested")] NotGrayscale, #[error("Invalid output buffer byte size {0}x{1} for {2}x{3} image with type {4:?} {5:?}")] InvalidOutputBufferSize(usize, usize, usize, usize, JxlColorType, JxlDataFormat), #[error("Attempting to save channels with different downsample amounts: {0:?} and {1:?}")] SaveDifferentDownsample((u8, u8), (u8, u8)), #[error("Image has {0} extra channels, more than the maximum of 256")] TooManyExtraChannels(usize), #[error( "CMS transform increases channel count from {in_channels} to {out_channels}, which is not supported" )] CmsChannelCountIncrease { in_channels: usize, out_channels: usize, }, #[error( "Cannot output extra channel {channel_index} ({channel_type:?}): it was consumed by CMS color conversion" )] CmsConsumedChannelRequested { channel_index: usize, channel_type: String, }, #[error("CMS error: {0}")] CmsError(String), } pub type Result = std::result::Result;