Merge pull request #370 from image-rs/restructure-buffer
Restructure decoding's Buffer
This commit is contained in:
12 files changed
+411
-393
No files matched your search
+23
-21
@@ -1,4 +1,4 @@
|
|||||||
use tiff::decoder::{BufferLayoutPreference, Decoder, DecodingBuffer, DecodingResult};
|
use tiff::decoder::{BufferLayoutPreference, Decoder, DecodingSampleBuffer, DecodingSampleSlice};
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let Some(image) = std::env::args_os().nth(1) else {
|
let Some(image) = std::env::args_os().nth(1) else {
|
||||||
@@ -10,7 +10,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
let io = std::io::BufReader::new(file);
|
let io = std::io::BufReader::new(file);
|
||||||
let mut reader = Decoder::open(io)?;
|
let mut reader = Decoder::open(io)?;
|
||||||
|
|
||||||
let mut data = DecodingResult::I8(vec![]);
|
let mut data = DecodingSampleBuffer::I8(vec![]);
|
||||||
|
|
||||||
for i in 0u32.. {
|
for i in 0u32.. {
|
||||||
let colortype = reader.colortype()?;
|
let colortype = reader.colortype()?;
|
||||||
@@ -31,32 +31,32 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
|
|
||||||
fn debug_planes(
|
fn debug_planes(
|
||||||
index: u32,
|
index: u32,
|
||||||
data: &mut DecodingResult,
|
data: &mut DecodingSampleBuffer,
|
||||||
layout: &BufferLayoutPreference,
|
layout: &BufferLayoutPreference,
|
||||||
colortype: &tiff::ColorType,
|
colortype: &tiff::ColorType,
|
||||||
(width, height): (u32, u32),
|
(width, height): (u32, u32),
|
||||||
) {
|
) {
|
||||||
match data {
|
match data {
|
||||||
DecodingResult::F16(v) => {
|
DecodingSampleBuffer::F16(v) => {
|
||||||
let samples = v
|
let samples = v
|
||||||
.iter()
|
.iter()
|
||||||
.map(|&f| (f64::from(f) * f64::from(u16::MAX)) as u16)
|
.map(|&f| (f64::from(f) * f64::from(u16::MAX)) as u16)
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
*data = DecodingResult::U16(samples);
|
*data = DecodingSampleBuffer::U16(samples);
|
||||||
}
|
}
|
||||||
DecodingResult::F32(v) => {
|
DecodingSampleBuffer::F32(v) => {
|
||||||
let samples = v
|
let samples = v
|
||||||
.iter()
|
.iter()
|
||||||
.map(|&f| (f64::from(f) * f64::from(u16::MAX)) as u16)
|
.map(|&f| (f64::from(f) * f64::from(u16::MAX)) as u16)
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
*data = DecodingResult::U16(samples);
|
*data = DecodingSampleBuffer::U16(samples);
|
||||||
}
|
}
|
||||||
DecodingResult::F64(v) => {
|
DecodingSampleBuffer::F64(v) => {
|
||||||
let samples = v
|
let samples = v
|
||||||
.iter()
|
.iter()
|
||||||
.map(|&f| (f * f64::from(u16::MAX)) as u16)
|
.map(|&f| (f * f64::from(u16::MAX)) as u16)
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
*data = DecodingResult::U16(samples);
|
*data = DecodingSampleBuffer::U16(samples);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
@@ -98,24 +98,24 @@ fn debug_planes(
|
|||||||
// them here (e.g. represent 1-bit as `{0, 1}`) but we'd also set `maxval` accordingly and
|
// them here (e.g. represent 1-bit as `{0, 1}`) but we'd also set `maxval` accordingly and
|
||||||
// this requires tupltype to be `BLACKANDWHITE` so introducing a bunch of complexity. If
|
// this requires tupltype to be `BLACKANDWHITE` so introducing a bunch of complexity. If
|
||||||
// you want to do that in your real code, go ahead.
|
// you want to do that in your real code, go ahead.
|
||||||
DecodingBuffer::U8(buf) => match colortype.bit_depth() {
|
DecodingSampleSlice::U8(buf) => match colortype.bit_depth() {
|
||||||
8 => u64::from(u8::MAX),
|
8 => u64::from(u8::MAX),
|
||||||
4 => {
|
4 => {
|
||||||
fallback_buffer = vec![0; (swidth * sheight) as usize];
|
fallback_buffer = vec![0; (swidth * sheight) as usize];
|
||||||
expand_4bit(buf, swidth, &mut fallback_buffer);
|
expand_4bit(buf, swidth, &mut fallback_buffer);
|
||||||
*data = DecodingResult::U8(fallback_buffer);
|
*data = DecodingSampleBuffer::U8(fallback_buffer);
|
||||||
u64::from(u8::MAX)
|
u64::from(u8::MAX)
|
||||||
}
|
}
|
||||||
2 => {
|
2 => {
|
||||||
fallback_buffer = vec![0; (swidth * sheight) as usize];
|
fallback_buffer = vec![0; (swidth * sheight) as usize];
|
||||||
expand_2bit(buf, swidth, &mut fallback_buffer);
|
expand_2bit(buf, swidth, &mut fallback_buffer);
|
||||||
*data = DecodingResult::U8(fallback_buffer);
|
*data = DecodingSampleBuffer::U8(fallback_buffer);
|
||||||
u64::from(u8::MAX)
|
u64::from(u8::MAX)
|
||||||
}
|
}
|
||||||
1 => {
|
1 => {
|
||||||
fallback_buffer = vec![0; (swidth * sheight) as usize];
|
fallback_buffer = vec![0; (swidth * sheight) as usize];
|
||||||
expand_1bit(buf, swidth, &mut fallback_buffer);
|
expand_1bit(buf, swidth, &mut fallback_buffer);
|
||||||
*data = DecodingResult::U8(fallback_buffer);
|
*data = DecodingSampleBuffer::U8(fallback_buffer);
|
||||||
u64::from(u8::MAX)
|
u64::from(u8::MAX)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@@ -126,28 +126,30 @@ fn debug_planes(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
DecodingBuffer::U16(_) => u64::from(u16::MAX),
|
DecodingSampleSlice::U16(_) => u64::from(u16::MAX),
|
||||||
DecodingBuffer::U32(_) => u64::from(u32::MAX),
|
DecodingSampleSlice::U32(_) => u64::from(u32::MAX),
|
||||||
DecodingBuffer::U64(_) => u64::MAX,
|
DecodingSampleSlice::U64(_) => u64::MAX,
|
||||||
// Eh, this is a good effort I guess.
|
// Eh, this is a good effort I guess.
|
||||||
DecodingBuffer::I8(items) => {
|
DecodingSampleSlice::I8(items) => {
|
||||||
items.iter_mut().for_each(|v| *v = 0.max(*v));
|
items.iter_mut().for_each(|v| *v = 0.max(*v));
|
||||||
u64::from(i8::MAX as u8)
|
u64::from(i8::MAX as u8)
|
||||||
}
|
}
|
||||||
DecodingBuffer::I16(items) => {
|
DecodingSampleSlice::I16(items) => {
|
||||||
items.iter_mut().for_each(|v| *v = 0.max(*v));
|
items.iter_mut().for_each(|v| *v = 0.max(*v));
|
||||||
u64::from(i16::MAX as u16)
|
u64::from(i16::MAX as u16)
|
||||||
}
|
}
|
||||||
DecodingBuffer::I32(items) => {
|
DecodingSampleSlice::I32(items) => {
|
||||||
items.iter_mut().for_each(|v| *v = 0.max(*v));
|
items.iter_mut().for_each(|v| *v = 0.max(*v));
|
||||||
u64::from(i32::MAX as u32)
|
u64::from(i32::MAX as u32)
|
||||||
}
|
}
|
||||||
DecodingBuffer::I64(items) => {
|
DecodingSampleSlice::I64(items) => {
|
||||||
items.iter_mut().for_each(|v| *v = 0.max(*v));
|
items.iter_mut().for_each(|v| *v = 0.max(*v));
|
||||||
i64::MAX as u64
|
i64::MAX as u64
|
||||||
}
|
}
|
||||||
// Not supported by PAM.
|
// Not supported by PAM.
|
||||||
DecodingBuffer::F16(_) | DecodingBuffer::F32(_) | DecodingBuffer::F64(_) => return,
|
DecodingSampleSlice::F16(_) | DecodingSampleSlice::F32(_) | DecodingSampleSlice::F64(_) => {
|
||||||
|
return
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let byte_len = if layout.planes > 1 {
|
let byte_len = if layout.planes > 1 {
|
||||||
|
|||||||
@@ -0,0 +1,302 @@
|
|||||||
|
use half::f16;
|
||||||
|
use std::alloc::{Layout, LayoutError};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
bytecast,
|
||||||
|
decoder::{BufferLayoutPreference, Limits},
|
||||||
|
error::{TiffError, TiffResult, TiffUnsupportedError},
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Result of a decoding process
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum DecodingSampleBuffer {
|
||||||
|
/// A vector of unsigned bytes
|
||||||
|
U8(Vec<u8>),
|
||||||
|
/// A vector of unsigned words
|
||||||
|
U16(Vec<u16>),
|
||||||
|
/// A vector of 32 bit unsigned ints
|
||||||
|
U32(Vec<u32>),
|
||||||
|
/// A vector of 64 bit unsigned ints
|
||||||
|
U64(Vec<u64>),
|
||||||
|
/// A vector of 16 bit IEEE floats (held in u16)
|
||||||
|
F16(Vec<f16>),
|
||||||
|
/// A vector of 32 bit IEEE floats
|
||||||
|
F32(Vec<f32>),
|
||||||
|
/// A vector of 64 bit IEEE floats
|
||||||
|
F64(Vec<f64>),
|
||||||
|
/// A vector of 8 bit signed ints
|
||||||
|
I8(Vec<i8>),
|
||||||
|
/// A vector of 16 bit signed ints
|
||||||
|
I16(Vec<i16>),
|
||||||
|
/// A vector of 32 bit signed ints
|
||||||
|
I32(Vec<i32>),
|
||||||
|
/// A vector of 64 bit signed ints
|
||||||
|
I64(Vec<i64>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DecodingSampleBuffer {
|
||||||
|
/// Reallocate the buffer to decode all planes of the indicated layout.
|
||||||
|
pub fn resize_to(
|
||||||
|
&mut self,
|
||||||
|
buffer: &BufferLayoutPreference,
|
||||||
|
limits: &Limits,
|
||||||
|
) -> Result<(), TiffError> {
|
||||||
|
let sample_type = buffer.sample_type.ok_or(TiffError::UnsupportedError(
|
||||||
|
TiffUnsupportedError::UnknownInterpretation,
|
||||||
|
))?;
|
||||||
|
|
||||||
|
let extent = sample_type.extent_for_bytes(buffer.complete_len);
|
||||||
|
self.resize_to_extent(extent, limits)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn resize_to_extent(
|
||||||
|
&mut self,
|
||||||
|
extent: DecodingExtent,
|
||||||
|
limits: &Limits,
|
||||||
|
) -> Result<(), TiffError> {
|
||||||
|
// FIXME: we *can* reuse the allocation sometimes.
|
||||||
|
*self = extent.to_result_buffer(limits)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new<T: Default + Copy>(
|
||||||
|
size: usize,
|
||||||
|
limits: &Limits,
|
||||||
|
from_fn: fn(Vec<T>) -> Self,
|
||||||
|
) -> TiffResult<DecodingSampleBuffer> {
|
||||||
|
if size > limits.decoding_buffer_size / core::mem::size_of::<T>() {
|
||||||
|
Err(TiffError::LimitsExceeded)
|
||||||
|
} else {
|
||||||
|
Ok(from_fn(vec![T::default(); size]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_u8(size: usize, limits: &Limits) -> TiffResult<DecodingSampleBuffer> {
|
||||||
|
Self::new(size, limits, DecodingSampleBuffer::U8)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_u16(size: usize, limits: &Limits) -> TiffResult<DecodingSampleBuffer> {
|
||||||
|
Self::new(size, limits, DecodingSampleBuffer::U16)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_u32(size: usize, limits: &Limits) -> TiffResult<DecodingSampleBuffer> {
|
||||||
|
Self::new(size, limits, DecodingSampleBuffer::U32)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_u64(size: usize, limits: &Limits) -> TiffResult<DecodingSampleBuffer> {
|
||||||
|
Self::new(size, limits, DecodingSampleBuffer::U64)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_f32(size: usize, limits: &Limits) -> TiffResult<DecodingSampleBuffer> {
|
||||||
|
Self::new(size, limits, DecodingSampleBuffer::F32)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_f64(size: usize, limits: &Limits) -> TiffResult<DecodingSampleBuffer> {
|
||||||
|
Self::new(size, limits, DecodingSampleBuffer::F64)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_f16(size: usize, limits: &Limits) -> TiffResult<DecodingSampleBuffer> {
|
||||||
|
Self::new(size, limits, DecodingSampleBuffer::F16)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_i8(size: usize, limits: &Limits) -> TiffResult<DecodingSampleBuffer> {
|
||||||
|
Self::new(size, limits, DecodingSampleBuffer::I8)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_i16(size: usize, limits: &Limits) -> TiffResult<DecodingSampleBuffer> {
|
||||||
|
Self::new(size, limits, DecodingSampleBuffer::I16)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_i32(size: usize, limits: &Limits) -> TiffResult<DecodingSampleBuffer> {
|
||||||
|
Self::new(size, limits, DecodingSampleBuffer::I32)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_i64(size: usize, limits: &Limits) -> TiffResult<DecodingSampleBuffer> {
|
||||||
|
Self::new(size, limits, DecodingSampleBuffer::I64)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a view of this buffer starting from the nth _sample_ of the current type.
|
||||||
|
pub fn as_buffer(&mut self, start: usize) -> DecodingSampleSlice<'_> {
|
||||||
|
match *self {
|
||||||
|
DecodingSampleBuffer::U8(ref mut buf) => DecodingSampleSlice::U8(&mut buf[start..]),
|
||||||
|
DecodingSampleBuffer::U16(ref mut buf) => DecodingSampleSlice::U16(&mut buf[start..]),
|
||||||
|
DecodingSampleBuffer::U32(ref mut buf) => DecodingSampleSlice::U32(&mut buf[start..]),
|
||||||
|
DecodingSampleBuffer::U64(ref mut buf) => DecodingSampleSlice::U64(&mut buf[start..]),
|
||||||
|
DecodingSampleBuffer::F16(ref mut buf) => DecodingSampleSlice::F16(&mut buf[start..]),
|
||||||
|
DecodingSampleBuffer::F32(ref mut buf) => DecodingSampleSlice::F32(&mut buf[start..]),
|
||||||
|
DecodingSampleBuffer::F64(ref mut buf) => DecodingSampleSlice::F64(&mut buf[start..]),
|
||||||
|
DecodingSampleBuffer::I8(ref mut buf) => DecodingSampleSlice::I8(&mut buf[start..]),
|
||||||
|
DecodingSampleBuffer::I16(ref mut buf) => DecodingSampleSlice::I16(&mut buf[start..]),
|
||||||
|
DecodingSampleBuffer::I32(ref mut buf) => DecodingSampleSlice::I32(&mut buf[start..]),
|
||||||
|
DecodingSampleBuffer::I64(ref mut buf) => DecodingSampleSlice::I64(&mut buf[start..]),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A buffer for image decoding
|
||||||
|
pub enum DecodingSampleSlice<'a> {
|
||||||
|
/// A slice of unsigned bytes
|
||||||
|
U8(&'a mut [u8]),
|
||||||
|
/// A slice of unsigned words
|
||||||
|
U16(&'a mut [u16]),
|
||||||
|
/// A slice of 32 bit unsigned ints
|
||||||
|
U32(&'a mut [u32]),
|
||||||
|
/// A slice of 64 bit unsigned ints
|
||||||
|
U64(&'a mut [u64]),
|
||||||
|
/// A slice of 16 bit IEEE floats
|
||||||
|
F16(&'a mut [f16]),
|
||||||
|
/// A slice of 32 bit IEEE floats
|
||||||
|
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]),
|
||||||
|
/// A slice of 32 bits signed ints
|
||||||
|
I32(&'a mut [i32]),
|
||||||
|
/// A slice of 64 bits signed ints
|
||||||
|
I64(&'a mut [i64]),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> DecodingSampleSlice<'a> {
|
||||||
|
pub fn as_bytes(&self) -> &[u8] {
|
||||||
|
match self {
|
||||||
|
DecodingSampleSlice::U8(buf) => buf,
|
||||||
|
DecodingSampleSlice::I8(buf) => bytecast::i8_as_ne_bytes(buf),
|
||||||
|
DecodingSampleSlice::U16(buf) => bytecast::u16_as_ne_bytes(buf),
|
||||||
|
DecodingSampleSlice::I16(buf) => bytecast::i16_as_ne_bytes(buf),
|
||||||
|
DecodingSampleSlice::U32(buf) => bytecast::u32_as_ne_bytes(buf),
|
||||||
|
DecodingSampleSlice::I32(buf) => bytecast::i32_as_ne_bytes(buf),
|
||||||
|
DecodingSampleSlice::U64(buf) => bytecast::u64_as_ne_bytes(buf),
|
||||||
|
DecodingSampleSlice::I64(buf) => bytecast::i64_as_ne_bytes(buf),
|
||||||
|
DecodingSampleSlice::F16(buf) => bytecast::f16_as_ne_bytes(buf),
|
||||||
|
DecodingSampleSlice::F32(buf) => bytecast::f32_as_ne_bytes(buf),
|
||||||
|
DecodingSampleSlice::F64(buf) => bytecast::f64_as_ne_bytes(buf),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_bytes_mut(&mut self) -> &mut [u8] {
|
||||||
|
match self {
|
||||||
|
DecodingSampleSlice::U8(buf) => buf,
|
||||||
|
DecodingSampleSlice::I8(buf) => bytecast::i8_as_ne_mut_bytes(buf),
|
||||||
|
DecodingSampleSlice::U16(buf) => bytecast::u16_as_ne_mut_bytes(buf),
|
||||||
|
DecodingSampleSlice::I16(buf) => bytecast::i16_as_ne_mut_bytes(buf),
|
||||||
|
DecodingSampleSlice::U32(buf) => bytecast::u32_as_ne_mut_bytes(buf),
|
||||||
|
DecodingSampleSlice::I32(buf) => bytecast::i32_as_ne_mut_bytes(buf),
|
||||||
|
DecodingSampleSlice::U64(buf) => bytecast::u64_as_ne_mut_bytes(buf),
|
||||||
|
DecodingSampleSlice::I64(buf) => bytecast::i64_as_ne_mut_bytes(buf),
|
||||||
|
DecodingSampleSlice::F16(buf) => bytecast::f16_as_ne_mut_bytes(buf),
|
||||||
|
DecodingSampleSlice::F32(buf) => bytecast::f32_as_ne_mut_bytes(buf),
|
||||||
|
DecodingSampleSlice::F64(buf) => bytecast::f64_as_ne_mut_bytes(buf),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn byte_len(&self) -> usize {
|
||||||
|
self.as_bytes().len()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
pub enum DecodingSampleType {
|
||||||
|
U8,
|
||||||
|
U16,
|
||||||
|
U32,
|
||||||
|
U64,
|
||||||
|
F16,
|
||||||
|
F32,
|
||||||
|
F64,
|
||||||
|
I8,
|
||||||
|
I16,
|
||||||
|
I32,
|
||||||
|
I64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DecodingSampleType {
|
||||||
|
pub(crate) fn extent_for_bytes(self, bytes: usize) -> DecodingExtent {
|
||||||
|
match self {
|
||||||
|
DecodingSampleType::U8 => DecodingExtent::U8(bytes),
|
||||||
|
DecodingSampleType::U16 => DecodingExtent::U16(bytes.div_ceil(2)),
|
||||||
|
DecodingSampleType::U32 => DecodingExtent::U32(bytes.div_ceil(4)),
|
||||||
|
DecodingSampleType::U64 => DecodingExtent::U64(bytes.div_ceil(8)),
|
||||||
|
DecodingSampleType::I8 => DecodingExtent::I8(bytes),
|
||||||
|
DecodingSampleType::I16 => DecodingExtent::I16(bytes.div_ceil(2)),
|
||||||
|
DecodingSampleType::I32 => DecodingExtent::I32(bytes.div_ceil(4)),
|
||||||
|
DecodingSampleType::I64 => DecodingExtent::I64(bytes.div_ceil(8)),
|
||||||
|
DecodingSampleType::F16 => DecodingExtent::F16(bytes.div_ceil(2)),
|
||||||
|
DecodingSampleType::F32 => DecodingExtent::F32(bytes.div_ceil(4)),
|
||||||
|
DecodingSampleType::F64 => DecodingExtent::F64(bytes.div_ceil(8)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The count and matching discriminant for a `DecodingBuffer`.
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub(crate) enum DecodingExtent {
|
||||||
|
U8(usize),
|
||||||
|
U16(usize),
|
||||||
|
U32(usize),
|
||||||
|
U64(usize),
|
||||||
|
F16(usize),
|
||||||
|
F32(usize),
|
||||||
|
F64(usize),
|
||||||
|
I8(usize),
|
||||||
|
I16(usize),
|
||||||
|
I32(usize),
|
||||||
|
I64(usize),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DecodingExtent {
|
||||||
|
pub(crate) fn to_result_buffer(&self, limits: &Limits) -> TiffResult<DecodingSampleBuffer> {
|
||||||
|
match *self {
|
||||||
|
DecodingExtent::U8(count) => DecodingSampleBuffer::new_u8(count, limits),
|
||||||
|
DecodingExtent::U16(count) => DecodingSampleBuffer::new_u16(count, limits),
|
||||||
|
DecodingExtent::U32(count) => DecodingSampleBuffer::new_u32(count, limits),
|
||||||
|
DecodingExtent::U64(count) => DecodingSampleBuffer::new_u64(count, limits),
|
||||||
|
DecodingExtent::F16(count) => DecodingSampleBuffer::new_f16(count, limits),
|
||||||
|
DecodingExtent::F32(count) => DecodingSampleBuffer::new_f32(count, limits),
|
||||||
|
DecodingExtent::F64(count) => DecodingSampleBuffer::new_f64(count, limits),
|
||||||
|
DecodingExtent::I8(count) => DecodingSampleBuffer::new_i8(count, limits),
|
||||||
|
DecodingExtent::I16(count) => DecodingSampleBuffer::new_i16(count, limits),
|
||||||
|
DecodingExtent::I32(count) => DecodingSampleBuffer::new_i32(count, limits),
|
||||||
|
DecodingExtent::I64(count) => DecodingSampleBuffer::new_i64(count, limits),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn preferred_layout(self) -> TiffResult<Layout> {
|
||||||
|
fn overflow(_: LayoutError) -> TiffError {
|
||||||
|
TiffError::LimitsExceeded
|
||||||
|
}
|
||||||
|
|
||||||
|
match self {
|
||||||
|
DecodingExtent::U8(count) => Layout::array::<u8>(count),
|
||||||
|
DecodingExtent::U16(count) => Layout::array::<u16>(count),
|
||||||
|
DecodingExtent::U32(count) => Layout::array::<u32>(count),
|
||||||
|
DecodingExtent::U64(count) => Layout::array::<u64>(count),
|
||||||
|
DecodingExtent::F16(count) => Layout::array::<f16>(count),
|
||||||
|
DecodingExtent::F32(count) => Layout::array::<f32>(count),
|
||||||
|
DecodingExtent::F64(count) => Layout::array::<f64>(count),
|
||||||
|
DecodingExtent::I8(count) => Layout::array::<i8>(count),
|
||||||
|
DecodingExtent::I16(count) => Layout::array::<i16>(count),
|
||||||
|
DecodingExtent::I32(count) => Layout::array::<i32>(count),
|
||||||
|
DecodingExtent::I64(count) => Layout::array::<i64>(count),
|
||||||
|
}
|
||||||
|
.map_err(overflow)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn sample_type(&self) -> DecodingSampleType {
|
||||||
|
match *self {
|
||||||
|
DecodingExtent::U8(_) => DecodingSampleType::U8,
|
||||||
|
DecodingExtent::U16(_) => DecodingSampleType::U16,
|
||||||
|
DecodingExtent::U32(_) => DecodingSampleType::U32,
|
||||||
|
DecodingExtent::U64(_) => DecodingSampleType::U64,
|
||||||
|
DecodingExtent::F16(_) => DecodingSampleType::F16,
|
||||||
|
DecodingExtent::F32(_) => DecodingSampleType::F32,
|
||||||
|
DecodingExtent::F64(_) => DecodingSampleType::F64,
|
||||||
|
DecodingExtent::I8(_) => DecodingSampleType::I8,
|
||||||
|
DecodingExtent::I16(_) => DecodingSampleType::I16,
|
||||||
|
DecodingExtent::I32(_) => DecodingSampleType::I32,
|
||||||
|
DecodingExtent::I64(_) => DecodingSampleType::I64,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+16
-302
@@ -1,4 +1,3 @@
|
|||||||
use std::alloc::{Layout, LayoutError};
|
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::io::{self, Read, Seek};
|
use std::io::{self, Read, Seek};
|
||||||
use std::num::NonZeroUsize;
|
use std::num::NonZeroUsize;
|
||||||
@@ -8,14 +7,13 @@ use crate::tags::{
|
|||||||
ValueBuffer,
|
ValueBuffer,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
bytecast, ColorType, Directory, TiffError, TiffFormatError, TiffResult, TiffUnsupportedError,
|
ColorType, Directory, TiffError, TiffFormatError, TiffResult, TiffUnsupportedError, UsageError,
|
||||||
UsageError,
|
|
||||||
};
|
};
|
||||||
use half::f16;
|
|
||||||
|
|
||||||
use self::image::Image;
|
use self::image::Image;
|
||||||
use self::stream::EndianReader;
|
use self::stream::EndianReader;
|
||||||
|
|
||||||
|
mod buffer;
|
||||||
mod cycles;
|
mod cycles;
|
||||||
pub mod ifd;
|
pub mod ifd;
|
||||||
mod image;
|
mod image;
|
||||||
@@ -23,233 +21,20 @@ mod logluv;
|
|||||||
mod stream;
|
mod stream;
|
||||||
mod tag_reader;
|
mod tag_reader;
|
||||||
|
|
||||||
|
pub use self::buffer::{DecodingSampleBuffer, DecodingSampleSlice, DecodingSampleType};
|
||||||
|
|
||||||
|
#[deprecated = "Renamed to `DecodingSampleBuffer`"]
|
||||||
|
pub type DecodingResult = DecodingSampleBuffer;
|
||||||
|
|
||||||
|
#[deprecated = "Renamed to `DecodingSampleSlice`"]
|
||||||
|
pub type DecodingBuffer<'a> = DecodingSampleSlice<'a>;
|
||||||
|
|
||||||
|
use self::buffer::DecodingExtent;
|
||||||
|
|
||||||
/// An index referring to a (rectangular) region of an image.
|
/// An index referring to a (rectangular) region of an image.
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||||
pub struct TiffCodingUnit(pub u32);
|
pub struct TiffCodingUnit(pub u32);
|
||||||
|
|
||||||
/// Result of a decoding process
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum DecodingResult {
|
|
||||||
/// A vector of unsigned bytes
|
|
||||||
U8(Vec<u8>),
|
|
||||||
/// A vector of unsigned words
|
|
||||||
U16(Vec<u16>),
|
|
||||||
/// A vector of 32 bit unsigned ints
|
|
||||||
U32(Vec<u32>),
|
|
||||||
/// A vector of 64 bit unsigned ints
|
|
||||||
U64(Vec<u64>),
|
|
||||||
/// A vector of 16 bit IEEE floats (held in u16)
|
|
||||||
F16(Vec<f16>),
|
|
||||||
/// A vector of 32 bit IEEE floats
|
|
||||||
F32(Vec<f32>),
|
|
||||||
/// A vector of 64 bit IEEE floats
|
|
||||||
F64(Vec<f64>),
|
|
||||||
/// A vector of 8 bit signed ints
|
|
||||||
I8(Vec<i8>),
|
|
||||||
/// A vector of 16 bit signed ints
|
|
||||||
I16(Vec<i16>),
|
|
||||||
/// A vector of 32 bit signed ints
|
|
||||||
I32(Vec<i32>),
|
|
||||||
/// A vector of 64 bit signed ints
|
|
||||||
I64(Vec<i64>),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DecodingResult {
|
|
||||||
/// Reallocate the buffer to decode all planes of the indicated layout.
|
|
||||||
pub fn resize_to(
|
|
||||||
&mut self,
|
|
||||||
buffer: &BufferLayoutPreference,
|
|
||||||
limits: &Limits,
|
|
||||||
) -> Result<(), TiffError> {
|
|
||||||
let sample_type = buffer.sample_type.ok_or(TiffError::UnsupportedError(
|
|
||||||
TiffUnsupportedError::UnknownInterpretation,
|
|
||||||
))?;
|
|
||||||
|
|
||||||
let extent = sample_type.extent_for_bytes(buffer.complete_len);
|
|
||||||
self.resize_to_extent(extent, limits)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn resize_to_extent(
|
|
||||||
&mut self,
|
|
||||||
extent: DecodingExtent,
|
|
||||||
limits: &Limits,
|
|
||||||
) -> Result<(), TiffError> {
|
|
||||||
// FIXME: we *can* reuse the allocation sometimes.
|
|
||||||
*self = extent.to_result_buffer(limits)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn new<T: Default + Copy>(
|
|
||||||
size: usize,
|
|
||||||
limits: &Limits,
|
|
||||||
from_fn: fn(Vec<T>) -> Self,
|
|
||||||
) -> TiffResult<DecodingResult> {
|
|
||||||
if size > limits.decoding_buffer_size / core::mem::size_of::<T>() {
|
|
||||||
Err(TiffError::LimitsExceeded)
|
|
||||||
} else {
|
|
||||||
Ok(from_fn(vec![T::default(); size]))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn new_u8(size: usize, limits: &Limits) -> TiffResult<DecodingResult> {
|
|
||||||
Self::new(size, limits, DecodingResult::U8)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn new_u16(size: usize, limits: &Limits) -> TiffResult<DecodingResult> {
|
|
||||||
Self::new(size, limits, DecodingResult::U16)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn new_u32(size: usize, limits: &Limits) -> TiffResult<DecodingResult> {
|
|
||||||
Self::new(size, limits, DecodingResult::U32)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn new_u64(size: usize, limits: &Limits) -> TiffResult<DecodingResult> {
|
|
||||||
Self::new(size, limits, DecodingResult::U64)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn new_f32(size: usize, limits: &Limits) -> TiffResult<DecodingResult> {
|
|
||||||
Self::new(size, limits, DecodingResult::F32)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn new_f64(size: usize, limits: &Limits) -> TiffResult<DecodingResult> {
|
|
||||||
Self::new(size, limits, DecodingResult::F64)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn new_f16(size: usize, limits: &Limits) -> TiffResult<DecodingResult> {
|
|
||||||
Self::new(size, limits, DecodingResult::F16)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn new_i8(size: usize, limits: &Limits) -> TiffResult<DecodingResult> {
|
|
||||||
Self::new(size, limits, DecodingResult::I8)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn new_i16(size: usize, limits: &Limits) -> TiffResult<DecodingResult> {
|
|
||||||
Self::new(size, limits, DecodingResult::I16)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn new_i32(size: usize, limits: &Limits) -> TiffResult<DecodingResult> {
|
|
||||||
Self::new(size, limits, DecodingResult::I32)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn new_i64(size: usize, limits: &Limits) -> TiffResult<DecodingResult> {
|
|
||||||
Self::new(size, limits, DecodingResult::I64)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get a view of this buffer starting from the nth _sample_ of the current type.
|
|
||||||
pub fn as_buffer(&mut self, start: usize) -> DecodingBuffer<'_> {
|
|
||||||
match *self {
|
|
||||||
DecodingResult::U8(ref mut buf) => DecodingBuffer::U8(&mut buf[start..]),
|
|
||||||
DecodingResult::U16(ref mut buf) => DecodingBuffer::U16(&mut buf[start..]),
|
|
||||||
DecodingResult::U32(ref mut buf) => DecodingBuffer::U32(&mut buf[start..]),
|
|
||||||
DecodingResult::U64(ref mut buf) => DecodingBuffer::U64(&mut buf[start..]),
|
|
||||||
DecodingResult::F16(ref mut buf) => DecodingBuffer::F16(&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..]),
|
|
||||||
DecodingResult::I32(ref mut buf) => DecodingBuffer::I32(&mut buf[start..]),
|
|
||||||
DecodingResult::I64(ref mut buf) => DecodingBuffer::I64(&mut buf[start..]),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// A buffer for image decoding
|
|
||||||
pub enum DecodingBuffer<'a> {
|
|
||||||
/// A slice of unsigned bytes
|
|
||||||
U8(&'a mut [u8]),
|
|
||||||
/// A slice of unsigned words
|
|
||||||
U16(&'a mut [u16]),
|
|
||||||
/// A slice of 32 bit unsigned ints
|
|
||||||
U32(&'a mut [u32]),
|
|
||||||
/// A slice of 64 bit unsigned ints
|
|
||||||
U64(&'a mut [u64]),
|
|
||||||
/// A slice of 16 bit IEEE floats
|
|
||||||
F16(&'a mut [f16]),
|
|
||||||
/// A slice of 32 bit IEEE floats
|
|
||||||
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]),
|
|
||||||
/// A slice of 32 bits signed ints
|
|
||||||
I32(&'a mut [i32]),
|
|
||||||
/// A slice of 64 bits signed ints
|
|
||||||
I64(&'a mut [i64]),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> DecodingBuffer<'a> {
|
|
||||||
pub fn as_bytes(&self) -> &[u8] {
|
|
||||||
match self {
|
|
||||||
DecodingBuffer::U8(buf) => buf,
|
|
||||||
DecodingBuffer::I8(buf) => bytecast::i8_as_ne_bytes(buf),
|
|
||||||
DecodingBuffer::U16(buf) => bytecast::u16_as_ne_bytes(buf),
|
|
||||||
DecodingBuffer::I16(buf) => bytecast::i16_as_ne_bytes(buf),
|
|
||||||
DecodingBuffer::U32(buf) => bytecast::u32_as_ne_bytes(buf),
|
|
||||||
DecodingBuffer::I32(buf) => bytecast::i32_as_ne_bytes(buf),
|
|
||||||
DecodingBuffer::U64(buf) => bytecast::u64_as_ne_bytes(buf),
|
|
||||||
DecodingBuffer::I64(buf) => bytecast::i64_as_ne_bytes(buf),
|
|
||||||
DecodingBuffer::F16(buf) => bytecast::f16_as_ne_bytes(buf),
|
|
||||||
DecodingBuffer::F32(buf) => bytecast::f32_as_ne_bytes(buf),
|
|
||||||
DecodingBuffer::F64(buf) => bytecast::f64_as_ne_bytes(buf),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn as_bytes_mut(&mut self) -> &mut [u8] {
|
|
||||||
match self {
|
|
||||||
DecodingBuffer::U8(buf) => buf,
|
|
||||||
DecodingBuffer::I8(buf) => bytecast::i8_as_ne_mut_bytes(buf),
|
|
||||||
DecodingBuffer::U16(buf) => bytecast::u16_as_ne_mut_bytes(buf),
|
|
||||||
DecodingBuffer::I16(buf) => bytecast::i16_as_ne_mut_bytes(buf),
|
|
||||||
DecodingBuffer::U32(buf) => bytecast::u32_as_ne_mut_bytes(buf),
|
|
||||||
DecodingBuffer::I32(buf) => bytecast::i32_as_ne_mut_bytes(buf),
|
|
||||||
DecodingBuffer::U64(buf) => bytecast::u64_as_ne_mut_bytes(buf),
|
|
||||||
DecodingBuffer::I64(buf) => bytecast::i64_as_ne_mut_bytes(buf),
|
|
||||||
DecodingBuffer::F16(buf) => bytecast::f16_as_ne_mut_bytes(buf),
|
|
||||||
DecodingBuffer::F32(buf) => bytecast::f32_as_ne_mut_bytes(buf),
|
|
||||||
DecodingBuffer::F64(buf) => bytecast::f64_as_ne_mut_bytes(buf),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn byte_len(&self) -> usize {
|
|
||||||
self.as_bytes().len()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
||||||
pub enum DecodingSampleType {
|
|
||||||
U8,
|
|
||||||
U16,
|
|
||||||
U32,
|
|
||||||
U64,
|
|
||||||
F16,
|
|
||||||
F32,
|
|
||||||
F64,
|
|
||||||
I8,
|
|
||||||
I16,
|
|
||||||
I32,
|
|
||||||
I64,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DecodingSampleType {
|
|
||||||
fn extent_for_bytes(self, bytes: usize) -> DecodingExtent {
|
|
||||||
match self {
|
|
||||||
DecodingSampleType::U8 => DecodingExtent::U8(bytes),
|
|
||||||
DecodingSampleType::U16 => DecodingExtent::U16(bytes.div_ceil(2)),
|
|
||||||
DecodingSampleType::U32 => DecodingExtent::U32(bytes.div_ceil(4)),
|
|
||||||
DecodingSampleType::U64 => DecodingExtent::U64(bytes.div_ceil(8)),
|
|
||||||
DecodingSampleType::I8 => DecodingExtent::I8(bytes),
|
|
||||||
DecodingSampleType::I16 => DecodingExtent::I16(bytes.div_ceil(2)),
|
|
||||||
DecodingSampleType::I32 => DecodingExtent::I32(bytes.div_ceil(4)),
|
|
||||||
DecodingSampleType::I64 => DecodingExtent::I64(bytes.div_ceil(8)),
|
|
||||||
DecodingSampleType::F16 => DecodingExtent::F16(bytes.div_ceil(2)),
|
|
||||||
DecodingSampleType::F32 => DecodingExtent::F32(bytes.div_ceil(4)),
|
|
||||||
DecodingSampleType::F64 => DecodingExtent::F64(bytes.div_ceil(8)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Information on the byte buffer that should be supplied to the decoder.
|
/// Information on the byte buffer that should be supplied to the decoder.
|
||||||
///
|
///
|
||||||
/// This is relevant for [`Decoder::read_image_bytes`] and [`Decoder::read_chunk_bytes`] where the
|
/// This is relevant for [`Decoder::read_image_bytes`] and [`Decoder::read_chunk_bytes`] where the
|
||||||
@@ -383,77 +168,6 @@ impl image::ReadoutLayout {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The count and matching discriminant for a `DecodingBuffer`.
|
|
||||||
#[derive(Clone)]
|
|
||||||
enum DecodingExtent {
|
|
||||||
U8(usize),
|
|
||||||
U16(usize),
|
|
||||||
U32(usize),
|
|
||||||
U64(usize),
|
|
||||||
F16(usize),
|
|
||||||
F32(usize),
|
|
||||||
F64(usize),
|
|
||||||
I8(usize),
|
|
||||||
I16(usize),
|
|
||||||
I32(usize),
|
|
||||||
I64(usize),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DecodingExtent {
|
|
||||||
fn to_result_buffer(&self, limits: &Limits) -> TiffResult<DecodingResult> {
|
|
||||||
match *self {
|
|
||||||
DecodingExtent::U8(count) => DecodingResult::new_u8(count, limits),
|
|
||||||
DecodingExtent::U16(count) => DecodingResult::new_u16(count, limits),
|
|
||||||
DecodingExtent::U32(count) => DecodingResult::new_u32(count, limits),
|
|
||||||
DecodingExtent::U64(count) => DecodingResult::new_u64(count, limits),
|
|
||||||
DecodingExtent::F16(count) => DecodingResult::new_f16(count, limits),
|
|
||||||
DecodingExtent::F32(count) => DecodingResult::new_f32(count, limits),
|
|
||||||
DecodingExtent::F64(count) => DecodingResult::new_f64(count, limits),
|
|
||||||
DecodingExtent::I8(count) => DecodingResult::new_i8(count, limits),
|
|
||||||
DecodingExtent::I16(count) => DecodingResult::new_i16(count, limits),
|
|
||||||
DecodingExtent::I32(count) => DecodingResult::new_i32(count, limits),
|
|
||||||
DecodingExtent::I64(count) => DecodingResult::new_i64(count, limits),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn preferred_layout(self) -> TiffResult<Layout> {
|
|
||||||
fn overflow(_: LayoutError) -> TiffError {
|
|
||||||
TiffError::LimitsExceeded
|
|
||||||
}
|
|
||||||
|
|
||||||
match self {
|
|
||||||
DecodingExtent::U8(count) => Layout::array::<u8>(count),
|
|
||||||
DecodingExtent::U16(count) => Layout::array::<u16>(count),
|
|
||||||
DecodingExtent::U32(count) => Layout::array::<u32>(count),
|
|
||||||
DecodingExtent::U64(count) => Layout::array::<u64>(count),
|
|
||||||
DecodingExtent::F16(count) => Layout::array::<f16>(count),
|
|
||||||
DecodingExtent::F32(count) => Layout::array::<f32>(count),
|
|
||||||
DecodingExtent::F64(count) => Layout::array::<f64>(count),
|
|
||||||
DecodingExtent::I8(count) => Layout::array::<i8>(count),
|
|
||||||
DecodingExtent::I16(count) => Layout::array::<i16>(count),
|
|
||||||
DecodingExtent::I32(count) => Layout::array::<i32>(count),
|
|
||||||
DecodingExtent::I64(count) => Layout::array::<i64>(count),
|
|
||||||
}
|
|
||||||
.map_err(overflow)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn sample_type(&self) -> DecodingSampleType {
|
|
||||||
match *self {
|
|
||||||
DecodingExtent::U8(_) => DecodingSampleType::U8,
|
|
||||||
DecodingExtent::U16(_) => DecodingSampleType::U16,
|
|
||||||
DecodingExtent::U32(_) => DecodingSampleType::U32,
|
|
||||||
DecodingExtent::U64(_) => DecodingSampleType::U64,
|
|
||||||
DecodingExtent::F16(_) => DecodingSampleType::F16,
|
|
||||||
DecodingExtent::F32(_) => DecodingSampleType::F32,
|
|
||||||
DecodingExtent::F64(_) => DecodingSampleType::F64,
|
|
||||||
DecodingExtent::I8(_) => DecodingSampleType::I8,
|
|
||||||
DecodingExtent::I16(_) => DecodingSampleType::I16,
|
|
||||||
DecodingExtent::I32(_) => DecodingSampleType::I32,
|
|
||||||
DecodingExtent::I64(_) => DecodingSampleType::I64,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||||
/// Chunk type of the internal representation
|
/// Chunk type of the internal representation
|
||||||
pub enum ChunkType {
|
pub enum ChunkType {
|
||||||
@@ -1400,7 +1114,7 @@ impl<R: Read + Seek> Decoder<R> {
|
|||||||
/// Read the specified chunk (at index `chunk_index`) and return the binary data as a Vector.
|
/// Read the specified chunk (at index `chunk_index`) and return the binary data as a Vector.
|
||||||
///
|
///
|
||||||
/// Note that for planar images each chunk contains only one sample of the underlying data.
|
/// Note that for planar images each chunk contains only one sample of the underlying data.
|
||||||
pub fn read_chunk(&mut self, chunk_index: u32) -> TiffResult<DecodingResult> {
|
pub fn read_chunk(&mut self, chunk_index: u32) -> TiffResult<DecodingSampleBuffer> {
|
||||||
let (width, height) = self.image.chunk_data_dimensions(chunk_index)?;
|
let (width, height) = self.image.chunk_data_dimensions(chunk_index)?;
|
||||||
|
|
||||||
let readout = self.image.readout_for_size(width, height)?;
|
let readout = self.image.readout_for_size(width, height)?;
|
||||||
@@ -1441,7 +1155,7 @@ impl<R: Read + Seek> Decoder<R> {
|
|||||||
/// Note that for planar images each chunk contains only one sample of the underlying data.
|
/// Note that for planar images each chunk contains only one sample of the underlying data.
|
||||||
pub fn read_chunk_to_buffer(
|
pub fn read_chunk_to_buffer(
|
||||||
&mut self,
|
&mut self,
|
||||||
buffer: &mut DecodingResult,
|
buffer: &mut DecodingSampleBuffer,
|
||||||
chunk_index: u32,
|
chunk_index: u32,
|
||||||
output_width: usize,
|
output_width: usize,
|
||||||
) -> TiffResult<()> {
|
) -> TiffResult<()> {
|
||||||
@@ -1564,7 +1278,7 @@ impl<R: Read + Seek> Decoder<R> {
|
|||||||
/// calls. This old method will likely keep its bugged planar behavior until it is fully
|
/// calls. This old method will likely keep its bugged planar behavior until it is fully
|
||||||
/// replaced, to ensure that existing code will not run into unexpectedly large allocations
|
/// replaced, to ensure that existing code will not run into unexpectedly large allocations
|
||||||
/// that will error on limits instead.
|
/// that will error on limits instead.
|
||||||
pub fn read_image(&mut self) -> TiffResult<DecodingResult> {
|
pub fn read_image(&mut self) -> TiffResult<DecodingSampleBuffer> {
|
||||||
let readout = self.image.readout_for_image()?;
|
let readout = self.image.readout_for_image()?;
|
||||||
|
|
||||||
let mut result = readout
|
let mut result = readout
|
||||||
@@ -1625,7 +1339,7 @@ impl<R: Read + Seek> Decoder<R> {
|
|||||||
/// ```
|
/// ```
|
||||||
pub fn read_image_to_buffer(
|
pub fn read_image_to_buffer(
|
||||||
&mut self,
|
&mut self,
|
||||||
result: &mut DecodingResult,
|
result: &mut DecodingSampleBuffer,
|
||||||
) -> TiffResult<BufferLayoutPreference> {
|
) -> TiffResult<BufferLayoutPreference> {
|
||||||
let readout = self.image.readout_for_image()?;
|
let readout = self.image.readout_for_image()?;
|
||||||
let planes = readout.to_plane_layout()?;
|
let planes = readout.to_plane_layout()?;
|
||||||
|
|||||||
@@ -221,7 +221,7 @@ fn encoder_on_short_writes() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let imgdata = vec![42u8; 100 * 100];
|
let imgdata = vec![42u8; 100 * 100];
|
||||||
let mut data = crate::decoder::DecodingResult::U8(vec![]);
|
let mut data = crate::decoder::DecodingSampleBuffer::U8(vec![]);
|
||||||
|
|
||||||
for comp in [
|
for comp in [
|
||||||
super::Compression::Uncompressed,
|
super::Compression::Uncompressed,
|
||||||
@@ -247,7 +247,7 @@ fn encoder_on_short_writes() {
|
|||||||
let _layout = tiff_reader.read_image_to_buffer(&mut data).unwrap();
|
let _layout = tiff_reader.read_image_to_buffer(&mut data).unwrap();
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
matches!(&data, crate::decoder::DecodingResult::U8(v) if *v == imgdata),
|
matches!(&data, crate::decoder::DecodingSampleBuffer::U8(v) if *v == imgdata),
|
||||||
"{data:?} @ {}",
|
"{data:?} @ {}",
|
||||||
data.as_buffer(0).byte_len()
|
data.as_buffer(0).byte_len()
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
extern crate tiff;
|
extern crate tiff;
|
||||||
|
|
||||||
use tiff::decoder::{Decoder, DecodingResult};
|
use tiff::decoder::{Decoder, DecodingSampleBuffer};
|
||||||
use tiff::ColorType;
|
use tiff::ColorType;
|
||||||
|
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
@@ -28,7 +28,7 @@ fn test_white_ieee_fp16() {
|
|||||||
ColorType::Gray(16)
|
ColorType::Gray(16)
|
||||||
);
|
);
|
||||||
|
|
||||||
if let DecodingResult::F16(img) = decoder.read_image().unwrap() {
|
if let DecodingSampleBuffer::F16(img) = decoder.read_image().unwrap() {
|
||||||
for p in img {
|
for p in img {
|
||||||
assert!(p == half::f16::from_f32_const(1.0));
|
assert!(p == half::f16::from_f32_const(1.0));
|
||||||
}
|
}
|
||||||
@@ -58,7 +58,7 @@ fn test_one_black_pixel_ieee_fp16() {
|
|||||||
ColorType::Gray(16)
|
ColorType::Gray(16)
|
||||||
);
|
);
|
||||||
|
|
||||||
if let DecodingResult::F16(img) = decoder.read_image().unwrap() {
|
if let DecodingSampleBuffer::F16(img) = decoder.read_image().unwrap() {
|
||||||
for (i, p) in img.iter().enumerate() {
|
for (i, p) in img.iter().enumerate() {
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
assert!(p < &half::f16::from_f32_const(0.001));
|
assert!(p < &half::f16::from_f32_const(0.001));
|
||||||
@@ -92,7 +92,7 @@ fn test_pattern_horizontal_differencing_ieee_fp16() {
|
|||||||
ColorType::Gray(16)
|
ColorType::Gray(16)
|
||||||
);
|
);
|
||||||
|
|
||||||
if let DecodingResult::F16(img) = decoder.read_image().unwrap() {
|
if let DecodingSampleBuffer::F16(img) = decoder.read_image().unwrap() {
|
||||||
// 0, 2, 5, 8, 12, 16, 255 are black
|
// 0, 2, 5, 8, 12, 16, 255 are black
|
||||||
let black = [0, 2, 5, 8, 12, 16, 255];
|
let black = [0, 2, 5, 8, 12, 16, 255];
|
||||||
for (i, p) in img.iter().enumerate() {
|
for (i, p) in img.iter().enumerate() {
|
||||||
@@ -128,7 +128,7 @@ fn test_pattern_predictor_ieee_fp16() {
|
|||||||
ColorType::Gray(16)
|
ColorType::Gray(16)
|
||||||
);
|
);
|
||||||
|
|
||||||
if let DecodingResult::F16(img) = decoder.read_image().unwrap() {
|
if let DecodingSampleBuffer::F16(img) = decoder.read_image().unwrap() {
|
||||||
// 0, 2, 5, 8, 12, 16, 255 are black
|
// 0, 2, 5, 8, 12, 16, 255 are black
|
||||||
let black = [0, 2, 5, 8, 12, 16, 255];
|
let black = [0, 2, 5, 8, 12, 16, 255];
|
||||||
for (i, p) in img.iter().enumerate() {
|
for (i, p) in img.iter().enumerate() {
|
||||||
@@ -199,7 +199,7 @@ fn test_predictor_ieee_fp16() {
|
|||||||
ColorType::Gray(16)
|
ColorType::Gray(16)
|
||||||
);
|
);
|
||||||
|
|
||||||
if let DecodingResult::F16(img) = decoder.read_image().unwrap() {
|
if let DecodingSampleBuffer::F16(img) = decoder.read_image().unwrap() {
|
||||||
for (exp, found) in std::iter::zip(pnm_values.iter(), img.iter()) {
|
for (exp, found) in std::iter::zip(pnm_values.iter(), img.iter()) {
|
||||||
assert!((exp - found.to_f32()).abs() < 0.0001);
|
assert!((exp - found.to_f32()).abs() < 0.0001);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
extern crate tiff;
|
extern crate tiff;
|
||||||
|
|
||||||
use tiff::decoder::{Decoder, DecodingResult};
|
use tiff::decoder::{Decoder, DecodingSampleBuffer};
|
||||||
use tiff::tags::Tag;
|
use tiff::tags::Tag;
|
||||||
use tiff::ColorType;
|
use tiff::ColorType;
|
||||||
|
|
||||||
@@ -56,7 +56,7 @@ fn test_geo_tiff() {
|
|||||||
.expect("Cannot get pixel scale"),
|
.expect("Cannot get pixel scale"),
|
||||||
vec![60.0, 60.0, 0.0]
|
vec![60.0, 60.0, 0.0]
|
||||||
);
|
);
|
||||||
let DecodingResult::I16(data) = decoder.read_image().unwrap() else {
|
let DecodingSampleBuffer::I16(data) = decoder.read_image().unwrap() else {
|
||||||
panic!("Cannot read band data")
|
panic!("Cannot read band data")
|
||||||
};
|
};
|
||||||
assert_eq!(data.len(), 500);
|
assert_eq!(data.len(), 500);
|
||||||
@@ -67,7 +67,7 @@ fn test_geo_tiff() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_webp_tiff() {
|
fn test_webp_tiff() {
|
||||||
let filenames = ["usda_naip_256_webp_z3.tif"];
|
let filenames = ["usda_naip_256_webp_z3.tif"];
|
||||||
let mut buffer = DecodingResult::U8(vec![]);
|
let mut buffer = DecodingSampleBuffer::U8(vec![]);
|
||||||
|
|
||||||
for filename in filenames.iter() {
|
for filename in filenames.iter() {
|
||||||
let path = PathBuf::from(TEST_IMAGE_DIR).join(filename);
|
let path = PathBuf::from(TEST_IMAGE_DIR).join(filename);
|
||||||
|
|||||||
+20
-20
@@ -1,6 +1,6 @@
|
|||||||
extern crate tiff;
|
extern crate tiff;
|
||||||
|
|
||||||
use tiff::decoder::{ifd, Decoder, DecodingResult};
|
use tiff::decoder::{ifd, Decoder, DecodingSampleBuffer};
|
||||||
use tiff::tags::{ByteOrder, Type};
|
use tiff::tags::{ByteOrder, Type};
|
||||||
use tiff::ColorType;
|
use tiff::ColorType;
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@ macro_rules! test_image_sum {
|
|||||||
let img_res = decoder.read_image().unwrap();
|
let img_res = decoder.read_image().unwrap();
|
||||||
|
|
||||||
match img_res {
|
match img_res {
|
||||||
DecodingResult::$buffer(res) => {
|
DecodingSampleBuffer::$buffer(res) => {
|
||||||
let sum: $sum_ty = res.into_iter().map(<$sum_ty>::from).sum();
|
let sum: $sum_ty = res.into_iter().map(<$sum_ty>::from).sum();
|
||||||
assert_eq!(sum, expected_sum);
|
assert_eq!(sum, expected_sum);
|
||||||
}
|
}
|
||||||
@@ -88,17 +88,17 @@ fn compute_tiff_hash<R: Read + Seek>(reader: R) -> u32 {
|
|||||||
// Hash decoded data: TIFF type tag (u16 repr) + LE sample bytes.
|
// Hash decoded data: TIFF type tag (u16 repr) + LE sample bytes.
|
||||||
// Map each variant to the corresponding TIFF Type for byte-order normalization.
|
// Map each variant to the corresponding TIFF Type for byte-order normalization.
|
||||||
let sample_type = match &result {
|
let sample_type = match &result {
|
||||||
DecodingResult::U8(_) => Type::BYTE,
|
DecodingSampleBuffer::U8(_) => Type::BYTE,
|
||||||
DecodingResult::I8(_) => Type::SBYTE,
|
DecodingSampleBuffer::I8(_) => Type::SBYTE,
|
||||||
DecodingResult::U16(_) => Type::SHORT,
|
DecodingSampleBuffer::U16(_) => Type::SHORT,
|
||||||
DecodingResult::I16(_) => Type::SSHORT,
|
DecodingSampleBuffer::I16(_) => Type::SSHORT,
|
||||||
DecodingResult::U32(_) => Type::LONG,
|
DecodingSampleBuffer::U32(_) => Type::LONG,
|
||||||
DecodingResult::I32(_) => Type::SLONG,
|
DecodingSampleBuffer::I32(_) => Type::SLONG,
|
||||||
DecodingResult::F32(_) => Type::FLOAT,
|
DecodingSampleBuffer::F32(_) => Type::FLOAT,
|
||||||
DecodingResult::U64(_) => Type::LONG8,
|
DecodingSampleBuffer::U64(_) => Type::LONG8,
|
||||||
DecodingResult::I64(_) => Type::SLONG8,
|
DecodingSampleBuffer::I64(_) => Type::SLONG8,
|
||||||
DecodingResult::F64(_) => Type::DOUBLE,
|
DecodingSampleBuffer::F64(_) => Type::DOUBLE,
|
||||||
DecodingResult::F16(_) => Type::SHORT, // f16 is 2 bytes like SHORT
|
DecodingSampleBuffer::F16(_) => Type::SHORT, // f16 is 2 bytes like SHORT
|
||||||
};
|
};
|
||||||
hasher.update(&sample_type.to_u16().to_le_bytes());
|
hasher.update(&sample_type.to_u16().to_le_bytes());
|
||||||
|
|
||||||
@@ -431,7 +431,7 @@ fn test_decode_data() {
|
|||||||
decoder.next_image().expect("Cannot read image IFD");
|
decoder.next_image().expect("Cannot read image IFD");
|
||||||
assert_eq!(decoder.colortype().unwrap(), ColorType::RGB(8));
|
assert_eq!(decoder.colortype().unwrap(), ColorType::RGB(8));
|
||||||
assert_eq!(decoder.dimensions().unwrap(), (100, 100));
|
assert_eq!(decoder.dimensions().unwrap(), (100, 100));
|
||||||
if let DecodingResult::U8(img_res) = decoder.read_image().unwrap() {
|
if let DecodingSampleBuffer::U8(img_res) = decoder.read_image().unwrap() {
|
||||||
assert_eq!(image_data, img_res);
|
assert_eq!(image_data, img_res);
|
||||||
} else {
|
} else {
|
||||||
panic!("Wrong data type");
|
panic!("Wrong data type");
|
||||||
@@ -511,7 +511,7 @@ fn test_inner_access() {
|
|||||||
let raw_sum: u64 = buf.into_iter().map(<u64>::from).sum();
|
let raw_sum: u64 = buf.into_iter().map(<u64>::from).sum();
|
||||||
|
|
||||||
match decoder.read_chunk(0).unwrap() {
|
match decoder.read_chunk(0).unwrap() {
|
||||||
DecodingResult::U8(chunk) => {
|
DecodingSampleBuffer::U8(chunk) => {
|
||||||
let sum: u64 = chunk.into_iter().map(<u64>::from).sum();
|
let sum: u64 = chunk.into_iter().map(<u64>::from).sum();
|
||||||
assert_eq!(sum, raw_sum);
|
assert_eq!(sum, raw_sum);
|
||||||
}
|
}
|
||||||
@@ -570,7 +570,7 @@ fn test_tiled_incremental() {
|
|||||||
|
|
||||||
for tile in 0..tiles {
|
for tile in 0..tiles {
|
||||||
match decoder.read_chunk(tile).unwrap() {
|
match decoder.read_chunk(tile).unwrap() {
|
||||||
DecodingResult::U8(res) => {
|
DecodingSampleBuffer::U8(res) => {
|
||||||
let sum: u64 = res.into_iter().map(<u64>::from).sum();
|
let sum: u64 = res.into_iter().map(<u64>::from).sum();
|
||||||
assert_eq!(sum, sums[tile as usize]);
|
assert_eq!(sum, sums[tile as usize]);
|
||||||
}
|
}
|
||||||
@@ -604,21 +604,21 @@ fn test_read_planar_bands() {
|
|||||||
|
|
||||||
// 1st band (red)
|
// 1st band (red)
|
||||||
match decoder.read_chunk(0).unwrap() {
|
match decoder.read_chunk(0).unwrap() {
|
||||||
DecodingResult::U8(chunk) => {
|
DecodingSampleBuffer::U8(chunk) => {
|
||||||
assert_eq!(chunk[0], 73);
|
assert_eq!(chunk[0], 73);
|
||||||
}
|
}
|
||||||
_ => panic!("Wrong bit depth"),
|
_ => panic!("Wrong bit depth"),
|
||||||
}
|
}
|
||||||
// 2nd band (green)
|
// 2nd band (green)
|
||||||
match decoder.read_chunk(chunks / 3).unwrap() {
|
match decoder.read_chunk(chunks / 3).unwrap() {
|
||||||
DecodingResult::U8(chunk) => {
|
DecodingSampleBuffer::U8(chunk) => {
|
||||||
assert_eq!(chunk[0], 51);
|
assert_eq!(chunk[0], 51);
|
||||||
}
|
}
|
||||||
_ => panic!("Wrong bit depth"),
|
_ => panic!("Wrong bit depth"),
|
||||||
}
|
}
|
||||||
// 3rd band (blue)
|
// 3rd band (blue)
|
||||||
match decoder.read_chunk(chunks / 3 * 2).unwrap() {
|
match decoder.read_chunk(chunks / 3 * 2).unwrap() {
|
||||||
DecodingResult::U8(chunk) => {
|
DecodingSampleBuffer::U8(chunk) => {
|
||||||
assert_eq!(chunk[0], 30);
|
assert_eq!(chunk[0], 30);
|
||||||
}
|
}
|
||||||
_ => panic!("Wrong bit depth"),
|
_ => panic!("Wrong bit depth"),
|
||||||
@@ -994,7 +994,7 @@ fn test_decode_huge_g4() {
|
|||||||
.read_image()
|
.read_image()
|
||||||
.expect("failed to decode huge G4 image");
|
.expect("failed to decode huge G4 image");
|
||||||
|
|
||||||
if let tiff::decoder::DecodingResult::U8(data) = result {
|
if let tiff::decoder::DecodingSampleBuffer::U8(data) = result {
|
||||||
assert_eq!(data.len(), (width as usize * height as usize));
|
assert_eq!(data.len(), (width as usize * height as usize));
|
||||||
} else {
|
} else {
|
||||||
panic!("Unexpected decoding result type");
|
panic!("Unexpected decoding result type");
|
||||||
|
|||||||
+14
-14
@@ -1,7 +1,7 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::{fs::File, path};
|
use std::{fs::File, path};
|
||||||
|
|
||||||
use tiff::decoder::{Decoder, DecodingResult};
|
use tiff::decoder::{Decoder, DecodingSampleBuffer};
|
||||||
use tiff::tags::{ByteOrder, Type};
|
use tiff::tags::{ByteOrder, Type};
|
||||||
use tiff::ColorType;
|
use tiff::ColorType;
|
||||||
|
|
||||||
@@ -252,19 +252,19 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Map DecodingResult variant to a TIFF Type for byte-order normalization.
|
/// Map DecodingResult variant to a TIFF Type for byte-order normalization.
|
||||||
fn sample_type_of(result: &DecodingResult) -> Type {
|
fn sample_type_of(result: &DecodingSampleBuffer) -> Type {
|
||||||
match result {
|
match result {
|
||||||
DecodingResult::U8(_) => Type::BYTE,
|
DecodingSampleBuffer::U8(_) => Type::BYTE,
|
||||||
DecodingResult::I8(_) => Type::SBYTE,
|
DecodingSampleBuffer::I8(_) => Type::SBYTE,
|
||||||
DecodingResult::U16(_) => Type::SHORT,
|
DecodingSampleBuffer::U16(_) => Type::SHORT,
|
||||||
DecodingResult::I16(_) => Type::SSHORT,
|
DecodingSampleBuffer::I16(_) => Type::SSHORT,
|
||||||
DecodingResult::U32(_) => Type::LONG,
|
DecodingSampleBuffer::U32(_) => Type::LONG,
|
||||||
DecodingResult::I32(_) => Type::SLONG,
|
DecodingSampleBuffer::I32(_) => Type::SLONG,
|
||||||
DecodingResult::F32(_) => Type::FLOAT,
|
DecodingSampleBuffer::F32(_) => Type::FLOAT,
|
||||||
DecodingResult::U64(_) => Type::LONG8,
|
DecodingSampleBuffer::U64(_) => Type::LONG8,
|
||||||
DecodingResult::I64(_) => Type::SLONG8,
|
DecodingSampleBuffer::I64(_) => Type::SLONG8,
|
||||||
DecodingResult::F64(_) => Type::DOUBLE,
|
DecodingSampleBuffer::F64(_) => Type::DOUBLE,
|
||||||
DecodingResult::F16(_) => Type::SHORT, // f16 is 2 bytes like SHORT
|
DecodingSampleBuffer::F16(_) => Type::SHORT, // f16 is 2 bytes like SHORT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -299,7 +299,7 @@ fn compute_hash(path: &std::path::Path) -> Result<u32, tiff::TiffError> {
|
|||||||
let img_file = File::open(path)?;
|
let img_file = File::open(path)?;
|
||||||
let mut decoder = Decoder::open(img_file)?;
|
let mut decoder = Decoder::open(img_file)?;
|
||||||
let mut hasher = crc32fast::Hasher::new();
|
let mut hasher = crc32fast::Hasher::new();
|
||||||
let mut buffer = DecodingResult::U8(vec![]);
|
let mut buffer = DecodingSampleBuffer::U8(vec![]);
|
||||||
|
|
||||||
let mut page = 0u32;
|
let mut page = 0u32;
|
||||||
while decoder.more_images() {
|
while decoder.more_images() {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use tiff::decoder::{Decoder, DecodingResult, Limits, TiffCodingUnit};
|
use tiff::decoder::{Decoder, DecodingSampleBuffer, Limits, TiffCodingUnit};
|
||||||
|
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
@@ -84,7 +84,7 @@ fn read_planes_by_limits() {
|
|||||||
let io = std::io::BufReader::new(file);
|
let io = std::io::BufReader::new(file);
|
||||||
|
|
||||||
let mut limits = Limits::default();
|
let mut limits = Limits::default();
|
||||||
let mut buffer = DecodingResult::U8(vec![]);
|
let mut buffer = DecodingSampleBuffer::U8(vec![]);
|
||||||
|
|
||||||
// Make room for 1 plane.
|
// Make room for 1 plane.
|
||||||
let mut tif = Decoder::open(io).unwrap();
|
let mut tif = Decoder::open(io).unwrap();
|
||||||
|
|||||||
+16
-16
@@ -1,6 +1,6 @@
|
|||||||
extern crate tiff;
|
extern crate tiff;
|
||||||
|
|
||||||
use tiff::decoder::{ifd, Decoder, DecodingResult};
|
use tiff::decoder::{ifd, Decoder, DecodingSampleBuffer};
|
||||||
use tiff::encoder::{colortype, Ifd, Ifd8, Predictor, SRational, TiffEncoder};
|
use tiff::encoder::{colortype, Ifd, Ifd8, Predictor, SRational, TiffEncoder};
|
||||||
use tiff::tags::Tag;
|
use tiff::tags::Tag;
|
||||||
use tiff::ColorType;
|
use tiff::ColorType;
|
||||||
@@ -84,9 +84,9 @@ fn encode_decode() {
|
|||||||
ifd::Value::Ascii("Image-tiff".into())
|
ifd::Value::Ascii("Image-tiff".into())
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut buffer = tiff::decoder::DecodingResult::U8(vec![]);
|
let mut buffer = tiff::decoder::DecodingSampleBuffer::U8(vec![]);
|
||||||
let _layout = decoder.read_image_to_buffer(&mut buffer).unwrap();
|
let _layout = decoder.read_image_to_buffer(&mut buffer).unwrap();
|
||||||
if let tiff::decoder::DecodingResult::U8(img_res) = buffer {
|
if let tiff::decoder::DecodingSampleBuffer::U8(img_res) = buffer {
|
||||||
assert_eq!(image_data, img_res);
|
assert_eq!(image_data, img_res);
|
||||||
} else {
|
} else {
|
||||||
panic!("Wrong data type");
|
panic!("Wrong data type");
|
||||||
@@ -168,9 +168,9 @@ fn encode_decode_big() {
|
|||||||
decoder.get_tag(Tag::Artist).unwrap(),
|
decoder.get_tag(Tag::Artist).unwrap(),
|
||||||
ifd::Value::Ascii("Image-tiff".into())
|
ifd::Value::Ascii("Image-tiff".into())
|
||||||
);
|
);
|
||||||
let mut buffer = tiff::decoder::DecodingResult::U8(vec![]);
|
let mut buffer = tiff::decoder::DecodingSampleBuffer::U8(vec![]);
|
||||||
let _layout = decoder.read_image_to_buffer(&mut buffer).unwrap();
|
let _layout = decoder.read_image_to_buffer(&mut buffer).unwrap();
|
||||||
if let DecodingResult::U8(img_res) = buffer {
|
if let DecodingSampleBuffer::U8(img_res) = buffer {
|
||||||
assert_eq!(image_data, img_res);
|
assert_eq!(image_data, img_res);
|
||||||
} else {
|
} else {
|
||||||
panic!("Wrong data type");
|
panic!("Wrong data type");
|
||||||
@@ -258,11 +258,11 @@ macro_rules! test_roundtrip {
|
|||||||
|
|
||||||
assert_eq!(decoder.colortype().unwrap(), expected_type);
|
assert_eq!(decoder.colortype().unwrap(), expected_type);
|
||||||
|
|
||||||
let mut buffer = tiff::decoder::DecodingResult::U8(vec![]);
|
let mut buffer = tiff::decoder::DecodingSampleBuffer::U8(vec![]);
|
||||||
decoder.read_image_to_buffer(&mut buffer).unwrap();
|
decoder.read_image_to_buffer(&mut buffer).unwrap();
|
||||||
|
|
||||||
let image_data = match buffer {
|
let image_data = match buffer {
|
||||||
DecodingResult::$buffer(res) => res,
|
DecodingSampleBuffer::$buffer(res) => res,
|
||||||
_ => panic!("Wrong data type"),
|
_ => panic!("Wrong data type"),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -275,11 +275,11 @@ macro_rules! test_roundtrip {
|
|||||||
}
|
}
|
||||||
file.seek(SeekFrom::Start(0)).unwrap();
|
file.seek(SeekFrom::Start(0)).unwrap();
|
||||||
{
|
{
|
||||||
let mut buffer = tiff::decoder::DecodingResult::U8(vec![]);
|
let mut buffer = tiff::decoder::DecodingSampleBuffer::U8(vec![]);
|
||||||
let mut decoder = Decoder::open(&mut file).unwrap();
|
let mut decoder = Decoder::open(&mut file).unwrap();
|
||||||
decoder.next_image().unwrap();
|
decoder.next_image().unwrap();
|
||||||
decoder.read_image_to_buffer(&mut buffer).unwrap();
|
decoder.read_image_to_buffer(&mut buffer).unwrap();
|
||||||
if let DecodingResult::$buffer(img_res) = buffer {
|
if let DecodingSampleBuffer::$buffer(img_res) = buffer {
|
||||||
assert_eq!(*image_data, img_res);
|
assert_eq!(*image_data, img_res);
|
||||||
} else {
|
} else {
|
||||||
panic!("Wrong data type");
|
panic!("Wrong data type");
|
||||||
@@ -418,9 +418,9 @@ fn test_gray_f32_floating_point_predictor() {
|
|||||||
decoder.next_image().unwrap();
|
decoder.next_image().unwrap();
|
||||||
assert_eq!(decoder.colortype().unwrap(), ColorType::Gray(32));
|
assert_eq!(decoder.colortype().unwrap(), ColorType::Gray(32));
|
||||||
|
|
||||||
let mut buffer = DecodingResult::F32(vec![]);
|
let mut buffer = DecodingSampleBuffer::F32(vec![]);
|
||||||
decoder.read_image_to_buffer(&mut buffer).unwrap();
|
decoder.read_image_to_buffer(&mut buffer).unwrap();
|
||||||
if let DecodingResult::F32(img_res) = buffer {
|
if let DecodingSampleBuffer::F32(img_res) = buffer {
|
||||||
assert_eq!(image_data.len(), img_res.len());
|
assert_eq!(image_data.len(), img_res.len());
|
||||||
for (orig, decoded) in image_data.iter().zip(img_res.iter()) {
|
for (orig, decoded) in image_data.iter().zip(img_res.iter()) {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -465,9 +465,9 @@ fn test_rgb_f32_floating_point_predictor() {
|
|||||||
decoder.next_image().unwrap();
|
decoder.next_image().unwrap();
|
||||||
assert_eq!(decoder.colortype().unwrap(), ColorType::RGB(32));
|
assert_eq!(decoder.colortype().unwrap(), ColorType::RGB(32));
|
||||||
|
|
||||||
let mut buffer = DecodingResult::F32(vec![]);
|
let mut buffer = DecodingSampleBuffer::F32(vec![]);
|
||||||
decoder.read_image_to_buffer(&mut buffer).unwrap();
|
decoder.read_image_to_buffer(&mut buffer).unwrap();
|
||||||
if let DecodingResult::F32(img_res) = buffer {
|
if let DecodingSampleBuffer::F32(img_res) = buffer {
|
||||||
assert_eq!(image_data.len(), img_res.len());
|
assert_eq!(image_data.len(), img_res.len());
|
||||||
for (i, (orig, decoded)) in image_data.iter().zip(img_res.iter()).enumerate() {
|
for (i, (orig, decoded)) in image_data.iter().zip(img_res.iter()).enumerate() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -509,9 +509,9 @@ fn test_gray_f64_floating_point_predictor() {
|
|||||||
decoder.next_image().unwrap();
|
decoder.next_image().unwrap();
|
||||||
assert_eq!(decoder.colortype().unwrap(), ColorType::Gray(64));
|
assert_eq!(decoder.colortype().unwrap(), ColorType::Gray(64));
|
||||||
|
|
||||||
let mut buffer = DecodingResult::F64(vec![]);
|
let mut buffer = DecodingSampleBuffer::F64(vec![]);
|
||||||
decoder.read_image_to_buffer(&mut buffer).unwrap();
|
decoder.read_image_to_buffer(&mut buffer).unwrap();
|
||||||
if let DecodingResult::F64(img_res) = buffer {
|
if let DecodingSampleBuffer::F64(img_res) = buffer {
|
||||||
assert_eq!(image_data.len(), img_res.len());
|
assert_eq!(image_data.len(), img_res.len());
|
||||||
for (orig, decoded) in image_data.iter().zip(img_res.iter()) {
|
for (orig, decoded) in image_data.iter().zip(img_res.iter()) {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -782,7 +782,7 @@ fn test_rows_per_strip() {
|
|||||||
for i in 0..50 {
|
for i in 0..50 {
|
||||||
let img2 = [i; 2 * 100];
|
let img2 = [i; 2 * 100];
|
||||||
match decoder.read_chunk(i as u32).unwrap() {
|
match decoder.read_chunk(i as u32).unwrap() {
|
||||||
DecodingResult::U8(data) => assert_eq!(&img2[..], &data[..]),
|
DecodingSampleBuffer::U8(data) => assert_eq!(&img2[..], &data[..]),
|
||||||
other => panic!("Incorrect strip type {other:?}"),
|
other => panic!("Incorrect strip type {other:?}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ extern crate tiff;
|
|||||||
|
|
||||||
use std::io::{Cursor, Seek, Write};
|
use std::io::{Cursor, Seek, Write};
|
||||||
use tiff::{
|
use tiff::{
|
||||||
decoder::{Decoder, DecodingResult},
|
decoder::{Decoder, DecodingSampleBuffer},
|
||||||
encoder::{
|
encoder::{
|
||||||
colortype::{self, ColorType},
|
colortype::{self, ColorType},
|
||||||
Compression, TiffEncoder, TiffValue,
|
Compression, TiffEncoder, TiffValue,
|
||||||
@@ -115,7 +115,7 @@ fn encode_decode_with_compression(compression: Compression) {
|
|||||||
// Check the RGB image
|
// Check the RGB image
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
match decoder.read_image() {
|
match decoder.read_image() {
|
||||||
Ok(DecodingResult::U16(image_data)) => image_data,
|
Ok(DecodingSampleBuffer::U16(image_data)) => image_data,
|
||||||
unexpected => panic!("Descoding RGB failed: {unexpected:?}"),
|
unexpected => panic!("Descoding RGB failed: {unexpected:?}"),
|
||||||
},
|
},
|
||||||
image_rgb.reference_data()
|
image_rgb.reference_data()
|
||||||
@@ -125,7 +125,7 @@ fn encode_decode_with_compression(compression: Compression) {
|
|||||||
decoder.next_image().unwrap();
|
decoder.next_image().unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
match decoder.read_image() {
|
match decoder.read_image() {
|
||||||
Ok(DecodingResult::U8(image_data)) => image_data,
|
Ok(DecodingSampleBuffer::U8(image_data)) => image_data,
|
||||||
unexpected => panic!("Decoding grayscale failed: {unexpected:?}"),
|
unexpected => panic!("Decoding grayscale failed: {unexpected:?}"),
|
||||||
},
|
},
|
||||||
image_grayscale.reference_data()
|
image_grayscale.reference_data()
|
||||||
|
|||||||
+4
-4
@@ -1,6 +1,6 @@
|
|||||||
extern crate tiff;
|
extern crate tiff;
|
||||||
|
|
||||||
use tiff::decoder::{Decoder, DecodingResult};
|
use tiff::decoder::{Decoder, DecodingSampleBuffer};
|
||||||
use tiff::encoder::{colortype, Predictor, TiffEncoder};
|
use tiff::encoder::{colortype, Predictor, TiffEncoder};
|
||||||
use tiff::ColorType;
|
use tiff::ColorType;
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@ macro_rules! test_predict {
|
|||||||
decoder.next_image().unwrap();
|
decoder.next_image().unwrap();
|
||||||
assert_eq!(decoder.colortype().unwrap(), expected_type);
|
assert_eq!(decoder.colortype().unwrap(), expected_type);
|
||||||
let image_data = match decoder.read_image().unwrap() {
|
let image_data = match decoder.read_image().unwrap() {
|
||||||
DecodingResult::$buffer(res) => res,
|
DecodingSampleBuffer::$buffer(res) => res,
|
||||||
_ => panic!("Wrong data type"),
|
_ => panic!("Wrong data type"),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -130,7 +130,7 @@ macro_rules! test_predict_roundtrip {
|
|||||||
assert_eq!(decoder.colortype().unwrap(), expected_type);
|
assert_eq!(decoder.colortype().unwrap(), expected_type);
|
||||||
|
|
||||||
let image_data = match decoder.read_image().unwrap() {
|
let image_data = match decoder.read_image().unwrap() {
|
||||||
DecodingResult::$buffer(res) => res,
|
DecodingSampleBuffer::$buffer(res) => res,
|
||||||
_ => panic!("Wrong data type"),
|
_ => panic!("Wrong data type"),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -147,7 +147,7 @@ macro_rules! test_predict_roundtrip {
|
|||||||
{
|
{
|
||||||
let mut decoder = Decoder::open(&mut file).unwrap();
|
let mut decoder = Decoder::open(&mut file).unwrap();
|
||||||
decoder.next_image().unwrap();
|
decoder.next_image().unwrap();
|
||||||
if let DecodingResult::$buffer(img_res) =
|
if let DecodingSampleBuffer::$buffer(img_res) =
|
||||||
decoder.read_image().expect("Decoding image failed")
|
decoder.read_image().expect("Decoding image failed")
|
||||||
{
|
{
|
||||||
assert_eq!(image_data, img_res);
|
assert_eq!(image_data, img_res);
|
||||||
|
|||||||
Reference in new issue
Block a user