Repository: image-rs/image-tiff (rust)

Issue:
Tags of type Short are read as Unsigned
When reading a tag that fits into the offset field and is of type `SHORT` (Tiff type 3) the value is returned as `Value::Unsigned` instead of `Value::Short`.

I believe the issue lies in [line 407 of ifd.rs](https://github.com/image-rs/image-tiff/blob/aefea7786f038417632f72d861c0bf32bf6299ba/src/decoder/ifd.rs#LL407C18-L407C18).

The right behavior is what can be seen when multiple values are handled ([line 475 of ifd.rs](https://github.com/image-rs/image-tiff/blob/aefea7786f038417632f72d861c0bf32bf6299ba/src/decoder/ifd.rs#L475))

Pull request:
Read Short as u16, SignedShort as i16
Previously, Short values were read incorrectly as `u32` instead of `u16`, and SignedShort values were read incorrectly as `i32` instead of `i16`.

This PR does the following:
- Add `TiffFormatError::ShortExpected` enum variant
- Correctly cast `Type::SHORT` as u16 values, and support casting Short to other unsigned types via the `into_u32_vec` and `into_u64_vec` methods.
- Correctly cast `Type::SSHORT` as i16 values

Fixes #204

Patch:
diff --git a/src/decoder/ifd.rs b/src/decoder/ifd.rs
index 9be0d35..93134a5 100644
--- a/src/decoder/ifd.rs
+++ b/src/decoder/ifd.rs
@@ -59,9 +59,7 @@ impl Value {
             Short(val) => Ok(val),
             Unsigned(val) => Ok(u16::try_from(val)?),
             UnsignedBig(val) => Ok(u16::try_from(val)?),
-            val => Err(TiffError::FormatError(
-                TiffFormatError::UnsignedIntegerExpected(val),
-            )),
+            val => Err(TiffError::FormatError(TiffFormatError::ShortExpected(val))),
         }
     }
 
@@ -163,6 +161,7 @@ impl Value {
                 }
                 Ok(new_vec)
             }
+            Short(val) => Ok(vec![val.into()]),
             Unsigned(val) => Ok(vec![val]),
             UnsignedBig(val) => Ok(vec![u32::try_from(val)?]),
             Rational(numerator, denominator) => Ok(vec![numerator, denominator]),
@@ -205,9 +204,7 @@ impl Value {
                 Ok(new_vec)
             }
             Short(val) => Ok(vec![val]),
-            val => Err(TiffError::FormatError(
-                TiffFormatError::UnsignedIntegerExpected(val),
-            )),
+            val => Err(TiffError::FormatError(TiffFormatError::ShortExpected(val))),
         }
     }
 
@@ -285,6 +282,7 @@ impl Value {
                 }
                 Ok(new_vec)
             }
+            Short(val) => Ok(vec![val.into()]),
             Unsigned(val) => Ok(vec![val.into()]),
             UnsignedBig(val) => Ok(vec![val]),
             Rational(numerator, denominator) => Ok(vec![numerator.into(), denominator.into()]),
@@ -433,8 +431,8 @@ impl Entry {
                 Type::BYTE => Unsigned(u32::from(self.offset[0])),
                 Type::SBYTE => Signed(i32::from(self.offset[0] as i8)),
                 Type::UNDEFINED => Byte(self.offset[0]),
-                Type::SHORT => Unsigned(u32::from(self.r(bo).read_u16()?)),
-                Type::SSHORT => Signed(i32::from(self.r(bo).read_i16()?)),
+                Type::SHORT => Short(self.r(bo).read_u16()?),
+                Type::SSHORT => SignedShort(self.r(bo).read_i16()?),
                 Type::LONG => Unsigned(self.r(bo).read_u32()?),
                 Type::SLONG => Signed(self.r(bo).read_i32()?),
                 Type::FLOAT => Float(self.r(bo).read_f32()?),
@@ -509,7 +507,7 @@ impl Entry {
                     let mut r = self.r(bo);
                     let mut v = Vec::new();
                     for _ in 0..self.count {
-                        v.push(Signed(i32::from(r.read_i16()?)));
+                        v.push(SignedShort(r.read_i16()?));
                     }
                     return Ok(List(v));
                 }
@@ -569,10 +567,10 @@ impl Entry {
                 Ok(SignedBig(i64::from(reader.read_i8()?)))
             }),
             Type::SHORT => self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| {
-                Ok(UnsignedBig(u64::from(reader.read_u16()?)))
+                Ok(Short(reader.read_u16()?))
             }),
             Type::SSHORT => self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| {
-                Ok(SignedBig(i64::from(reader.read_i16()?)))
+                Ok(SignedShort(reader.read_i16()?))
             }),
             Type::LONG => self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| {
                 Ok(Unsigned(reader.read_u32()?))
diff --git a/src/error.rs b/src/error.rs
index 955da67..8cd3fdd 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -69,6 +69,7 @@ pub enum TiffFormatError {
     UnknownPlanarConfiguration(u16),
     ByteExpected(Value),
     SignedByteExpected(Value),
+    ShortExpected(Value),
     SignedShortExpected(Value),
     UnsignedIntegerExpected(Value),
     SignedIntegerExpected(Value),
@@ -122,6 +123,7 @@ impl fmt::Display for TiffFormatError {
             }
             ByteExpected(ref val) => write!(fmt, "Expected byte, {:?} found.", val),
             SignedByteExpected(ref val) => write!(fmt, "Expected signed byte, {:?} found.", val),
+            ShortExpected(ref val) => write!(fmt, "Expected short, {:?} found.", val),
             SignedShortExpected(ref val) => write!(fmt, "Expected signed short, {:?} found.", val),
             UnsignedIntegerExpected(ref val) => {
                 write!(fmt, "Expected unsigned integer, {:?} found.", val)


Test patch:
diff --git a/tests/encode_images.rs b/tests/encode_images.rs
index ee1e3c0..a5b4091 100644
--- a/tests/encode_images.rs
+++ b/tests/encode_images.rs
@@ -50,28 +50,28 @@ fn encode_decode() {
                 (
                     Tag::BitsPerSample,
                     ifd::Value::List(vec![
-                        ifd::Value::UnsignedBig(8),
-                        ifd::Value::UnsignedBig(8),
-                        ifd::Value::UnsignedBig(8)
+                        ifd::Value::Short(8),
+                        ifd::Value::Short(8),
+                        ifd::Value::Short(8)
                     ])
                 ),
-                (Tag::Compression, ifd::Value::Unsigned(1)),
-                (Tag::PhotometricInterpretation, ifd::Value::Unsigned(2)),
+                (Tag::Compression, ifd::Value::Short(1)),
+                (Tag::PhotometricInterpretation, ifd::Value::Short(2)),
                 (Tag::StripOffsets, ifd::Value::Unsigned(8)),
-                (Tag::SamplesPerPixel, ifd::Value::Unsigned(3)),
+                (Tag::SamplesPerPixel, ifd::Value::Short(3)),
                 (Tag::RowsPerStrip, ifd::Value::Unsigned(3334)),
                 (Tag::StripByteCounts, ifd::Value::Unsigned(30000)),
                 (Tag::XResolution, ifd::Value::Rational(1, 1)),
                 (Tag::YResolution, ifd::Value::Rational(1, 1)),
-                (Tag::ResolutionUnit, ifd::Value::Unsigned(1)),
+                (Tag::ResolutionUnit, ifd::Value::Short(1)),
                 (Tag::Artist, ifd::Value::Ascii("Image-tiff".into())),
-                (Tag::Predictor, ifd::Value::Unsigned(1)),
+                (Tag::Predictor, ifd::Value::Short(1)),
                 (
                     Tag::SampleFormat,
                     ifd::Value::List(vec![
-                        ifd::Value::UnsignedBig(1),
-                        ifd::Value::UnsignedBig(1),
-                        ifd::Value::UnsignedBig(1)
+                        ifd::Value::Short(1),
+                        ifd::Value::Short(1),
+                        ifd::Value::Short(1)
                     ])
                 ),
             ]
@@ -135,17 +135,17 @@ fn encode_decode_big() {
                         ifd::Value::Short(8)
                     ])
                 ),
-                (Tag::Compression, ifd::Value::Unsigned(1)),
-                (Tag::PhotometricInterpretation, ifd::Value::Unsigned(2)),
+                (Tag::Compression, ifd::Value::Short(1)),
+                (Tag::PhotometricInterpretation, ifd::Value::Short(2)),
                 (Tag::StripOffsets, ifd::Value::UnsignedBig(16)),
-                (Tag::SamplesPerPixel, ifd::Value::Unsigned(3)),
+                (Tag::SamplesPerPixel, ifd::Value::Short(3)),
                 (Tag::RowsPerStrip, ifd::Value::Unsigned(3334)),
                 (Tag::StripByteCounts, ifd::Value::UnsignedBig(30000)),
                 (Tag::XResolution, ifd::Value::Rational(1, 1)),
                 (Tag::YResolution, ifd::Value::Rational(1, 1)),
-                (Tag::ResolutionUnit, ifd::Value::Unsigned(1)),
+                (Tag::ResolutionUnit, ifd::Value::Short(1)),
                 (Tag::Artist, ifd::Value::Ascii("Image-tiff".into())),
-                (Tag::Predictor, ifd::Value::Unsigned(1)),
+                (Tag::Predictor, ifd::Value::Short(1)),
                 (
                     Tag::SampleFormat,
                     ifd::Value::List(vec![