Files
image-tiff/src/error.rs
T
A. Molzer 9a23090b6e Provide write_entry_bytes
This complements the entry API of the encoder with the byte slice based
method. Note we don't provide it for writing raw data, here a
`std::io::Write` would be more appropriate and we should not attempt to
make it `write_all`, nor compress. You'd get all the benefits of the
other API through `[u8]: TiffValue` since that interface is otherwise
type agnostic and `u8` specifically is endian agnostic.
2026-01-11 22:59:34 +01:00

255 lines
9.2 KiB
Rust

use std::io;
use std::str;
use std::string;
use quick_error::quick_error;
use crate::decoder::ChunkType;
use crate::tags::Type;
use crate::tags::{
CompressionMethod, PhotometricInterpretation, PlanarConfiguration, SampleFormat, Tag,
};
use crate::ColorType;
quick_error! {
/// Tiff error kinds.
#[derive(Debug)]
pub enum TiffError {
/// The Image is not formatted properly.
FormatError(err: TiffFormatError) {
display("format error: {err}")
from()
source(err)
}
/// The Decoder does not support features required by the image.
UnsupportedError(err: TiffUnsupportedError) {
display("unsupported error: {err}")
from()
source(err)
}
/// An I/O Error occurred while decoding the image.
IoError(err: io::Error) {
display("{err}")
from()
source(err)
}
/// The Limits of the Decoder is exceeded.
LimitsExceeded {
display("decoder limits exceeded")
}
/// An integer conversion to or from a platform size failed.
IntSizeError {
display("platform or format size limits exceeded")
}
/// The image does not support the requested operation
UsageError(err: UsageError) {
display("usage error: {err}")
from()
source(err)
}
}
}
quick_error! {
/// The image is not formatted properly.
///
/// This indicates that the encoder producing the image might behave incorrectly or that the
/// input file has been corrupted.
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub enum TiffFormatError {
TiffSignatureNotFound {
display("TIFF signature not found")
}
TiffSignatureInvalid {
display("TIFF signature invalid")
}
ImageFileDirectoryNotFound {
display("image file directory not found")
}
InconsistentSizesEncountered {
display("inconsistent sizes encountered")
}
InvalidDimensions(width: u32, height: u32) {
display("invalid dimensions: {width}x{height}")
}
InvalidTag {
display("image contains invalid tag")
}
InvalidTagValueType(tag: Tag) {
display("tag `{tag:?}` did not have the expected value type")
}
RequiredTagNotFound(tag: Tag) {
display("required tag `{tag:?}` not found")
}
UnknownPredictor(pred: u16) {
display("unknown predictor “{pred}” encountered")
}
UnknownPlanarConfiguration(cfg: u16) {
display("unknown planar configuration “{cfg}”")
}
InvalidTypeForTag {
display("tag has invalid type")
}
InvalidCountForTag(tag: Tag, len: usize) {
display("tag `{tag:?}` with incorrect number of elements ({len}) encountered")
}
StripTileTagConflict {
display("file should contain either (StripByteCounts and StripOffsets) or (TileByteCounts and TileOffsets), other combination was found")
}
CycleInOffsets {
display("file contained a cycle in the list of IFDs")
}
SamplesPerPixelIsZero {
display("samples per pixel is zero")
}
CompressedDataCorrupt(message: String) {
display("compressed data is corrupt: {message}")
}
}
}
quick_error! {
/// The Decoder does not support features required by the image.
///
/// This only captures known failures for which the standard either does not require support or an
/// implementation has been planned but not yet completed. Some variants may become unused over
/// time and will then get deprecated before being removed.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum TiffUnsupportedError {
FloatingPointPredictor(color_type: ColorType) {
display("floating point predictor for {color_type:?} is unsupported")
}
HorizontalPredictor(color_type: ColorType) {
display("horizontal predictor for {color_type:?} is unsupported")
}
InconsistentBitsPerSample(bits_per_sample: Vec<u8>) {
display("inconsistent bits per sample: {bits_per_sample:?}")
}
InterpretationWithBits(interpretation: PhotometricInterpretation, bits_per_sample: Vec<u8>) {
display("Photometric interpretation {interpretation:?} with bits per sample {bits_per_sample:?} is unsupported")
}
UnknownInterpretation {
display("unknown photometric interpretation")
}
UnknownCompressionMethod {
display("unknown compression method")
}
UnsupportedCompressionMethod(method: CompressionMethod) {
display("compression method {method:?} is unsupported")
}
UnsupportedSampleDepth(depth: u8) {
display("{depth} samples per pixel is unsupported")
}
UnsupportedSampleFormat(sample_format: Vec<SampleFormat>) {
display("sample format {sample_format:?} is unsupported")
}
UnsupportedColorType(color_type: ColorType) {
display("color type {color_type:?} is unsupported")
}
UnsupportedBitsPerChannel(bits_per_channel: u8) {
display("{bits_per_channel} bits per channel not supported")
}
UnsupportedPlanarConfig(planar: Option<PlanarConfiguration>) {
display("unsupported planar configuration “{planar:?}”")
}
UnsupportedDataType {
display("unsupported data type.")
}
UnsupportedInterpretation(interpretation: PhotometricInterpretation) {
display("unsupported photometric interpretation \"{interpretation:?}\"")
}
ChromaSubsampling {
display("chroma subsampling of YCbCr color is unsupported")
}
MisalignedTileBoundaries {
display("tile rows are not aligned to byte boundaries")
}
}
}
quick_error! {
/// User attempted to use the Decoder in a way that is incompatible with a specific image.
///
/// For example: attempting to read a tile from a stripped image.
#[derive(Debug)]
#[non_exhaustive]
pub enum UsageError {
InvalidChunkType(expected: ChunkType, actual: ChunkType) {
display("requested operation is only valid for images with chunk encoding of type {expected:?} but got {actual:?}")
}
InvalidChunkIndex(index: u32) {
display("invalid chunk index ({index}) requested")
}
InvalidPlaneIndex(index: u16) {
display("invalid plane index ({index}) requested")
}
InvalidCodingUnit(index: u32, have: u32) {
display("out of bounds coding unit ({index}) requested, only {have} available")
}
PredictorCompressionMismatch {
display("requested predictor is not compatible with the requested compression")
}
PredictorIncompatible {
display("the requested predictor is not compatible with the image's format")
}
PredictorUnavailable {
display("the requested predictor is not available")
}
InsufficientOutputBufferSize { needed: usize, provided: usize } {
display("the borrowed output buffer is not large enough for the decoded data, needed {needed} but have {provided}")
}
InsufficientOutputRowStride { needed: usize, requested: usize } {
display("the provided output row stride would alias rows of decoded data, needed {needed} but have {requested}")
}
ZeroIfdPointer {
display("the offset 0 can not point to a valid IFD")
}
ReconfiguredAfterImageWrite {
display("attempted to reconfigure the encoder after image writing has started")
}
ByteOrderMismatch {
display("attempted to use data with a byte order that does not match the required one")
}
MismatchedEntryLength {ty: Type, found: usize } {
display("the length of data is not a multiple of the size of the type {ty:?}, found {found}")
}
}
}
impl From<str::Utf8Error> for TiffError {
fn from(_err: str::Utf8Error) -> TiffError {
TiffError::FormatError(TiffFormatError::InvalidTag)
}
}
impl From<string::FromUtf8Error> for TiffError {
fn from(_err: string::FromUtf8Error) -> TiffError {
TiffError::FormatError(TiffFormatError::InvalidTag)
}
}
impl From<std::num::TryFromIntError> for TiffError {
fn from(_err: std::num::TryFromIntError) -> TiffError {
TiffError::IntSizeError
}
}
#[cfg(feature = "lzw")]
impl From<weezl::LzwError> for TiffError {
fn from(err: weezl::LzwError) -> TiffError {
TiffError::FormatError(TiffFormatError::CompressedDataCorrupt(err.to_string()))
}
}
#[cfg(feature = "jpeg")]
impl From<zune_jpeg::errors::DecodeErrors> for TiffError {
fn from(err: zune_jpeg::errors::DecodeErrors) -> Self {
TiffError::FormatError(TiffFormatError::CompressedDataCorrupt(err.to_string()))
}
}
/// Result of an image decoding/encoding process
pub type TiffResult<T> = Result<T, TiffError>;