diff --git a/src/decoder/ifd.rs b/src/decoder/ifd.rs index 55775a0e..9be0d354 100644 --- a/src/decoder/ifd.rs +++ b/src/decoder/ifd.rs @@ -11,7 +11,7 @@ use crate::{TiffError, TiffFormatError, TiffResult}; use self::Value::{ Ascii, Byte, Double, Float, Ifd, IfdBig, List, Rational, RationalBig, SRational, SRationalBig, - Short, Signed, SignedBig, Unsigned, UnsignedBig, + Short, Signed, SignedBig, SignedByte, SignedShort, Unsigned, UnsignedBig, }; #[allow(unused_qualifications)] @@ -20,6 +20,8 @@ use self::Value::{ pub enum Value { Byte(u8), Short(u16), + SignedByte(i8), + SignedShort(i16), Signed(i32), SignedBig(i64), Unsigned(u32), @@ -43,6 +45,14 @@ impl Value { val => Err(TiffError::FormatError(TiffFormatError::ByteExpected(val))), } } + pub fn into_i8(self) -> TiffResult { + match self { + SignedByte(val) => Ok(val), + val => Err(TiffError::FormatError(TiffFormatError::SignedByteExpected( + val, + ))), + } + } pub fn into_u16(self) -> TiffResult { match self { @@ -55,6 +65,18 @@ impl Value { } } + pub fn into_i16(self) -> TiffResult { + match self { + SignedByte(val) => Ok(val.into()), + SignedShort(val) => Ok(val), + Signed(val) => Ok(i16::try_from(val)?), + SignedBig(val) => Ok(i16::try_from(val)?), + val => Err(TiffError::FormatError( + TiffFormatError::SignedShortExpected(val), + )), + } + } + pub fn into_u32(self) -> TiffResult { match self { Short(val) => Ok(val.into()), @@ -70,6 +92,8 @@ impl Value { pub fn into_i32(self) -> TiffResult { match self { + SignedByte(val) => Ok(val.into()), + SignedShort(val) => Ok(val.into()), Signed(val) => Ok(val), SignedBig(val) => Ok(i32::try_from(val)?), val => Err(TiffError::FormatError( @@ -93,6 +117,8 @@ impl Value { pub fn into_i64(self) -> TiffResult { match self { + SignedByte(val) => Ok(val.into()), + SignedShort(val) => Ok(val.into()), Signed(val) => Ok(val.into()), SignedBig(val) => Ok(val), val => Err(TiffError::FormatError( @@ -204,6 +230,8 @@ impl Value { } Ok(new_vec) } + SignedByte(val) => Ok(vec![val.into()]), + SignedShort(val) => Ok(vec![val.into()]), Signed(val) => Ok(vec![val]), SignedBig(val) => Ok(vec![i32::try_from(val)?]), SRational(numerator, denominator) => Ok(vec![numerator, denominator]), @@ -289,6 +317,8 @@ impl Value { } Ok(new_vec) } + SignedByte(val) => Ok(vec![val.into()]), + SignedShort(val) => Ok(vec![val.into()]), Signed(val) => Ok(vec![val.into()]), SignedBig(val) => Ok(vec![val]), SRational(numerator, denominator) => Ok(vec![numerator.into(), denominator.into()]), diff --git a/src/error.rs b/src/error.rs index c6fe8ed5..71fd972f 100644 --- a/src/error.rs +++ b/src/error.rs @@ -68,6 +68,8 @@ pub enum TiffFormatError { UnknownPredictor(u16), UnknownPlanarConfiguration(u16), ByteExpected(Value), + SignedByteExpected(Value), + SignedShortExpected(Value), UnsignedIntegerExpected(Value), SignedIntegerExpected(Value), Format(String), @@ -119,6 +121,8 @@ impl fmt::Display for TiffFormatError { write!(fmt, "Unknown planar configuration “{}” encountered", planar_config) } ByteExpected(ref val) => write!(fmt, "Expected byte, {:?} found.", val), + SignedByteExpected(ref val) => write!(fmt, "Expected signed byte, {:?} found.", val), + SignedShortExpected(ref val) => write!(fmt, "Expected signed short, {:?} found.", val), UnsignedIntegerExpected(ref val) => { write!(fmt, "Expected unsigned integer, {:?} found.", val) } diff --git a/tests/encode_images.rs b/tests/encode_images.rs index 57c569fa..532ed21c 100644 --- a/tests/encode_images.rs +++ b/tests/encode_images.rs @@ -188,7 +188,9 @@ macro_rules! test_roundtrip { } test_roundtrip!(test_u8_roundtrip, U8, u8); +test_roundtrip!(test_i8_roundtrip, I8, i8); test_roundtrip!(test_u16_roundtrip, U16, u16); +test_roundtrip!(test_i16_roundtrip, I16, i16); test_roundtrip!(test_u32_roundtrip, U32, u32); test_roundtrip!(test_u64_roundtrip, U64, u64); test_roundtrip!(test_f32_roundtrip, F32, f32); @@ -199,6 +201,11 @@ fn test_gray_u8_roundtrip() { test_u8_roundtrip::("minisblack-1c-8b.tiff", ColorType::Gray(8)); } +#[test] +fn test_gray_i8_roundtrip() { + test_i8_roundtrip::("minisblack-1c-i8b.tiff", ColorType::Gray(8)); +} + #[test] fn test_rgb_u8_roundtrip() { test_u8_roundtrip::("rgb-3c-8b.tiff", ColorType::RGB(8)); @@ -214,6 +221,11 @@ fn test_gray_u16_roundtrip() { test_u16_roundtrip::("minisblack-1c-16b.tiff", ColorType::Gray(16)); } +#[test] +fn test_gray_i16_roundtrip() { + test_i16_roundtrip::("minisblack-1c-i16b.tiff", ColorType::Gray(16)); +} + #[test] fn test_rgb_u16_roundtrip() { test_u16_roundtrip::("rgb-3c-16b.tiff", ColorType::RGB(16)); diff --git a/tests/images/minisblack-1c-i16b.tiff b/tests/images/minisblack-1c-i16b.tiff new file mode 100644 index 00000000..62c4ce6f Binary files /dev/null and b/tests/images/minisblack-1c-i16b.tiff differ diff --git a/tests/images/minisblack-1c-i8b.tiff b/tests/images/minisblack-1c-i8b.tiff new file mode 100644 index 00000000..e1449f95 Binary files /dev/null and b/tests/images/minisblack-1c-i8b.tiff differ