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.
255 lines
9.2 KiB
Rust
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>;
|