From 3de87a7001121690db23dc43843bbc1ffea48b77 Mon Sep 17 00:00:00 2001 From: Vadim Dyadkin Date: Sat, 20 Feb 2021 18:25:29 +0100 Subject: [PATCH] Open tif files containing i32 arrays --- src/bytecast.rs | 2 +- src/decoder/mod.rs | 32 +++++++++++++++++++++++++++++++- src/decoder/stream.rs | 18 ++++++++++++++++++ 3 files changed, 50 insertions(+), 2 deletions(-) diff --git a/src/bytecast.rs b/src/bytecast.rs index 0d8869f..ff14d3c 100644 --- a/src/bytecast.rs +++ b/src/bytecast.rs @@ -27,7 +27,7 @@ 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); -integral_slice_as_bytes!(i32, i32_as_ne_bytes); +integral_slice_as_bytes!(i32, i32_as_ne_bytes, i32_as_ne_mut_bytes); integral_slice_as_bytes!(u64, u64_as_ne_bytes, u64_as_ne_mut_bytes); integral_slice_as_bytes!(f32, f32_as_ne_bytes, f32_as_ne_mut_bytes); integral_slice_as_bytes!(f64, f64_as_ne_bytes, f64_as_ne_mut_bytes); diff --git a/src/decoder/mod.rs b/src/decoder/mod.rs index 8ac4512..8d4bf33 100644 --- a/src/decoder/mod.rs +++ b/src/decoder/mod.rs @@ -36,6 +36,8 @@ pub enum DecodingResult { I8(Vec), /// A vector of 16 bit signed ints I16(Vec), + /// A vector of 32 bit signed ints + I32(Vec), } impl DecodingResult { @@ -103,6 +105,14 @@ impl DecodingResult { } } + fn new_i32(size: usize, limits: &Limits) -> TiffResult { + if size > limits.decoding_buffer_size / 4 { + Err(TiffError::LimitsExceeded) + } else { + Ok(DecodingResult::I32(vec![0; size])) + } + } + pub fn as_buffer(&mut self, start: usize) -> DecodingBuffer { match *self { DecodingResult::U8(ref mut buf) => DecodingBuffer::U8(&mut buf[start..]), @@ -113,6 +123,7 @@ impl DecodingResult { 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..]), + DecodingResult::I32(ref mut buf) => DecodingBuffer::I32(&mut buf[start..]), } } } @@ -135,6 +146,8 @@ pub enum DecodingBuffer<'a> { I8(&'a mut [i8]), /// A slice of 16 bits signed ints I16(&'a mut [i16]), + /// A slice of 16 bits signed ints + I32(&'a mut [i32]), } impl<'a> DecodingBuffer<'a> { @@ -148,6 +161,7 @@ impl<'a> DecodingBuffer<'a> { DecodingBuffer::F64(ref buf) => buf.len(), DecodingBuffer::I8(ref buf) => buf.len(), DecodingBuffer::I16(ref buf) => buf.len(), + DecodingBuffer::I32(ref buf) => buf.len(), } } @@ -161,6 +175,7 @@ impl<'a> DecodingBuffer<'a> { DecodingBuffer::F64(_) => 8, DecodingBuffer::I8(_) => 1, DecodingBuffer::I16(_) => 2, + DecodingBuffer::I32(_) => 4, } } @@ -177,6 +192,7 @@ impl<'a> DecodingBuffer<'a> { DecodingBuffer::F64(ref mut buf) => DecodingBuffer::F64(buf), DecodingBuffer::I8(ref mut buf) => DecodingBuffer::I8(buf), DecodingBuffer::I16(ref mut buf) => DecodingBuffer::I16(buf), + DecodingBuffer::I32(ref mut buf) => DecodingBuffer::I32(buf), } } } @@ -301,6 +317,12 @@ impl Wrapping for i16 { } } +impl Wrapping for i32 { + fn wrapping_add(&self, other: Self) -> Self { + i32::wrapping_add(*self, other) + } +} + fn rev_hpredict_nsamp(image: &mut [T], size: (u32, u32), samples: usize) -> TiffResult<()> where T: Copy + Wrapping, @@ -370,6 +392,9 @@ fn rev_hpredict(image: DecodingBuffer, size: (u32, u32), color_type: ColorType) DecodingBuffer::I16(buf) => { rev_hpredict_nsamp(buf, size, samples)?; } + DecodingBuffer::I32(buf) => { + rev_hpredict_nsamp(buf, size, samples)?; + } } Ok(()) } @@ -953,6 +978,10 @@ impl Decoder { } bytes / 4 } + (ColorType::Gray(32), DecodingBuffer::I32(ref mut buffer)) => { + reader.read_i32_into(&mut buffer[..bytes / 4])?; + bytes / 4 + } (ColorType::Gray(16), DecodingBuffer::U16(ref mut buffer)) => { reader.read_u16_into(&mut buffer[..bytes / 2])?; if self.photometric_interpretation == PhotometricInterpretation::WhiteIsZero { @@ -1193,7 +1222,8 @@ impl Decoder { }, SampleFormat::Int => match max_sample_bits { 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 if n == 16 => DecodingResult::new_i16(buffer_size, &self.limits), + n if (n > 16) & (n <= 32) => DecodingResult::new_i32(buffer_size, &self.limits), n => Err(TiffError::UnsupportedError( TiffUnsupportedError::UnsupportedBitsPerChannel(n), )), diff --git a/src/decoder/stream.rs b/src/decoder/stream.rs index 862da76..cc5b31c 100644 --- a/src/decoder/stream.rs +++ b/src/decoder/stream.rs @@ -135,6 +135,24 @@ pub trait EndianReader: Read { Ok(()) } + #[inline(always)] + fn read_i32_into(&mut self, buffer: &mut [i32]) -> Result<(), io::Error> { + self.read_exact(bytecast::i32_as_ne_mut_bytes(buffer))?; + match self.byte_order() { + ByteOrder::LittleEndian => { + for n in buffer { + *n = i32::from_le(*n); + } + } + ByteOrder::BigEndian => { + for n in buffer { + *n = i32::from_be(*n); + } + } + } + Ok(()) + } + /// Reads an i32 #[inline(always)] fn read_i32(&mut self) -> Result {