From 978808578690dba1a01f4d2396ecac258947218b Mon Sep 17 00:00:00 2001 From: HagaiHargil Date: Wed, 21 Oct 2020 17:17:23 +0300 Subject: [PATCH 1/7] Int16 support --- src/bytecast.rs | 2 +- src/decoder/mod.rs | 71 ++++++++++++++++++++++++++++++++++++++----- src/decoder/stream.rs | 18 +++++++++++ 3 files changed, 83 insertions(+), 8 deletions(-) diff --git a/src/bytecast.rs b/src/bytecast.rs index 906ac79..40e5fe5 100644 --- a/src/bytecast.rs +++ b/src/bytecast.rs @@ -25,7 +25,7 @@ macro_rules! integral_slice_as_bytes{($int:ty, $const:ident $(,$mut:ident)*) => integral_slice_as_bytes!(i8, i8_as_ne_bytes); integral_slice_as_bytes!(u16, u16_as_ne_bytes, u16_as_ne_mut_bytes); -integral_slice_as_bytes!(i16, i16_as_ne_bytes); +integral_slice_as_bytes!(i16, i16_as_ne_bytes, i16_as_ne_mut_bytes); integral_slice_as_bytes!(u32, u32_as_ne_bytes, u32_as_ne_mut_bytes); integral_slice_as_bytes!(i32, i32_as_ne_bytes); integral_slice_as_bytes!(u64, u64_as_ne_bytes, u64_as_ne_mut_bytes); diff --git a/src/decoder/mod.rs b/src/decoder/mod.rs index 6ff7163..d715ee5 100644 --- a/src/decoder/mod.rs +++ b/src/decoder/mod.rs @@ -32,6 +32,8 @@ pub enum DecodingResult { F32(Vec), /// A vector of 64 bit IEEE floats F64(Vec), + /// A vector of 16 bit signed ints + I16(Vec), } impl DecodingResult { @@ -83,6 +85,15 @@ impl DecodingResult { } } + fn new_i16(size: usize, limits: &Limits) -> TiffResult { + if size > limits.decoding_buffer_size / 2 { + Err(TiffError::LimitsExceeded) + } else { + Ok(DecodingResult::I16(vec![0; size])) + } + } + + pub fn as_buffer(&mut self, start: usize) -> DecodingBuffer { match *self { DecodingResult::U8(ref mut buf) => DecodingBuffer::U8(&mut buf[start..]), @@ -91,6 +102,7 @@ impl DecodingResult { DecodingResult::U64(ref mut buf) => DecodingBuffer::U64(&mut buf[start..]), DecodingResult::F32(ref mut buf) => DecodingBuffer::F32(&mut buf[start..]), DecodingResult::F64(ref mut buf) => DecodingBuffer::F64(&mut buf[start..]), + DecodingResult::I16(ref mut buf) => DecodingBuffer::I16(&mut buf[start..]), } } } @@ -109,6 +121,8 @@ pub enum DecodingBuffer<'a> { F32(&'a mut [f32]), /// A slice of 64 bit IEEE floats F64(&'a mut [f64]), + /// A slice of 16 bits signed ints + I16(&'a mut [i16]), } impl<'a> DecodingBuffer<'a> { @@ -120,6 +134,7 @@ impl<'a> DecodingBuffer<'a> { DecodingBuffer::U64(ref buf) => buf.len(), DecodingBuffer::F32(ref buf) => buf.len(), DecodingBuffer::F64(ref buf) => buf.len(), + DecodingBuffer::I16(ref buf) => buf.len(), } } @@ -131,6 +146,7 @@ impl<'a> DecodingBuffer<'a> { DecodingBuffer::U64(_) => 8, DecodingBuffer::F32(_) => 4, DecodingBuffer::F64(_) => 8, + DecodingBuffer::I16(_) => 2, } } @@ -145,6 +161,7 @@ impl<'a> DecodingBuffer<'a> { DecodingBuffer::U64(ref mut buf) => DecodingBuffer::U64(buf), DecodingBuffer::F32(ref mut buf) => DecodingBuffer::F32(buf), DecodingBuffer::F64(ref mut buf) => DecodingBuffer::F64(buf), + DecodingBuffer::I16(ref mut buf) => DecodingBuffer::I16(buf), } } } @@ -257,6 +274,24 @@ impl Wrapping for u64 { } } +impl Wrapping for f32 { + fn wrapping_add(&self, other: Self) -> Self { + self + other + } +} + +impl Wrapping for f64 { + fn wrapping_add(&self, other: Self) -> Self { + self + other + } +} + +impl Wrapping for i16 { + fn wrapping_add(&self, other: Self) -> Self { + i16::wrapping_add(*self, other) + } +} + fn rev_hpredict_nsamp(image: &mut [T], size: (u32, u32), samples: usize) -> TiffResult<()> where T: Copy + Wrapping, @@ -320,6 +355,9 @@ fn rev_hpredict(image: DecodingBuffer, size: (u32, u32), color_type: ColorType) TiffUnsupportedError::HorizontalPredictor(color_type), )); } + DecodingBuffer::I16(buf) => { + rev_hpredict_nsamp(buf, size, samples)?; + } } Ok(()) } @@ -872,6 +910,13 @@ impl Decoder { reader.read_u64_into(&mut buffer[..bytes / 8])?; bytes / 8 } + (ColorType::RGBA(16), DecodingBuffer::I16(ref mut buffer)) + | (ColorType::RGB(16), DecodingBuffer::I16(ref mut buffer)) + | (ColorType::CMYK(16), DecodingBuffer::I16(ref mut buffer)) => { + reader.read_i16_into(&mut buffer[..bytes / 2])?; + bytes / 2 + } + (ColorType::Gray(64), DecodingBuffer::U64(ref mut buffer)) => { reader.read_u64_into(&mut buffer[..bytes / 8])?; if self.photometric_interpretation == PhotometricInterpretation::WhiteIsZero { @@ -899,6 +944,16 @@ impl Decoder { } bytes / 2 } + // TODO: not sure about the following implementation + (ColorType::Gray(16), DecodingBuffer::I16(ref mut buffer)) => { + reader.read_i16_into(&mut buffer[..bytes / 2])?; + if self.photometric_interpretation == PhotometricInterpretation::WhiteIsZero { + for datum in buffer[..bytes / 2].iter_mut() { + *datum = 0xff - *datum + } + } + bytes / 2 + } (ColorType::Gray(n), DecodingBuffer::U8(ref mut buffer)) if n <= 8 => { reader.read_exact(&mut buffer[..bytes])?; if self.photometric_interpretation == PhotometricInterpretation::WhiteIsZero { @@ -1017,7 +1072,6 @@ impl Decoder { pub fn read_strip_to_buffer(&mut self, mut buffer: DecodingBuffer) -> TiffResult<()> { self.initialize_strip_decoder()?; - let index = self.strip_decoder.as_ref().unwrap().strip_index; let offset = *self .strip_decoder @@ -1037,7 +1091,6 @@ impl Decoder { .ok_or(TiffError::FormatError( TiffFormatError::InconsistentSizesEncountered, ))?; - let tag_rows = self.get_tag_u32(Tag::RowsPerStrip).unwrap_or(self.height); let rows_per_strip = usize::try_from(tag_rows)?; @@ -1047,7 +1100,7 @@ impl Decoder { let strip_height = cmp::min(rows_per_strip, sized_height - index * rows_per_strip); let buffer_size = sized_width * strip_height * self.bits_per_sample.len(); - + if buffer.len() < buffer_size { return Err(TiffError::FormatError( TiffFormatError::InconsistentSizesEncountered, @@ -1055,13 +1108,11 @@ impl Decoder { } let units_read = self.expand_strip(buffer.copy(), offset, byte_count, buffer_size)?; - self.strip_decoder.as_mut().unwrap().strip_index += 1; if u32::try_from(index)? == self.strip_count()? { self.strip_decoder = None; } - if units_read < buffer_size { return Err(TiffError::FormatError( TiffFormatError::InconsistentStripSamples { @@ -1112,6 +1163,12 @@ impl Decoder { TiffUnsupportedError::UnsupportedBitsPerChannel(n), )), }, + SampleFormat::Int => match max_sample_bits { + n if n <=16 => DecodingResult::new_i16(buffer_size, &self.limits), + n => Err(TiffError::UnsupportedError( + TiffUnsupportedError::UnsupportedBitsPerChannel(n), + )), + } format => { Err(TiffUnsupportedError::UnsupportedSampleFormat(vec![format.clone()]).into()) } @@ -1132,7 +1189,6 @@ impl Decoder { ); let mut result = self.result_buffer(strip_height)?; - self.read_strip_to_buffer(result.as_buffer(0))?; Ok(result) @@ -1154,7 +1210,8 @@ impl Decoder { let mut result = self.result_buffer(usize::try_from(self.height)?)?; for i in 0..usize::try_from(self.strip_count()?)? { - self.read_strip_to_buffer(result.as_buffer(samples_per_strip * i))?; + let r = result.as_buffer(samples_per_strip * i); + self.read_strip_to_buffer(r)?; } Ok(result) } diff --git a/src/decoder/stream.rs b/src/decoder/stream.rs index 9b89046..b371f05 100644 --- a/src/decoder/stream.rs +++ b/src/decoder/stream.rs @@ -59,6 +59,24 @@ pub trait EndianReader: Read { }) } + #[inline(always)] + fn read_i16_into(&mut self, buffer: &mut [i16]) -> Result<(), io::Error> { + self.read_exact(bytecast::i16_as_ne_mut_bytes(buffer))?; + match self.byte_order() { + ByteOrder::LittleEndian => { + for n in buffer { + *n = i16::from_le(*n); + } + } + ByteOrder::BigEndian => { + for n in buffer { + *n = i16::from_be(*n); + } + } + } + Ok(()) + } + /// Reads an u32 #[inline(always)] fn read_u32(&mut self) -> Result { From 7ec2b75c70c44013677aa6fe0651c01c8842f793 Mon Sep 17 00:00:00 2001 From: HagaiHargil Date: Tue, 8 Dec 2020 12:07:36 +0200 Subject: [PATCH 2/7] Added int16 tests --- tests/decode_images.rs | 11 +++++++++++ tests/images/int16.tif | Bin 0 -> 8512 bytes tests/images/int16_rgb.tif | Bin 0 -> 24912 bytes 3 files changed, 11 insertions(+) create mode 100755 tests/images/int16.tif create mode 100755 tests/images/int16_rgb.tif diff --git a/tests/decode_images.rs b/tests/decode_images.rs index 2336178..3049700 100644 --- a/tests/decode_images.rs +++ b/tests/decode_images.rs @@ -30,6 +30,7 @@ macro_rules! test_image_sum { test_image_sum!(test_image_sum_u8, U8, u64); test_image_sum!(test_image_sum_u16, U16, u64); +test_image_sum!(test_image_sum_i16, I16, i64); test_image_sum!(test_image_sum_u32, U32, u64); test_image_sum!(test_image_sum_u64, U64, u64); test_image_sum!(test_image_sum_f32, F32, f32); @@ -135,6 +136,16 @@ fn test_rgb_f32() { test_image_sum_f32("gradient-3c-32b-float.tiff", ColorType::RGB(32), 472.8405); } +#[test] +fn test_int16() { + test_image_sum_i16("int16.tif", ColorType::Gray(16), 354396); +} + +#[test] +fn test_int16_rgb() { + test_image_sum_i16("int16_rgb.tif", ColorType::RGB(16), 1063188); +} + #[test] fn test_string_tags() { // these files have null-terminated strings for their Software tag. One has extra bytes after diff --git a/tests/images/int16.tif b/tests/images/int16.tif new file mode 100755 index 0000000000000000000000000000000000000000..5853b06f6c6057fb717551e298f4813025e41566 GIT binary patch literal 8512 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 literal 0 HcmV?d00001 diff --git a/tests/images/int16_rgb.tif b/tests/images/int16_rgb.tif new file mode 100755 index 0000000000000000000000000000000000000000..950a9ac77d3ef7c915e746b1c97587fb9bc7419d GIT binary patch literal 24912 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 a|Fiyo*8k7?|5^V(>;Gr{|NsB~|NjBrhY|1q literal 0 HcmV?d00001 From ec98e32a3b8876893bc46fbe24f0fb76ef8ae332 Mon Sep 17 00:00:00 2001 From: HagaiHargil Date: Tue, 8 Dec 2020 13:46:09 +0200 Subject: [PATCH 3/7] Removed unused wrapping f32 and f64 --- src/decoder/mod.rs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/decoder/mod.rs b/src/decoder/mod.rs index d715ee5..b6abf2a 100644 --- a/src/decoder/mod.rs +++ b/src/decoder/mod.rs @@ -274,18 +274,6 @@ impl Wrapping for u64 { } } -impl Wrapping for f32 { - fn wrapping_add(&self, other: Self) -> Self { - self + other - } -} - -impl Wrapping for f64 { - fn wrapping_add(&self, other: Self) -> Self { - self + other - } -} - impl Wrapping for i16 { fn wrapping_add(&self, other: Self) -> Self { i16::wrapping_add(*self, other) From 332ab1dc4d48cc30779a09d8daf4bf9e2e77ba52 Mon Sep 17 00:00:00 2001 From: Andreas Molzer Date: Fri, 11 Dec 2020 20:35:21 +0100 Subject: [PATCH 4/7] Use WhiteIsZero interpretation of libtiff Note that the variants are even named `MINISWHITE` in their code. Address the remaining review nits. --- src/decoder/mod.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/decoder/mod.rs b/src/decoder/mod.rs index b6abf2a..042baba 100644 --- a/src/decoder/mod.rs +++ b/src/decoder/mod.rs @@ -92,7 +92,6 @@ impl DecodingResult { Ok(DecodingResult::I16(vec![0; size])) } } - pub fn as_buffer(&mut self, start: usize) -> DecodingBuffer { match *self { @@ -932,12 +931,13 @@ impl Decoder { } bytes / 2 } - // TODO: not sure about the following implementation + // The following conversions interpret the image as in libtiff. + // In particular, MIN is white and MAX is black and not Zero as the name would imply. (ColorType::Gray(16), DecodingBuffer::I16(ref mut buffer)) => { reader.read_i16_into(&mut buffer[..bytes / 2])?; if self.photometric_interpretation == PhotometricInterpretation::WhiteIsZero { for datum in buffer[..bytes / 2].iter_mut() { - *datum = 0xff - *datum + *datum = !*datum; } } bytes / 2 @@ -946,7 +946,7 @@ impl Decoder { reader.read_exact(&mut buffer[..bytes])?; if self.photometric_interpretation == PhotometricInterpretation::WhiteIsZero { for byte in buffer[..bytes].iter_mut() { - *byte = 0xff - *byte + *byte = !*byte; } } bytes @@ -1088,7 +1088,7 @@ impl Decoder { let strip_height = cmp::min(rows_per_strip, sized_height - index * rows_per_strip); let buffer_size = sized_width * strip_height * self.bits_per_sample.len(); - + if buffer.len() < buffer_size { return Err(TiffError::FormatError( TiffFormatError::InconsistentSizesEncountered, @@ -1152,11 +1152,11 @@ impl Decoder { )), }, SampleFormat::Int => match max_sample_bits { - n if n <=16 => DecodingResult::new_i16(buffer_size, &self.limits), + n if n <= 16 => DecodingResult::new_i16(buffer_size, &self.limits), n => Err(TiffError::UnsupportedError( TiffUnsupportedError::UnsupportedBitsPerChannel(n), )), - } + }, format => { Err(TiffUnsupportedError::UnsupportedSampleFormat(vec![format.clone()]).into()) } From aa13e31894f69a3f5684b53af1954386e5d6fca4 Mon Sep 17 00:00:00 2001 From: HagaiHargil Date: Sun, 13 Dec 2020 11:37:56 +0200 Subject: [PATCH 5/7] Initial i8 support --- src/bytecast.rs | 2 +- src/decoder/mod.rs | 29 ++++++++++++++++++++++++++++- src/decoder/stream.rs | 29 +++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 2 deletions(-) diff --git a/src/bytecast.rs b/src/bytecast.rs index 40e5fe5..0d8869f 100644 --- a/src/bytecast.rs +++ b/src/bytecast.rs @@ -23,7 +23,7 @@ macro_rules! integral_slice_as_bytes{($int:ty, $const:ident $(,$mut:ident)*) => })* }} -integral_slice_as_bytes!(i8, i8_as_ne_bytes); +integral_slice_as_bytes!(i8, i8_as_ne_bytes, i8_as_ne_mut_bytes); integral_slice_as_bytes!(u16, u16_as_ne_bytes, u16_as_ne_mut_bytes); integral_slice_as_bytes!(i16, i16_as_ne_bytes, i16_as_ne_mut_bytes); integral_slice_as_bytes!(u32, u32_as_ne_bytes, u32_as_ne_mut_bytes); diff --git a/src/decoder/mod.rs b/src/decoder/mod.rs index 042baba..e555fde 100644 --- a/src/decoder/mod.rs +++ b/src/decoder/mod.rs @@ -32,6 +32,8 @@ pub enum DecodingResult { F32(Vec), /// A vector of 64 bit IEEE floats F64(Vec), + /// A vector of 8 bit signed ints + I8(Vec), /// A vector of 16 bit signed ints I16(Vec), } @@ -85,6 +87,14 @@ impl DecodingResult { } } + fn new_i8(size: usize, limits: &Limits) -> TiffResult { + if size > limits.decoding_buffer_size / std::mem::size_of::() { + Err(TiffError::LimitsExceeded) + } else { + Ok(DecodingResult::I8(vec![0; size])) + } + } + fn new_i16(size: usize, limits: &Limits) -> TiffResult { if size > limits.decoding_buffer_size / 2 { Err(TiffError::LimitsExceeded) @@ -101,6 +111,7 @@ impl DecodingResult { DecodingResult::U64(ref mut buf) => DecodingBuffer::U64(&mut buf[start..]), DecodingResult::F32(ref mut buf) => DecodingBuffer::F32(&mut buf[start..]), DecodingResult::F64(ref mut buf) => DecodingBuffer::F64(&mut buf[start..]), + DecodingResult::I8(ref mut buf) => DecodingBuffer::I8(&mut buf[start..]), DecodingResult::I16(ref mut buf) => DecodingBuffer::I16(&mut buf[start..]), } } @@ -120,6 +131,8 @@ pub enum DecodingBuffer<'a> { F32(&'a mut [f32]), /// A slice of 64 bit IEEE floats F64(&'a mut [f64]), + /// A slice of 8 bits signed ints + I8(&'a mut [i8]), /// A slice of 16 bits signed ints I16(&'a mut [i16]), } @@ -133,6 +146,7 @@ impl<'a> DecodingBuffer<'a> { DecodingBuffer::U64(ref buf) => buf.len(), DecodingBuffer::F32(ref buf) => buf.len(), DecodingBuffer::F64(ref buf) => buf.len(), + DecodingBuffer::I8(ref buf) => buf.len(), DecodingBuffer::I16(ref buf) => buf.len(), } } @@ -145,6 +159,7 @@ impl<'a> DecodingBuffer<'a> { DecodingBuffer::U64(_) => 8, DecodingBuffer::F32(_) => 4, DecodingBuffer::F64(_) => 8, + DecodingBuffer::I8(_) => 1, DecodingBuffer::I16(_) => 2, } } @@ -160,6 +175,7 @@ impl<'a> DecodingBuffer<'a> { DecodingBuffer::U64(ref mut buf) => DecodingBuffer::U64(buf), DecodingBuffer::F32(ref mut buf) => DecodingBuffer::F32(buf), DecodingBuffer::F64(ref mut buf) => DecodingBuffer::F64(buf), + DecodingBuffer::I8(ref mut buf) => DecodingBuffer::I8(buf), DecodingBuffer::I16(ref mut buf) => DecodingBuffer::I16(buf), } } @@ -273,6 +289,13 @@ impl Wrapping for u64 { } } + +impl Wrapping for i8 { + fn wrapping_add(&self, other: Self) -> Self { + i8::wrapping_add(*self, other) + } +} + impl Wrapping for i16 { fn wrapping_add(&self, other: Self) -> Self { i16::wrapping_add(*self, other) @@ -342,6 +365,9 @@ fn rev_hpredict(image: DecodingBuffer, size: (u32, u32), color_type: ColorType) TiffUnsupportedError::HorizontalPredictor(color_type), )); } + DecodingBuffer::I8(buf) => { + rev_hpredict_nsamp(buf, size, samples)?; + } DecodingBuffer::I16(buf) => { rev_hpredict_nsamp(buf, size, samples)?; } @@ -1152,7 +1178,8 @@ impl Decoder { )), }, SampleFormat::Int => match max_sample_bits { - n if n <= 16 => DecodingResult::new_i16(buffer_size, &self.limits), + n if n <= 8 => DecodingResult::new_i8(buffer_size, &self.limits), + n if (n > 8) & (n <= 16) => DecodingResult::new_i16(buffer_size, &self.limits), n => Err(TiffError::UnsupportedError( TiffUnsupportedError::UnsupportedBitsPerChannel(n), )), diff --git a/src/decoder/stream.rs b/src/decoder/stream.rs index b371f05..862da76 100644 --- a/src/decoder/stream.rs +++ b/src/decoder/stream.rs @@ -48,6 +48,35 @@ pub trait EndianReader: Read { Ok(()) } + /// Reads an i8 + #[inline(always)] + fn read_i8(&mut self) -> Result { + let mut n = [0u8; 1]; + self.read_exact(&mut n)?; + Ok(match self.byte_order() { + ByteOrder::LittleEndian => i8::from_le_bytes(n), + ByteOrder::BigEndian => i8::from_be_bytes(n), + }) + } + + #[inline(always)] + fn read_i8_into(&mut self, buffer: &mut [i8]) -> Result<(), io::Error> { + self.read_exact(bytecast::i8_as_ne_mut_bytes(buffer))?; + match self.byte_order() { + ByteOrder::LittleEndian => { + for n in buffer { + *n = i8::from_le(*n); + } + } + ByteOrder::BigEndian => { + for n in buffer { + *n = i8::from_be(*n); + } + } + } + Ok(()) + } + /// Reads an i16 #[inline(always)] fn read_i16(&mut self) -> Result { From cd2f4f6462f8eccacefd50407f0e809f5ea9c2a4 Mon Sep 17 00:00:00 2001 From: HagaiHargil Date: Sun, 13 Dec 2020 12:00:48 +0200 Subject: [PATCH 6/7] Added tests and finalized i8 support --- src/decoder/mod.rs | 15 +++++++++++++++ tests/decode_images.rs | 11 +++++++++++ tests/images/int8.tif | Bin 0 -> 4416 bytes tests/images/int8_rgb.tif | Bin 0 -> 12624 bytes 4 files changed, 26 insertions(+) create mode 100644 tests/images/int8.tif create mode 100644 tests/images/int8_rgb.tif diff --git a/src/decoder/mod.rs b/src/decoder/mod.rs index e555fde..5c6cb3f 100644 --- a/src/decoder/mod.rs +++ b/src/decoder/mod.rs @@ -923,6 +923,12 @@ impl Decoder { reader.read_u64_into(&mut buffer[..bytes / 8])?; bytes / 8 } + (ColorType::RGBA(8), DecodingBuffer::I8(ref mut buffer)) + | (ColorType::RGB(8), DecodingBuffer::I8(ref mut buffer)) + | (ColorType::CMYK(8), DecodingBuffer::I8(ref mut buffer)) => { + reader.read_i8_into(&mut buffer[..bytes])?; + bytes + } (ColorType::RGBA(16), DecodingBuffer::I16(ref mut buffer)) | (ColorType::RGB(16), DecodingBuffer::I16(ref mut buffer)) | (ColorType::CMYK(16), DecodingBuffer::I16(ref mut buffer)) => { @@ -957,6 +963,15 @@ impl Decoder { } bytes / 2 } + (ColorType::Gray(8), DecodingBuffer::I8(ref mut buffer)) => { + reader.read_i8_into(&mut buffer[..bytes])?; + if self.photometric_interpretation == PhotometricInterpretation::WhiteIsZero { + for datum in buffer[..bytes].iter_mut() { + *datum = !*datum; + } + } + bytes + } // The following conversions interpret the image as in libtiff. // In particular, MIN is white and MAX is black and not Zero as the name would imply. (ColorType::Gray(16), DecodingBuffer::I16(ref mut buffer)) => { diff --git a/tests/decode_images.rs b/tests/decode_images.rs index 3049700..1af340f 100644 --- a/tests/decode_images.rs +++ b/tests/decode_images.rs @@ -29,6 +29,7 @@ macro_rules! test_image_sum { } test_image_sum!(test_image_sum_u8, U8, u64); +test_image_sum!(test_image_sum_i8, I8, i64); test_image_sum!(test_image_sum_u16, U16, u64); test_image_sum!(test_image_sum_i16, I16, i64); test_image_sum!(test_image_sum_u32, U32, u64); @@ -136,6 +137,16 @@ fn test_rgb_f32() { test_image_sum_f32("gradient-3c-32b-float.tiff", ColorType::RGB(32), 472.8405); } +#[test] +fn test_int8() { + test_image_sum_i8("int8.tif", ColorType::Gray(8), 3111) +} + +#[test] +fn test_int8_rgb() { + test_image_sum_i8("int8_rgb.tif", ColorType::RGB(8), -10344) +} + #[test] fn test_int16() { test_image_sum_i16("int16.tif", ColorType::Gray(16), 354396); diff --git a/tests/images/int8.tif b/tests/images/int8.tif new file mode 100644 index 0000000000000000000000000000000000000000..807e0fd8105952583147ec3e303915d0201fe7c1 GIT binary patch literal 4416 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 literal 0 HcmV?d00001 diff --git a/tests/images/int8_rgb.tif b/tests/images/int8_rgb.tif new file mode 100644 index 0000000000000000000000000000000000000000..a0f6db0ed28871527fbfa144d6acf42f2ff1aa68 GIT binary patch literal 12624 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 Date: Sun, 13 Dec 2020 12:03:53 +0200 Subject: [PATCH 7/7] Rustfmt --- src/decoder/mod.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/decoder/mod.rs b/src/decoder/mod.rs index 5c6cb3f..8ac4512 100644 --- a/src/decoder/mod.rs +++ b/src/decoder/mod.rs @@ -289,7 +289,6 @@ impl Wrapping for u64 { } } - impl Wrapping for i8 { fn wrapping_add(&self, other: Self) -> Self { i8::wrapping_add(*self, other)