From aa13e31894f69a3f5684b53af1954386e5d6fca4 Mon Sep 17 00:00:00 2001 From: HagaiHargil Date: Sun, 13 Dec 2020 11:37:56 +0200 Subject: [PATCH] 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 {