Int16 support
This commit is contained in:
1 parent
fc80c5e3dd
commit
9788085786
3 files changed
+83
-8
No files matched your search
+1
-1
@@ -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!(i8, i8_as_ne_bytes);
|
||||||
integral_slice_as_bytes!(u16, u16_as_ne_bytes, u16_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);
|
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!(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);
|
||||||
integral_slice_as_bytes!(u64, u64_as_ne_bytes, u64_as_ne_mut_bytes);
|
integral_slice_as_bytes!(u64, u64_as_ne_bytes, u64_as_ne_mut_bytes);
|
||||||
|
|||||||
+64
-7
@@ -32,6 +32,8 @@ pub enum DecodingResult {
|
|||||||
F32(Vec<f32>),
|
F32(Vec<f32>),
|
||||||
/// A vector of 64 bit IEEE floats
|
/// A vector of 64 bit IEEE floats
|
||||||
F64(Vec<f64>),
|
F64(Vec<f64>),
|
||||||
|
/// A vector of 16 bit signed ints
|
||||||
|
I16(Vec<i16>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DecodingResult {
|
impl DecodingResult {
|
||||||
@@ -83,6 +85,15 @@ impl DecodingResult {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn new_i16(size: usize, limits: &Limits) -> TiffResult<DecodingResult> {
|
||||||
|
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 {
|
pub fn as_buffer(&mut self, start: usize) -> DecodingBuffer {
|
||||||
match *self {
|
match *self {
|
||||||
DecodingResult::U8(ref mut buf) => DecodingBuffer::U8(&mut buf[start..]),
|
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::U64(ref mut buf) => DecodingBuffer::U64(&mut buf[start..]),
|
||||||
DecodingResult::F32(ref mut buf) => DecodingBuffer::F32(&mut buf[start..]),
|
DecodingResult::F32(ref mut buf) => DecodingBuffer::F32(&mut buf[start..]),
|
||||||
DecodingResult::F64(ref mut buf) => DecodingBuffer::F64(&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]),
|
F32(&'a mut [f32]),
|
||||||
/// A slice of 64 bit IEEE floats
|
/// A slice of 64 bit IEEE floats
|
||||||
F64(&'a mut [f64]),
|
F64(&'a mut [f64]),
|
||||||
|
/// A slice of 16 bits signed ints
|
||||||
|
I16(&'a mut [i16]),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> DecodingBuffer<'a> {
|
impl<'a> DecodingBuffer<'a> {
|
||||||
@@ -120,6 +134,7 @@ impl<'a> DecodingBuffer<'a> {
|
|||||||
DecodingBuffer::U64(ref buf) => buf.len(),
|
DecodingBuffer::U64(ref buf) => buf.len(),
|
||||||
DecodingBuffer::F32(ref buf) => buf.len(),
|
DecodingBuffer::F32(ref buf) => buf.len(),
|
||||||
DecodingBuffer::F64(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::U64(_) => 8,
|
||||||
DecodingBuffer::F32(_) => 4,
|
DecodingBuffer::F32(_) => 4,
|
||||||
DecodingBuffer::F64(_) => 8,
|
DecodingBuffer::F64(_) => 8,
|
||||||
|
DecodingBuffer::I16(_) => 2,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,6 +161,7 @@ impl<'a> DecodingBuffer<'a> {
|
|||||||
DecodingBuffer::U64(ref mut buf) => DecodingBuffer::U64(buf),
|
DecodingBuffer::U64(ref mut buf) => DecodingBuffer::U64(buf),
|
||||||
DecodingBuffer::F32(ref mut buf) => DecodingBuffer::F32(buf),
|
DecodingBuffer::F32(ref mut buf) => DecodingBuffer::F32(buf),
|
||||||
DecodingBuffer::F64(ref mut buf) => DecodingBuffer::F64(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<T>(image: &mut [T], size: (u32, u32), samples: usize) -> TiffResult<()>
|
fn rev_hpredict_nsamp<T>(image: &mut [T], size: (u32, u32), samples: usize) -> TiffResult<()>
|
||||||
where
|
where
|
||||||
T: Copy + Wrapping,
|
T: Copy + Wrapping,
|
||||||
@@ -320,6 +355,9 @@ fn rev_hpredict(image: DecodingBuffer, size: (u32, u32), color_type: ColorType)
|
|||||||
TiffUnsupportedError::HorizontalPredictor(color_type),
|
TiffUnsupportedError::HorizontalPredictor(color_type),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
DecodingBuffer::I16(buf) => {
|
||||||
|
rev_hpredict_nsamp(buf, size, samples)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -872,6 +910,13 @@ impl<R: Read + Seek> Decoder<R> {
|
|||||||
reader.read_u64_into(&mut buffer[..bytes / 8])?;
|
reader.read_u64_into(&mut buffer[..bytes / 8])?;
|
||||||
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)) => {
|
(ColorType::Gray(64), DecodingBuffer::U64(ref mut buffer)) => {
|
||||||
reader.read_u64_into(&mut buffer[..bytes / 8])?;
|
reader.read_u64_into(&mut buffer[..bytes / 8])?;
|
||||||
if self.photometric_interpretation == PhotometricInterpretation::WhiteIsZero {
|
if self.photometric_interpretation == PhotometricInterpretation::WhiteIsZero {
|
||||||
@@ -899,6 +944,16 @@ impl<R: Read + Seek> Decoder<R> {
|
|||||||
}
|
}
|
||||||
bytes / 2
|
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 => {
|
(ColorType::Gray(n), DecodingBuffer::U8(ref mut buffer)) if n <= 8 => {
|
||||||
reader.read_exact(&mut buffer[..bytes])?;
|
reader.read_exact(&mut buffer[..bytes])?;
|
||||||
if self.photometric_interpretation == PhotometricInterpretation::WhiteIsZero {
|
if self.photometric_interpretation == PhotometricInterpretation::WhiteIsZero {
|
||||||
@@ -1017,7 +1072,6 @@ impl<R: Read + Seek> Decoder<R> {
|
|||||||
|
|
||||||
pub fn read_strip_to_buffer(&mut self, mut buffer: DecodingBuffer) -> TiffResult<()> {
|
pub fn read_strip_to_buffer(&mut self, mut buffer: DecodingBuffer) -> TiffResult<()> {
|
||||||
self.initialize_strip_decoder()?;
|
self.initialize_strip_decoder()?;
|
||||||
|
|
||||||
let index = self.strip_decoder.as_ref().unwrap().strip_index;
|
let index = self.strip_decoder.as_ref().unwrap().strip_index;
|
||||||
let offset = *self
|
let offset = *self
|
||||||
.strip_decoder
|
.strip_decoder
|
||||||
@@ -1037,7 +1091,6 @@ impl<R: Read + Seek> Decoder<R> {
|
|||||||
.ok_or(TiffError::FormatError(
|
.ok_or(TiffError::FormatError(
|
||||||
TiffFormatError::InconsistentSizesEncountered,
|
TiffFormatError::InconsistentSizesEncountered,
|
||||||
))?;
|
))?;
|
||||||
|
|
||||||
let tag_rows = self.get_tag_u32(Tag::RowsPerStrip).unwrap_or(self.height);
|
let tag_rows = self.get_tag_u32(Tag::RowsPerStrip).unwrap_or(self.height);
|
||||||
let rows_per_strip = usize::try_from(tag_rows)?;
|
let rows_per_strip = usize::try_from(tag_rows)?;
|
||||||
|
|
||||||
@@ -1047,7 +1100,7 @@ impl<R: Read + Seek> Decoder<R> {
|
|||||||
let strip_height = cmp::min(rows_per_strip, sized_height - index * rows_per_strip);
|
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();
|
let buffer_size = sized_width * strip_height * self.bits_per_sample.len();
|
||||||
|
|
||||||
if buffer.len() < buffer_size {
|
if buffer.len() < buffer_size {
|
||||||
return Err(TiffError::FormatError(
|
return Err(TiffError::FormatError(
|
||||||
TiffFormatError::InconsistentSizesEncountered,
|
TiffFormatError::InconsistentSizesEncountered,
|
||||||
@@ -1055,13 +1108,11 @@ impl<R: Read + Seek> Decoder<R> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let units_read = self.expand_strip(buffer.copy(), offset, byte_count, buffer_size)?;
|
let units_read = self.expand_strip(buffer.copy(), offset, byte_count, buffer_size)?;
|
||||||
|
|
||||||
self.strip_decoder.as_mut().unwrap().strip_index += 1;
|
self.strip_decoder.as_mut().unwrap().strip_index += 1;
|
||||||
|
|
||||||
if u32::try_from(index)? == self.strip_count()? {
|
if u32::try_from(index)? == self.strip_count()? {
|
||||||
self.strip_decoder = None;
|
self.strip_decoder = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
if units_read < buffer_size {
|
if units_read < buffer_size {
|
||||||
return Err(TiffError::FormatError(
|
return Err(TiffError::FormatError(
|
||||||
TiffFormatError::InconsistentStripSamples {
|
TiffFormatError::InconsistentStripSamples {
|
||||||
@@ -1112,6 +1163,12 @@ impl<R: Read + Seek> Decoder<R> {
|
|||||||
TiffUnsupportedError::UnsupportedBitsPerChannel(n),
|
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 => {
|
format => {
|
||||||
Err(TiffUnsupportedError::UnsupportedSampleFormat(vec![format.clone()]).into())
|
Err(TiffUnsupportedError::UnsupportedSampleFormat(vec![format.clone()]).into())
|
||||||
}
|
}
|
||||||
@@ -1132,7 +1189,6 @@ impl<R: Read + Seek> Decoder<R> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let mut result = self.result_buffer(strip_height)?;
|
let mut result = self.result_buffer(strip_height)?;
|
||||||
|
|
||||||
self.read_strip_to_buffer(result.as_buffer(0))?;
|
self.read_strip_to_buffer(result.as_buffer(0))?;
|
||||||
|
|
||||||
Ok(result)
|
Ok(result)
|
||||||
@@ -1154,7 +1210,8 @@ impl<R: Read + Seek> Decoder<R> {
|
|||||||
let mut result = self.result_buffer(usize::try_from(self.height)?)?;
|
let mut result = self.result_buffer(usize::try_from(self.height)?)?;
|
||||||
|
|
||||||
for i in 0..usize::try_from(self.strip_count()?)? {
|
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)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
/// Reads an u32
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn read_u32(&mut self) -> Result<u32, io::Error> {
|
fn read_u32(&mut self) -> Result<u32, io::Error> {
|
||||||
|
|||||||
Reference in new issue
Block a user