Coverage Report

Created: 2026-03-07 07:19

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/tiff-0.11.3/src/decoder/mod.rs
Line
Count
Source
1
use std::alloc::{Layout, LayoutError};
2
use std::collections::BTreeMap;
3
use std::io::{self, Read, Seek};
4
use std::num::NonZeroUsize;
5
6
use crate::tags::{
7
    CompressionMethod, IfdPointer, PhotometricInterpretation, PlanarConfiguration, Predictor,
8
    SampleFormat, Tag, Type, ValueBuffer,
9
};
10
use crate::{
11
    bytecast, ColorType, Directory, TiffError, TiffFormatError, TiffResult, TiffUnsupportedError,
12
    UsageError,
13
};
14
use half::f16;
15
16
use self::image::Image;
17
use self::stream::{ByteOrder, EndianReader};
18
19
mod cycles;
20
pub mod ifd;
21
mod image;
22
mod stream;
23
mod tag_reader;
24
25
/// An index referring to a (rectangular) region of an image.
26
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
27
pub struct TiffCodingUnit(pub u32);
28
29
/// Result of a decoding process
30
#[derive(Debug)]
31
pub enum DecodingResult {
32
    /// A vector of unsigned bytes
33
    U8(Vec<u8>),
34
    /// A vector of unsigned words
35
    U16(Vec<u16>),
36
    /// A vector of 32 bit unsigned ints
37
    U32(Vec<u32>),
38
    /// A vector of 64 bit unsigned ints
39
    U64(Vec<u64>),
40
    /// A vector of 16 bit IEEE floats (held in u16)
41
    F16(Vec<f16>),
42
    /// A vector of 32 bit IEEE floats
43
    F32(Vec<f32>),
44
    /// A vector of 64 bit IEEE floats
45
    F64(Vec<f64>),
46
    /// A vector of 8 bit signed ints
47
    I8(Vec<i8>),
48
    /// A vector of 16 bit signed ints
49
    I16(Vec<i16>),
50
    /// A vector of 32 bit signed ints
51
    I32(Vec<i32>),
52
    /// A vector of 64 bit signed ints
53
    I64(Vec<i64>),
54
}
55
56
impl DecodingResult {
57
    /// Reallocate the buffer to decode all planes of the indicated layout.
58
0
    pub fn resize_to(
59
0
        &mut self,
60
0
        buffer: &BufferLayoutPreference,
61
0
        limits: &Limits,
62
0
    ) -> Result<(), TiffError> {
63
0
        let sample_type = buffer.sample_type.ok_or(TiffError::UnsupportedError(
64
0
            TiffUnsupportedError::UnknownInterpretation,
65
0
        ))?;
66
67
0
        let extent = sample_type.extent_for_bytes(buffer.complete_len);
68
0
        self.resize_to_extent(extent, limits)
69
0
    }
70
71
13.7k
    fn resize_to_extent(
72
13.7k
        &mut self,
73
13.7k
        extent: DecodingExtent,
74
13.7k
        limits: &Limits,
75
13.7k
    ) -> Result<(), TiffError> {
76
        // FIXME: we *can* reuse the allocation sometimes.
77
13.7k
        *self = extent.to_result_buffer(limits)?;
78
13.7k
        Ok(())
79
13.7k
    }
80
81
13.7k
    fn new<T: Default + Copy>(
82
13.7k
        size: usize,
83
13.7k
        limits: &Limits,
84
13.7k
        from_fn: fn(Vec<T>) -> Self,
85
13.7k
    ) -> TiffResult<DecodingResult> {
86
13.7k
        if size > limits.decoding_buffer_size / core::mem::size_of::<T>() {
87
37
            Err(TiffError::LimitsExceeded)
88
        } else {
89
13.7k
            Ok(from_fn(vec![T::default(); size]))
90
        }
91
13.7k
    }
Unexecuted instantiation: <tiff::decoder::DecodingResult>::new::<half::binary16::f16>
Unexecuted instantiation: <tiff::decoder::DecodingResult>::new::<i8>
Unexecuted instantiation: <tiff::decoder::DecodingResult>::new::<f64>
<tiff::decoder::DecodingResult>::new::<f32>
Line
Count
Source
81
64
    fn new<T: Default + Copy>(
82
64
        size: usize,
83
64
        limits: &Limits,
84
64
        from_fn: fn(Vec<T>) -> Self,
85
64
    ) -> TiffResult<DecodingResult> {
86
64
        if size > limits.decoding_buffer_size / core::mem::size_of::<T>() {
87
0
            Err(TiffError::LimitsExceeded)
88
        } else {
89
64
            Ok(from_fn(vec![T::default(); size]))
90
        }
91
64
    }
<tiff::decoder::DecodingResult>::new::<u8>
Line
Count
Source
81
11.6k
    fn new<T: Default + Copy>(
82
11.6k
        size: usize,
83
11.6k
        limits: &Limits,
84
11.6k
        from_fn: fn(Vec<T>) -> Self,
85
11.6k
    ) -> TiffResult<DecodingResult> {
86
11.6k
        if size > limits.decoding_buffer_size / core::mem::size_of::<T>() {
87
18
            Err(TiffError::LimitsExceeded)
88
        } else {
89
11.5k
            Ok(from_fn(vec![T::default(); size]))
90
        }
91
11.6k
    }
Unexecuted instantiation: <tiff::decoder::DecodingResult>::new::<i32>
<tiff::decoder::DecodingResult>::new::<u32>
Line
Count
Source
81
18
    fn new<T: Default + Copy>(
82
18
        size: usize,
83
18
        limits: &Limits,
84
18
        from_fn: fn(Vec<T>) -> Self,
85
18
    ) -> TiffResult<DecodingResult> {
86
18
        if size > limits.decoding_buffer_size / core::mem::size_of::<T>() {
87
0
            Err(TiffError::LimitsExceeded)
88
        } else {
89
18
            Ok(from_fn(vec![T::default(); size]))
90
        }
91
18
    }
Unexecuted instantiation: <tiff::decoder::DecodingResult>::new::<i16>
<tiff::decoder::DecodingResult>::new::<u16>
Line
Count
Source
81
2.08k
    fn new<T: Default + Copy>(
82
2.08k
        size: usize,
83
2.08k
        limits: &Limits,
84
2.08k
        from_fn: fn(Vec<T>) -> Self,
85
2.08k
    ) -> TiffResult<DecodingResult> {
86
2.08k
        if size > limits.decoding_buffer_size / core::mem::size_of::<T>() {
87
19
            Err(TiffError::LimitsExceeded)
88
        } else {
89
2.07k
            Ok(from_fn(vec![T::default(); size]))
90
        }
91
2.08k
    }
Unexecuted instantiation: <tiff::decoder::DecodingResult>::new::<i64>
Unexecuted instantiation: <tiff::decoder::DecodingResult>::new::<u64>
92
93
11.6k
    fn new_u8(size: usize, limits: &Limits) -> TiffResult<DecodingResult> {
94
11.6k
        Self::new(size, limits, DecodingResult::U8)
95
11.6k
    }
96
97
2.08k
    fn new_u16(size: usize, limits: &Limits) -> TiffResult<DecodingResult> {
98
2.08k
        Self::new(size, limits, DecodingResult::U16)
99
2.08k
    }
100
101
18
    fn new_u32(size: usize, limits: &Limits) -> TiffResult<DecodingResult> {
102
18
        Self::new(size, limits, DecodingResult::U32)
103
18
    }
104
105
0
    fn new_u64(size: usize, limits: &Limits) -> TiffResult<DecodingResult> {
106
0
        Self::new(size, limits, DecodingResult::U64)
107
0
    }
108
109
64
    fn new_f32(size: usize, limits: &Limits) -> TiffResult<DecodingResult> {
110
64
        Self::new(size, limits, DecodingResult::F32)
111
64
    }
112
113
0
    fn new_f64(size: usize, limits: &Limits) -> TiffResult<DecodingResult> {
114
0
        Self::new(size, limits, DecodingResult::F64)
115
0
    }
116
117
0
    fn new_f16(size: usize, limits: &Limits) -> TiffResult<DecodingResult> {
118
0
        Self::new(size, limits, DecodingResult::F16)
119
0
    }
120
121
0
    fn new_i8(size: usize, limits: &Limits) -> TiffResult<DecodingResult> {
122
0
        Self::new(size, limits, DecodingResult::I8)
123
0
    }
124
125
0
    fn new_i16(size: usize, limits: &Limits) -> TiffResult<DecodingResult> {
126
0
        Self::new(size, limits, DecodingResult::I16)
127
0
    }
128
129
0
    fn new_i32(size: usize, limits: &Limits) -> TiffResult<DecodingResult> {
130
0
        Self::new(size, limits, DecodingResult::I32)
131
0
    }
132
133
0
    fn new_i64(size: usize, limits: &Limits) -> TiffResult<DecodingResult> {
134
0
        Self::new(size, limits, DecodingResult::I64)
135
0
    }
136
137
    /// Get a view of this buffer starting from the nth _sample_ of the current type.
138
17.5k
    pub fn as_buffer(&mut self, start: usize) -> DecodingBuffer<'_> {
139
17.5k
        match *self {
140
15.2k
            DecodingResult::U8(ref mut buf) => DecodingBuffer::U8(&mut buf[start..]),
141
2.12k
            DecodingResult::U16(ref mut buf) => DecodingBuffer::U16(&mut buf[start..]),
142
23
            DecodingResult::U32(ref mut buf) => DecodingBuffer::U32(&mut buf[start..]),
143
0
            DecodingResult::U64(ref mut buf) => DecodingBuffer::U64(&mut buf[start..]),
144
0
            DecodingResult::F16(ref mut buf) => DecodingBuffer::F16(&mut buf[start..]),
145
91
            DecodingResult::F32(ref mut buf) => DecodingBuffer::F32(&mut buf[start..]),
146
0
            DecodingResult::F64(ref mut buf) => DecodingBuffer::F64(&mut buf[start..]),
147
0
            DecodingResult::I8(ref mut buf) => DecodingBuffer::I8(&mut buf[start..]),
148
0
            DecodingResult::I16(ref mut buf) => DecodingBuffer::I16(&mut buf[start..]),
149
0
            DecodingResult::I32(ref mut buf) => DecodingBuffer::I32(&mut buf[start..]),
150
0
            DecodingResult::I64(ref mut buf) => DecodingBuffer::I64(&mut buf[start..]),
151
        }
152
17.5k
    }
153
}
154
155
// A buffer for image decoding
156
pub enum DecodingBuffer<'a> {
157
    /// A slice of unsigned bytes
158
    U8(&'a mut [u8]),
159
    /// A slice of unsigned words
160
    U16(&'a mut [u16]),
161
    /// A slice of 32 bit unsigned ints
162
    U32(&'a mut [u32]),
163
    /// A slice of 64 bit unsigned ints
164
    U64(&'a mut [u64]),
165
    /// A slice of 16 bit IEEE floats
166
    F16(&'a mut [f16]),
167
    /// A slice of 32 bit IEEE floats
168
    F32(&'a mut [f32]),
169
    /// A slice of 64 bit IEEE floats
170
    F64(&'a mut [f64]),
171
    /// A slice of 8 bits signed ints
172
    I8(&'a mut [i8]),
173
    /// A slice of 16 bits signed ints
174
    I16(&'a mut [i16]),
175
    /// A slice of 32 bits signed ints
176
    I32(&'a mut [i32]),
177
    /// A slice of 64 bits signed ints
178
    I64(&'a mut [i64]),
179
}
180
181
impl<'a> DecodingBuffer<'a> {
182
3.78k
    pub fn as_bytes(&self) -> &[u8] {
183
3.78k
        match self {
184
3.69k
            DecodingBuffer::U8(buf) => buf,
185
0
            DecodingBuffer::I8(buf) => bytecast::i8_as_ne_bytes(buf),
186
56
            DecodingBuffer::U16(buf) => bytecast::u16_as_ne_bytes(buf),
187
0
            DecodingBuffer::I16(buf) => bytecast::i16_as_ne_bytes(buf),
188
5
            DecodingBuffer::U32(buf) => bytecast::u32_as_ne_bytes(buf),
189
0
            DecodingBuffer::I32(buf) => bytecast::i32_as_ne_bytes(buf),
190
0
            DecodingBuffer::U64(buf) => bytecast::u64_as_ne_bytes(buf),
191
0
            DecodingBuffer::I64(buf) => bytecast::i64_as_ne_bytes(buf),
192
0
            DecodingBuffer::F16(buf) => bytecast::f16_as_ne_bytes(buf),
193
27
            DecodingBuffer::F32(buf) => bytecast::f32_as_ne_bytes(buf),
194
0
            DecodingBuffer::F64(buf) => bytecast::f64_as_ne_bytes(buf),
195
        }
196
3.78k
    }
197
198
13.7k
    pub fn as_bytes_mut(&mut self) -> &mut [u8] {
199
13.7k
        match self {
200
11.5k
            DecodingBuffer::U8(buf) => buf,
201
0
            DecodingBuffer::I8(buf) => bytecast::i8_as_ne_mut_bytes(buf),
202
2.07k
            DecodingBuffer::U16(buf) => bytecast::u16_as_ne_mut_bytes(buf),
203
0
            DecodingBuffer::I16(buf) => bytecast::i16_as_ne_mut_bytes(buf),
204
18
            DecodingBuffer::U32(buf) => bytecast::u32_as_ne_mut_bytes(buf),
205
0
            DecodingBuffer::I32(buf) => bytecast::i32_as_ne_mut_bytes(buf),
206
0
            DecodingBuffer::U64(buf) => bytecast::u64_as_ne_mut_bytes(buf),
207
0
            DecodingBuffer::I64(buf) => bytecast::i64_as_ne_mut_bytes(buf),
208
0
            DecodingBuffer::F16(buf) => bytecast::f16_as_ne_mut_bytes(buf),
209
64
            DecodingBuffer::F32(buf) => bytecast::f32_as_ne_mut_bytes(buf),
210
0
            DecodingBuffer::F64(buf) => bytecast::f64_as_ne_mut_bytes(buf),
211
        }
212
13.7k
    }
213
214
0
    pub fn byte_len(&self) -> usize {
215
0
        self.as_bytes().len()
216
0
    }
217
}
218
219
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
220
pub enum DecodingSampleType {
221
    U8,
222
    U16,
223
    U32,
224
    U64,
225
    F16,
226
    F32,
227
    F64,
228
    I8,
229
    I16,
230
    I32,
231
    I64,
232
}
233
234
impl DecodingSampleType {
235
13.7k
    fn extent_for_bytes(self, bytes: usize) -> DecodingExtent {
236
13.7k
        match self {
237
11.6k
            DecodingSampleType::U8 => DecodingExtent::U8(bytes),
238
2.08k
            DecodingSampleType::U16 => DecodingExtent::U16(bytes.div_ceil(2)),
239
18
            DecodingSampleType::U32 => DecodingExtent::U32(bytes.div_ceil(4)),
240
0
            DecodingSampleType::U64 => DecodingExtent::U64(bytes.div_ceil(8)),
241
0
            DecodingSampleType::I8 => DecodingExtent::I8(bytes),
242
0
            DecodingSampleType::I16 => DecodingExtent::I16(bytes.div_ceil(2)),
243
0
            DecodingSampleType::I32 => DecodingExtent::I32(bytes.div_ceil(4)),
244
0
            DecodingSampleType::I64 => DecodingExtent::I64(bytes.div_ceil(8)),
245
0
            DecodingSampleType::F16 => DecodingExtent::F16(bytes.div_ceil(2)),
246
64
            DecodingSampleType::F32 => DecodingExtent::F32(bytes.div_ceil(4)),
247
0
            DecodingSampleType::F64 => DecodingExtent::F64(bytes.div_ceil(8)),
248
        }
249
13.7k
    }
250
}
251
252
/// Information on the byte buffer that should be supplied to the decoder.
253
///
254
/// This is relevant for [`Decoder::read_image_bytes`] and [`Decoder::read_chunk_bytes`] where the
255
/// caller provided buffer must fit the expectations of the decoder to be filled with data from the
256
/// current image.
257
#[non_exhaustive]
258
#[derive(Debug, Clone)]
259
pub struct BufferLayoutPreference {
260
    /// Minimum byte size of the buffer to read image data.
261
    pub len: usize,
262
    /// The interpretation of each sample in the image.
263
    ///
264
    /// We only support a uniform sample layout. Detailed information for mixed colors may be added
265
    /// in the future and will become available by explicit query. The same goes for the bit-depth
266
    /// of samples that must also be uniform.
267
    pub sample_format: SampleFormat,
268
    /// The type representation for each sample. Only available for depths and formats which the
269
    /// library can describe.
270
    pub sample_type: Option<DecodingSampleType>,
271
    /// Minimum number of bytes to represent a row of image data of the requested content.
272
    pub row_stride: Option<NonZeroUsize>,
273
    /// Number of planes in the image.
274
    pub planes: usize,
275
    /// Number of bytes used to represent one plane.
276
    pub plane_stride: Option<NonZeroUsize>,
277
    /// Number of bytes of data when reading all planes.
278
    pub complete_len: usize,
279
}
280
281
impl BufferLayoutPreference {
282
13.7k
    fn from_planes(layout: &image::PlaneLayout) -> Self {
283
13.7k
        BufferLayoutPreference {
284
13.7k
            len: layout.readout.plane_stride,
285
13.7k
            row_stride: core::num::NonZeroUsize::new(layout.readout.row_stride),
286
13.7k
            planes: layout.plane_offsets.len(),
287
13.7k
            plane_stride: core::num::NonZeroUsize::new(layout.readout.plane_stride),
288
13.7k
            complete_len: layout.total_bytes,
289
13.7k
            sample_format: layout.readout.sample_format,
290
13.7k
            sample_type: Self::sample_type(layout.readout.sample_format, layout.readout.color),
291
13.7k
        }
292
13.7k
    }
293
294
27.5k
    fn sample_type(sample_format: SampleFormat, color: ColorType) -> Option<DecodingSampleType> {
295
27.5k
        Some(match sample_format {
296
27.4k
            SampleFormat::Uint => match color.bit_depth() {
297
27.4k
                n if n <= 8 => DecodingSampleType::U8,
298
4.21k
                n if n <= 16 => DecodingSampleType::U16,
299
36
                n if n <= 32 => DecodingSampleType::U32,
300
0
                n if n <= 64 => DecodingSampleType::U64,
301
0
                _ => return None,
302
            },
303
128
            SampleFormat::IEEEFP => match color.bit_depth() {
304
0
                16 => DecodingSampleType::F16,
305
128
                32 => DecodingSampleType::F32,
306
0
                64 => DecodingSampleType::F64,
307
0
                _ => return None,
308
            },
309
0
            SampleFormat::Int => match color.bit_depth() {
310
0
                n if n <= 8 => DecodingSampleType::I8,
311
0
                n if n <= 16 => DecodingSampleType::I16,
312
0
                n if n <= 32 => DecodingSampleType::I32,
313
0
                n if n <= 64 => DecodingSampleType::I64,
314
0
                _ => return None,
315
            },
316
0
            _other => {
317
0
                return None;
318
            }
319
        })
320
27.5k
    }
321
}
322
323
impl image::ReadoutLayout {
324
    // FIXME: when planes are not homogenous (i.e. subsampled or differing depths) then the
325
    // `readout_for_size` or `to_plane_layout` needs a parameter to determine the planes being
326
    // read instead of assuming a constant repeated size for them.
327
13.7k
    fn result_extent_for_planes(
328
13.7k
        self: &image::ReadoutLayout,
329
13.7k
        planes: core::ops::Range<u16>,
330
13.7k
    ) -> TiffResult<DecodingExtent> {
331
13.7k
        let buffer = self.to_plane_layout()?;
332
333
        // The layout is for all planes. So restrict ourselves to the planes that were requested.
334
13.7k
        let offset = match buffer.plane_offsets.get(usize::from(planes.start)) {
335
13.7k
            Some(n) => *n,
336
            None => {
337
0
                return Err(TiffError::UsageError(UsageError::InvalidPlaneIndex(
338
0
                    planes.start,
339
0
                )))
340
            }
341
        };
342
343
13.7k
        let end = match buffer.plane_offsets.get(usize::from(planes.end)) {
344
0
            Some(n) => *n,
345
13.7k
            None => buffer.total_bytes,
346
        };
347
348
13.7k
        let buffer_bytes = end - offset;
349
13.7k
        let bits_per_sample = self.color.bit_depth();
350
351
13.7k
        let Some(sample_type) = BufferLayoutPreference::sample_type(self.sample_format, self.color)
352
        else {
353
0
            if matches!(
354
0
                self.sample_format,
355
                SampleFormat::Uint | SampleFormat::Int | SampleFormat::IEEEFP
356
            ) {
357
0
                return Err(TiffError::UnsupportedError(
358
0
                    TiffUnsupportedError::UnsupportedSampleDepth(bits_per_sample),
359
0
                ));
360
            } else {
361
0
                return Err(TiffError::UnsupportedError(
362
0
                    TiffUnsupportedError::UnsupportedSampleFormat(vec![self.sample_format]),
363
0
                ));
364
            }
365
        };
366
367
13.7k
        Ok(sample_type.extent_for_bytes(buffer_bytes))
368
13.7k
    }
369
370
    #[inline(always)]
371
13.7k
    fn assert_min_layout<T>(&self, buffer: &[T]) -> TiffResult<()> {
372
13.7k
        if core::mem::size_of_val(buffer) < self.plane_stride {
373
0
            Err(TiffError::UsageError(
374
0
                UsageError::InsufficientOutputBufferSize {
375
0
                    needed: self.plane_stride,
376
0
                    provided: buffer.len(),
377
0
                },
378
0
            ))
379
        } else {
380
13.7k
            Ok(())
381
        }
382
13.7k
    }
<tiff::decoder::image::ReadoutLayout>::assert_min_layout::<u8>
Line
Count
Source
371
13.7k
    fn assert_min_layout<T>(&self, buffer: &[T]) -> TiffResult<()> {
372
13.7k
        if core::mem::size_of_val(buffer) < self.plane_stride {
373
0
            Err(TiffError::UsageError(
374
0
                UsageError::InsufficientOutputBufferSize {
375
0
                    needed: self.plane_stride,
376
0
                    provided: buffer.len(),
377
0
                },
378
0
            ))
379
        } else {
380
13.7k
            Ok(())
381
        }
382
13.7k
    }
Unexecuted instantiation: <tiff::decoder::image::ReadoutLayout>::assert_min_layout::<_>
383
}
384
385
/// The count and matching discriminant for a `DecodingBuffer`.
386
#[derive(Clone)]
387
enum DecodingExtent {
388
    U8(usize),
389
    U16(usize),
390
    U32(usize),
391
    U64(usize),
392
    F16(usize),
393
    F32(usize),
394
    F64(usize),
395
    I8(usize),
396
    I16(usize),
397
    I32(usize),
398
    I64(usize),
399
}
400
401
impl DecodingExtent {
402
13.7k
    fn to_result_buffer(&self, limits: &Limits) -> TiffResult<DecodingResult> {
403
13.7k
        match *self {
404
11.6k
            DecodingExtent::U8(count) => DecodingResult::new_u8(count, limits),
405
2.08k
            DecodingExtent::U16(count) => DecodingResult::new_u16(count, limits),
406
18
            DecodingExtent::U32(count) => DecodingResult::new_u32(count, limits),
407
0
            DecodingExtent::U64(count) => DecodingResult::new_u64(count, limits),
408
0
            DecodingExtent::F16(count) => DecodingResult::new_f16(count, limits),
409
64
            DecodingExtent::F32(count) => DecodingResult::new_f32(count, limits),
410
0
            DecodingExtent::F64(count) => DecodingResult::new_f64(count, limits),
411
0
            DecodingExtent::I8(count) => DecodingResult::new_i8(count, limits),
412
0
            DecodingExtent::I16(count) => DecodingResult::new_i16(count, limits),
413
0
            DecodingExtent::I32(count) => DecodingResult::new_i32(count, limits),
414
0
            DecodingExtent::I64(count) => DecodingResult::new_i64(count, limits),
415
        }
416
13.7k
    }
417
418
0
    fn preferred_layout(self) -> TiffResult<Layout> {
419
0
        fn overflow(_: LayoutError) -> TiffError {
420
0
            TiffError::LimitsExceeded
421
0
        }
422
423
0
        match self {
424
0
            DecodingExtent::U8(count) => Layout::array::<u8>(count),
425
0
            DecodingExtent::U16(count) => Layout::array::<u16>(count),
426
0
            DecodingExtent::U32(count) => Layout::array::<u32>(count),
427
0
            DecodingExtent::U64(count) => Layout::array::<u64>(count),
428
0
            DecodingExtent::F16(count) => Layout::array::<f16>(count),
429
0
            DecodingExtent::F32(count) => Layout::array::<f32>(count),
430
0
            DecodingExtent::F64(count) => Layout::array::<f64>(count),
431
0
            DecodingExtent::I8(count) => Layout::array::<i8>(count),
432
0
            DecodingExtent::I16(count) => Layout::array::<i16>(count),
433
0
            DecodingExtent::I32(count) => Layout::array::<i32>(count),
434
0
            DecodingExtent::I64(count) => Layout::array::<i64>(count),
435
        }
436
0
        .map_err(overflow)
437
0
    }
438
439
0
    fn sample_type(&self) -> DecodingSampleType {
440
0
        match *self {
441
0
            DecodingExtent::U8(_) => DecodingSampleType::U8,
442
0
            DecodingExtent::U16(_) => DecodingSampleType::U16,
443
0
            DecodingExtent::U32(_) => DecodingSampleType::U32,
444
0
            DecodingExtent::U64(_) => DecodingSampleType::U64,
445
0
            DecodingExtent::F16(_) => DecodingSampleType::F16,
446
0
            DecodingExtent::F32(_) => DecodingSampleType::F32,
447
0
            DecodingExtent::F64(_) => DecodingSampleType::F64,
448
0
            DecodingExtent::I8(_) => DecodingSampleType::I8,
449
0
            DecodingExtent::I16(_) => DecodingSampleType::I16,
450
0
            DecodingExtent::I32(_) => DecodingSampleType::I32,
451
0
            DecodingExtent::I64(_) => DecodingSampleType::I64,
452
        }
453
0
    }
454
}
455
456
#[derive(Debug, Copy, Clone, PartialEq)]
457
/// Chunk type of the internal representation
458
pub enum ChunkType {
459
    Strip,
460
    Tile,
461
}
462
463
/// Decoding limits
464
#[derive(Clone, Debug)]
465
#[non_exhaustive]
466
pub struct Limits {
467
    /// The maximum size of any `DecodingResult` in bytes, the default is
468
    /// 256MiB. If the entire image is decoded at once, then this will
469
    /// be the maximum size of the image. If it is decoded one strip at a
470
    /// time, this will be the maximum size of a strip.
471
    pub decoding_buffer_size: usize,
472
    /// The maximum size of any ifd value in bytes, the default is
473
    /// 1MiB.
474
    pub ifd_value_size: usize,
475
    /// Maximum size for intermediate buffer which may be used to limit the amount of data read per
476
    /// segment even if the entire image is decoded at once.
477
    pub intermediate_buffer_size: usize,
478
}
479
480
impl Limits {
481
    /// A configuration that does not impose any limits.
482
    ///
483
    /// This is a good start if the caller only wants to impose selective limits, contrary to the
484
    /// default limits which allows selectively disabling limits.
485
    ///
486
    /// Note that this configuration is likely to crash on excessively large images since,
487
    /// naturally, the machine running the program does not have infinite memory.
488
0
    pub fn unlimited() -> Limits {
489
0
        Limits {
490
0
            decoding_buffer_size: usize::MAX,
491
0
            ifd_value_size: usize::MAX,
492
0
            intermediate_buffer_size: usize::MAX,
493
0
        }
494
0
    }
495
}
496
497
impl Default for Limits {
498
33.5k
    fn default() -> Limits {
499
33.5k
        Limits {
500
33.5k
            decoding_buffer_size: 256 * 1024 * 1024,
501
33.5k
            intermediate_buffer_size: 128 * 1024 * 1024,
502
33.5k
            ifd_value_size: 1024 * 1024,
503
33.5k
        }
504
33.5k
    }
505
}
506
507
/// The representation of a TIFF decoder
508
///
509
/// Currently does not support decoding of interlaced images
510
#[derive(Debug)]
511
pub struct Decoder<R>
512
where
513
    R: Read + Seek,
514
{
515
    /// There are grouped for borrow checker reasons. This allows us to implement methods that
516
    /// borrow the stream access and the other fields mutably at the same time.
517
    value_reader: ValueReader<R>,
518
    current_ifd: Option<IfdPointer>,
519
    next_ifd: Option<IfdPointer>,
520
    /// The IFDs we visited already in this chain of IFDs.
521
    ifd_offsets: Vec<IfdPointer>,
522
    /// Map from the ifd into the `ifd_offsets` ordered list.
523
    seen_ifds: cycles::IfdCycles,
524
    image: Image,
525
}
526
527
/// All the information needed to read and interpret byte slices from the underlying file, i.e. to
528
/// turn an entry of a tag into an `ifd::Value` or otherwise fetch arrays of similar types. Used
529
/// only as the type of the field [`Decoder::value_reader`] and passed to submodules.
530
#[derive(Debug)]
531
struct ValueReader<R> {
532
    reader: EndianReader<R>,
533
    bigtiff: bool,
534
    limits: Limits,
535
}
536
537
/// Reads a directory's tag values from an underlying stream.
538
pub struct IfdDecoder<'lt> {
539
    inner: tag_reader::TagReader<'lt, dyn tag_reader::EntryDecoder + 'lt>,
540
}
541
542
43.7k
fn rev_hpredict_nsamp(buf: &mut [u8], bit_depth: u8, samples: u16) {
543
41.2k
    fn one_byte_predict<const N: usize>(buf: &mut [u8]) {
544
25.8M
        for i in N..buf.len() {
545
25.8M
            buf[i] = buf[i].wrapping_add(buf[i - N]);
546
25.8M
        }
547
41.2k
    }
tiff::decoder::rev_hpredict_nsamp::one_byte_predict::<1>
Line
Count
Source
543
36.8k
    fn one_byte_predict<const N: usize>(buf: &mut [u8]) {
544
19.0M
        for i in N..buf.len() {
545
19.0M
            buf[i] = buf[i].wrapping_add(buf[i - N]);
546
19.0M
        }
547
36.8k
    }
Unexecuted instantiation: tiff::decoder::rev_hpredict_nsamp::one_byte_predict::<2>
tiff::decoder::rev_hpredict_nsamp::one_byte_predict::<3>
Line
Count
Source
543
3.11k
    fn one_byte_predict<const N: usize>(buf: &mut [u8]) {
544
4.86M
        for i in N..buf.len() {
545
4.86M
            buf[i] = buf[i].wrapping_add(buf[i - N]);
546
4.86M
        }
547
3.11k
    }
tiff::decoder::rev_hpredict_nsamp::one_byte_predict::<4>
Line
Count
Source
543
1.29k
    fn one_byte_predict<const N: usize>(buf: &mut [u8]) {
544
1.92M
        for i in N..buf.len() {
545
1.92M
            buf[i] = buf[i].wrapping_add(buf[i - N]);
546
1.92M
        }
547
1.29k
    }
548
549
2.02k
    fn two_bytes_predict<const N: usize>(buf: &mut [u8]) {
550
251k
        for i in (2 * N..buf.len()).step_by(2) {
551
251k
            let v = u16::from_ne_bytes(buf[i..][..2].try_into().unwrap());
552
251k
            let p = u16::from_ne_bytes(buf[i - 2 * N..][..2].try_into().unwrap());
553
251k
            buf[i..][..2].copy_from_slice(&(v.wrapping_add(p)).to_ne_bytes());
554
251k
        }
555
2.02k
    }
tiff::decoder::rev_hpredict_nsamp::two_bytes_predict::<1>
Line
Count
Source
549
1.50k
    fn two_bytes_predict<const N: usize>(buf: &mut [u8]) {
550
151k
        for i in (2 * N..buf.len()).step_by(2) {
551
151k
            let v = u16::from_ne_bytes(buf[i..][..2].try_into().unwrap());
552
151k
            let p = u16::from_ne_bytes(buf[i - 2 * N..][..2].try_into().unwrap());
553
151k
            buf[i..][..2].copy_from_slice(&(v.wrapping_add(p)).to_ne_bytes());
554
151k
        }
555
1.50k
    }
Unexecuted instantiation: tiff::decoder::rev_hpredict_nsamp::two_bytes_predict::<2>
tiff::decoder::rev_hpredict_nsamp::two_bytes_predict::<3>
Line
Count
Source
549
526
    fn two_bytes_predict<const N: usize>(buf: &mut [u8]) {
550
99.9k
        for i in (2 * N..buf.len()).step_by(2) {
551
99.9k
            let v = u16::from_ne_bytes(buf[i..][..2].try_into().unwrap());
552
99.9k
            let p = u16::from_ne_bytes(buf[i - 2 * N..][..2].try_into().unwrap());
553
99.9k
            buf[i..][..2].copy_from_slice(&(v.wrapping_add(p)).to_ne_bytes());
554
99.9k
        }
555
526
    }
Unexecuted instantiation: tiff::decoder::rev_hpredict_nsamp::two_bytes_predict::<4>
556
557
180
    fn four_bytes_predict<const N: usize>(buf: &mut [u8]) {
558
252k
        for i in (N * 4..buf.len()).step_by(4) {
559
252k
            let v = u32::from_ne_bytes(buf[i..][..4].try_into().unwrap());
560
252k
            let p = u32::from_ne_bytes(buf[i - 4 * N..][..4].try_into().unwrap());
561
252k
            buf[i..][..4].copy_from_slice(&(v.wrapping_add(p)).to_ne_bytes());
562
252k
        }
563
180
    }
Unexecuted instantiation: tiff::decoder::rev_hpredict_nsamp::four_bytes_predict::<1>
Unexecuted instantiation: tiff::decoder::rev_hpredict_nsamp::four_bytes_predict::<2>
tiff::decoder::rev_hpredict_nsamp::four_bytes_predict::<3>
Line
Count
Source
557
164
    fn four_bytes_predict<const N: usize>(buf: &mut [u8]) {
558
252k
        for i in (N * 4..buf.len()).step_by(4) {
559
252k
            let v = u32::from_ne_bytes(buf[i..][..4].try_into().unwrap());
560
252k
            let p = u32::from_ne_bytes(buf[i - 4 * N..][..4].try_into().unwrap());
561
252k
            buf[i..][..4].copy_from_slice(&(v.wrapping_add(p)).to_ne_bytes());
562
252k
        }
563
164
    }
tiff::decoder::rev_hpredict_nsamp::four_bytes_predict::<4>
Line
Count
Source
557
16
    fn four_bytes_predict<const N: usize>(buf: &mut [u8]) {
558
320
        for i in (N * 4..buf.len()).step_by(4) {
559
320
            let v = u32::from_ne_bytes(buf[i..][..4].try_into().unwrap());
560
320
            let p = u32::from_ne_bytes(buf[i - 4 * N..][..4].try_into().unwrap());
561
320
            buf[i..][..4].copy_from_slice(&(v.wrapping_add(p)).to_ne_bytes());
562
320
        }
563
16
    }
564
565
43.7k
    let samples = usize::from(samples);
566
567
43.7k
    match (bit_depth, samples) {
568
        // Note we can't use `windows` or so due to the overlap between each iteration. We split
569
        // the cases by the samples / lookback constant so that each is optimized individually.
570
        // This is more code generated but each loop can then have a different vectorization
571
        // strategy.
572
43.7k
        (0..=8, 1) => one_byte_predict::<1>(buf),
573
0
        (0..=8, 2) => one_byte_predict::<2>(buf),
574
3.11k
        (0..=8, 3) => one_byte_predict::<3>(buf),
575
1.29k
        (0..=8, 4) => one_byte_predict::<4>(buf),
576
        // The generic, sub-optimal case for the above.
577
        (0..=8, _) => {
578
24.2k
            for i in samples..buf.len() {
579
24.2k
                buf[i] = buf[i].wrapping_add(buf[i - samples]);
580
24.2k
            }
581
        }
582
2.20k
        (9..=16, 1) => {
583
1.50k
            two_bytes_predict::<1>(buf);
584
1.50k
        }
585
0
        (9..=16, 2) => {
586
0
            two_bytes_predict::<2>(buf);
587
0
        }
588
526
        (9..=16, 3) => {
589
526
            two_bytes_predict::<3>(buf);
590
526
        }
591
0
        (9..=16, 4) => {
592
0
            two_bytes_predict::<4>(buf);
593
0
        }
594
        (9..=16, _) => {
595
0
            for i in (samples * 2..buf.len()).step_by(2) {
596
0
                let v = u16::from_ne_bytes(buf[i..][..2].try_into().unwrap());
597
0
                let p = u16::from_ne_bytes(buf[i - 2 * samples..][..2].try_into().unwrap());
598
0
                buf[i..][..2].copy_from_slice(&(v.wrapping_add(p)).to_ne_bytes());
599
0
            }
600
        }
601
180
        (17..=32, 1) => {
602
0
            four_bytes_predict::<1>(buf);
603
0
        }
604
0
        (17..=32, 2) => {
605
0
            four_bytes_predict::<2>(buf);
606
0
        }
607
164
        (17..=32, 3) => {
608
164
            four_bytes_predict::<3>(buf);
609
164
        }
610
16
        (17..=32, 4) => {
611
16
            four_bytes_predict::<4>(buf);
612
16
        }
613
        (17..=32, _) => {
614
0
            for i in (samples * 4..buf.len()).step_by(4) {
615
0
                let v = u32::from_ne_bytes(buf[i..][..4].try_into().unwrap());
616
0
                let p = u32::from_ne_bytes(buf[i - 4 * samples..][..4].try_into().unwrap());
617
0
                buf[i..][..4].copy_from_slice(&(v.wrapping_add(p)).to_ne_bytes());
618
0
            }
619
        }
620
0
        (33..=64, _) => {
621
0
            for i in (samples * 8..buf.len()).step_by(8) {
622
0
                let v = u64::from_ne_bytes(buf[i..][..8].try_into().unwrap());
623
0
                let p = u64::from_ne_bytes(buf[i - 8 * samples..][..8].try_into().unwrap());
624
0
                buf[i..][..8].copy_from_slice(&(v.wrapping_add(p)).to_ne_bytes());
625
0
            }
626
        }
627
        _ => {
628
0
            unreachable!("Caller should have validated arguments. Please file a bug.")
629
        }
630
    }
631
43.7k
}
632
633
1.26k
fn predict_f32(input: &mut [u8], output: &mut [u8], samples: u16) {
634
1.26k
    let samples = usize::from(samples);
635
636
3.83M
    for i in samples..input.len() {
637
3.83M
        input[i] = input[i].wrapping_add(input[i - samples]);
638
3.83M
    }
639
640
960k
    for (i, chunk) in output.chunks_mut(4).enumerate() {
641
960k
        chunk.copy_from_slice(&u32::to_ne_bytes(u32::from_be_bytes([
642
960k
            input[i],
643
960k
            input[input.len() / 4 + i],
644
960k
            input[input.len() / 4 * 2 + i],
645
960k
            input[input.len() / 4 * 3 + i],
646
960k
        ])));
647
960k
    }
648
1.26k
}
649
650
0
fn predict_f16(input: &mut [u8], output: &mut [u8], samples: u16) {
651
0
    let samples = usize::from(samples);
652
653
0
    for i in samples..input.len() {
654
0
        input[i] = input[i].wrapping_add(input[i - samples]);
655
0
    }
656
657
0
    for (i, chunk) in output.chunks_mut(2).enumerate() {
658
0
        chunk.copy_from_slice(&u16::to_ne_bytes(u16::from_be_bytes([
659
0
            input[i],
660
0
            input[input.len() / 2 + i],
661
0
        ])));
662
0
    }
663
0
}
664
665
0
fn predict_f64(input: &mut [u8], output: &mut [u8], samples: u16) {
666
0
    let samples = usize::from(samples);
667
668
0
    for i in samples..input.len() {
669
0
        input[i] = input[i].wrapping_add(input[i - samples]);
670
0
    }
671
672
0
    for (i, chunk) in output.chunks_mut(8).enumerate() {
673
0
        chunk.copy_from_slice(&u64::to_ne_bytes(u64::from_be_bytes([
674
0
            input[i],
675
0
            input[input.len() / 8 + i],
676
0
            input[input.len() / 8 * 2 + i],
677
0
            input[input.len() / 8 * 3 + i],
678
0
            input[input.len() / 8 * 4 + i],
679
0
            input[input.len() / 8 * 5 + i],
680
0
            input[input.len() / 8 * 6 + i],
681
0
            input[input.len() / 8 * 7 + i],
682
0
        ])));
683
0
    }
684
0
}
685
686
7.36M
fn fix_endianness_and_predict(
687
7.36M
    buf: &mut [u8],
688
7.36M
    bit_depth: u8,
689
7.36M
    samples: u16,
690
7.36M
    byte_order: ByteOrder,
691
7.36M
    predictor: Predictor,
692
7.36M
) {
693
7.36M
    match predictor {
694
7.31M
        Predictor::None => {
695
7.31M
            fix_endianness(buf, byte_order, bit_depth);
696
7.31M
        }
697
43.7k
        Predictor::Horizontal => {
698
43.7k
            fix_endianness(buf, byte_order, bit_depth);
699
43.7k
            rev_hpredict_nsamp(buf, bit_depth, samples);
700
43.7k
        }
701
        Predictor::FloatingPoint => {
702
1.24k
            let mut buffer_copy = buf.to_vec();
703
1.24k
            match bit_depth {
704
0
                16 => predict_f16(&mut buffer_copy, buf, samples),
705
1.24k
                32 => predict_f32(&mut buffer_copy, buf, samples),
706
0
                64 => predict_f64(&mut buffer_copy, buf, samples),
707
0
                _ => unreachable!("Caller should have validated arguments. Please file a bug."),
708
            }
709
        }
710
    }
711
7.36M
}
712
713
49.1k
fn invert_colors(
714
49.1k
    buf: &mut [u8],
715
49.1k
    color_type: ColorType,
716
49.1k
    sample_format: SampleFormat,
717
49.1k
) -> TiffResult<()> {
718
49.1k
    match (color_type, sample_format) {
719
        // Where pixels do not cross a byte boundary
720
        (ColorType::Gray(1 | 2 | 4 | 8), SampleFormat::Uint) => {
721
55.6M
            for x in buf {
722
55.5M
                // Equivalent to both of the following:
723
55.5M
                //
724
55.5M
                // *x = 0xff - *x
725
55.5M
                // *x = !*x
726
55.5M
                //
727
55.5M
                // since -x = !x+1
728
55.5M
                *x = !*x;
729
55.5M
            }
730
        }
731
        (ColorType::Gray(16), SampleFormat::Uint) => {
732
598k
            for x in buf.chunks_mut(2) {
733
598k
                let v = u16::from_ne_bytes(x.try_into().unwrap());
734
598k
                x.copy_from_slice(&(0xffff - v).to_ne_bytes());
735
598k
            }
736
        }
737
        (ColorType::Gray(32), SampleFormat::Uint) => {
738
0
            for x in buf.chunks_mut(4) {
739
0
                let v = u32::from_ne_bytes(x.try_into().unwrap());
740
0
                x.copy_from_slice(&(0xffff_ffff - v).to_ne_bytes());
741
0
            }
742
        }
743
        (ColorType::Gray(64), SampleFormat::Uint) => {
744
0
            for x in buf.chunks_mut(8) {
745
0
                let v = u64::from_ne_bytes(x.try_into().unwrap());
746
0
                x.copy_from_slice(&(0xffff_ffff_ffff_ffff - v).to_ne_bytes());
747
0
            }
748
        }
749
        (ColorType::Gray(32), SampleFormat::IEEEFP) => {
750
0
            for x in buf.chunks_mut(4) {
751
0
                let v = f32::from_ne_bytes(x.try_into().unwrap());
752
0
                x.copy_from_slice(&(1.0 - v).to_ne_bytes());
753
0
            }
754
        }
755
        (ColorType::Gray(64), SampleFormat::IEEEFP) => {
756
0
            for x in buf.chunks_mut(8) {
757
0
                let v = f64::from_ne_bytes(x.try_into().unwrap());
758
0
                x.copy_from_slice(&(1.0 - v).to_ne_bytes());
759
0
            }
760
        }
761
        _ => {
762
0
            return Err(TiffError::UnsupportedError(
763
0
                TiffUnsupportedError::UnknownInterpretation,
764
0
            ))
765
        }
766
    }
767
768
49.1k
    Ok(())
769
49.1k
}
770
771
/// Fix endianness. If `byte_order` matches the host, then conversion is a no-op.
772
7.36M
fn fix_endianness(buf: &mut [u8], byte_order: ByteOrder, bit_depth: u8) {
773
7.36M
    let host = ByteOrder::native();
774
775
7.36M
    let class = match bit_depth {
776
7.36M
        0..=8 => crate::tags::EndianBytes::One,
777
30.4k
        9..=16 => crate::tags::EndianBytes::Two,
778
773
        17..=32 => crate::tags::EndianBytes::Four,
779
0
        _ => crate::tags::EndianBytes::Eight,
780
    };
781
782
7.36M
    host.convert_endian_bytes(class, buf, byte_order);
783
7.36M
}
784
785
impl<R: Read + Seek> Decoder<R> {
786
19.8k
    pub fn new(mut r: R) -> TiffResult<Decoder<R>> {
787
19.8k
        let mut endianess = Vec::with_capacity(2);
788
19.8k
        (&mut r).take(2).read_to_end(&mut endianess)?;
789
19.8k
        let byte_order = match &*endianess {
790
19.8k
            b"II" => ByteOrder::LittleEndian,
791
1.42k
            b"MM" => ByteOrder::BigEndian,
792
            _ => {
793
20
                return Err(TiffError::FormatError(
794
20
                    TiffFormatError::TiffSignatureNotFound,
795
20
                ))
796
            }
797
        };
798
19.8k
        let mut reader = EndianReader::new(r, byte_order);
799
800
19.8k
        let bigtiff = match reader.read_u16()? {
801
19.3k
            42 => false,
802
            43 => {
803
                // Read bytesize of offsets (in bigtiff it's alway 8 but provide a way to move to 16 some day)
804
518
                if reader.read_u16()? != 8 {
805
16
                    return Err(TiffError::FormatError(
806
16
                        TiffFormatError::TiffSignatureNotFound,
807
16
                    ));
808
499
                }
809
                // This constant should always be 0
810
499
                if reader.read_u16()? != 0 {
811
16
                    return Err(TiffError::FormatError(
812
16
                        TiffFormatError::TiffSignatureNotFound,
813
16
                    ));
814
481
                }
815
481
                true
816
            }
817
            _ => {
818
1
                return Err(TiffError::FormatError(
819
1
                    TiffFormatError::TiffSignatureInvalid,
820
1
                ))
821
            }
822
        };
823
824
19.7k
        let next_ifd = if bigtiff {
825
481
            Some(reader.read_u64()?)
826
        } else {
827
19.3k
            Some(u64::from(reader.read_u32()?))
828
        }
829
19.7k
        .map(IfdPointer);
830
831
19.7k
        let current_ifd = *next_ifd.as_ref().unwrap();
832
19.7k
        let ifd_offsets = vec![current_ifd];
833
834
19.7k
        let mut decoder = Decoder {
835
19.7k
            value_reader: ValueReader {
836
19.7k
                reader,
837
19.7k
                bigtiff,
838
19.7k
                limits: Default::default(),
839
19.7k
            },
840
19.7k
            next_ifd,
841
19.7k
            ifd_offsets,
842
19.7k
            current_ifd: None,
843
19.7k
            seen_ifds: cycles::IfdCycles::new(),
844
19.7k
            image: Image {
845
19.7k
                ifd: None,
846
19.7k
                width: 0,
847
19.7k
                height: 0,
848
19.7k
                bits_per_sample: 1,
849
19.7k
                samples: 1,
850
19.7k
                extra_samples: vec![],
851
19.7k
                photometric_samples: 1,
852
19.7k
                sample_format: SampleFormat::Uint,
853
19.7k
                photometric_interpretation: PhotometricInterpretation::BlackIsZero,
854
19.7k
                compression_method: CompressionMethod::None,
855
19.7k
                jpeg_tables: None,
856
19.7k
                predictor: Predictor::None,
857
19.7k
                chunk_type: ChunkType::Strip,
858
19.7k
                planar_config: PlanarConfiguration::Chunky,
859
19.7k
                strip_decoder: None,
860
19.7k
                tile_attributes: None,
861
19.7k
                chunk_offsets: Vec::new(),
862
19.7k
                chunk_bytes: Vec::new(),
863
19.7k
                chroma_subsampling: (2, 2),
864
19.7k
            },
865
19.7k
        };
866
19.7k
        decoder.next_image()?;
867
14.0k
        Ok(decoder)
868
19.8k
    }
<tiff::decoder::Decoder<std::io::cursor::Cursor<&[u8]>>>::new
Line
Count
Source
786
19.8k
    pub fn new(mut r: R) -> TiffResult<Decoder<R>> {
787
19.8k
        let mut endianess = Vec::with_capacity(2);
788
19.8k
        (&mut r).take(2).read_to_end(&mut endianess)?;
789
19.8k
        let byte_order = match &*endianess {
790
19.8k
            b"II" => ByteOrder::LittleEndian,
791
1.42k
            b"MM" => ByteOrder::BigEndian,
792
            _ => {
793
20
                return Err(TiffError::FormatError(
794
20
                    TiffFormatError::TiffSignatureNotFound,
795
20
                ))
796
            }
797
        };
798
19.8k
        let mut reader = EndianReader::new(r, byte_order);
799
800
19.8k
        let bigtiff = match reader.read_u16()? {
801
19.3k
            42 => false,
802
            43 => {
803
                // Read bytesize of offsets (in bigtiff it's alway 8 but provide a way to move to 16 some day)
804
518
                if reader.read_u16()? != 8 {
805
16
                    return Err(TiffError::FormatError(
806
16
                        TiffFormatError::TiffSignatureNotFound,
807
16
                    ));
808
499
                }
809
                // This constant should always be 0
810
499
                if reader.read_u16()? != 0 {
811
16
                    return Err(TiffError::FormatError(
812
16
                        TiffFormatError::TiffSignatureNotFound,
813
16
                    ));
814
481
                }
815
481
                true
816
            }
817
            _ => {
818
1
                return Err(TiffError::FormatError(
819
1
                    TiffFormatError::TiffSignatureInvalid,
820
1
                ))
821
            }
822
        };
823
824
19.7k
        let next_ifd = if bigtiff {
825
481
            Some(reader.read_u64()?)
826
        } else {
827
19.3k
            Some(u64::from(reader.read_u32()?))
828
        }
829
19.7k
        .map(IfdPointer);
830
831
19.7k
        let current_ifd = *next_ifd.as_ref().unwrap();
832
19.7k
        let ifd_offsets = vec![current_ifd];
833
834
19.7k
        let mut decoder = Decoder {
835
19.7k
            value_reader: ValueReader {
836
19.7k
                reader,
837
19.7k
                bigtiff,
838
19.7k
                limits: Default::default(),
839
19.7k
            },
840
19.7k
            next_ifd,
841
19.7k
            ifd_offsets,
842
19.7k
            current_ifd: None,
843
19.7k
            seen_ifds: cycles::IfdCycles::new(),
844
19.7k
            image: Image {
845
19.7k
                ifd: None,
846
19.7k
                width: 0,
847
19.7k
                height: 0,
848
19.7k
                bits_per_sample: 1,
849
19.7k
                samples: 1,
850
19.7k
                extra_samples: vec![],
851
19.7k
                photometric_samples: 1,
852
19.7k
                sample_format: SampleFormat::Uint,
853
19.7k
                photometric_interpretation: PhotometricInterpretation::BlackIsZero,
854
19.7k
                compression_method: CompressionMethod::None,
855
19.7k
                jpeg_tables: None,
856
19.7k
                predictor: Predictor::None,
857
19.7k
                chunk_type: ChunkType::Strip,
858
19.7k
                planar_config: PlanarConfiguration::Chunky,
859
19.7k
                strip_decoder: None,
860
19.7k
                tile_attributes: None,
861
19.7k
                chunk_offsets: Vec::new(),
862
19.7k
                chunk_bytes: Vec::new(),
863
19.7k
                chroma_subsampling: (2, 2),
864
19.7k
            },
865
19.7k
        };
866
19.7k
        decoder.next_image()?;
867
14.0k
        Ok(decoder)
868
19.8k
    }
Unexecuted instantiation: <tiff::decoder::Decoder<_>>::new
869
870
13.7k
    pub fn with_limits(mut self, limits: Limits) -> Decoder<R> {
871
13.7k
        self.value_reader.limits = limits;
872
13.7k
        self
873
13.7k
    }
<tiff::decoder::Decoder<std::io::cursor::Cursor<&[u8]>>>::with_limits
Line
Count
Source
870
13.7k
    pub fn with_limits(mut self, limits: Limits) -> Decoder<R> {
871
13.7k
        self.value_reader.limits = limits;
872
13.7k
        self
873
13.7k
    }
Unexecuted instantiation: <tiff::decoder::Decoder<_>>::with_limits
874
875
14.0k
    pub fn dimensions(&mut self) -> TiffResult<(u32, u32)> {
876
14.0k
        Ok((self.image().width, self.image().height))
877
14.0k
    }
<tiff::decoder::Decoder<std::io::cursor::Cursor<&[u8]>>>::dimensions
Line
Count
Source
875
14.0k
    pub fn dimensions(&mut self) -> TiffResult<(u32, u32)> {
876
14.0k
        Ok((self.image().width, self.image().height))
877
14.0k
    }
Unexecuted instantiation: <tiff::decoder::Decoder<_>>::dimensions
878
879
14.0k
    pub fn colortype(&mut self) -> TiffResult<ColorType> {
880
14.0k
        self.image().colortype()
881
14.0k
    }
<tiff::decoder::Decoder<std::io::cursor::Cursor<&[u8]>>>::colortype
Line
Count
Source
879
14.0k
    pub fn colortype(&mut self) -> TiffResult<ColorType> {
880
14.0k
        self.image().colortype()
881
14.0k
    }
Unexecuted instantiation: <tiff::decoder::Decoder<_>>::colortype
882
883
    /// The offset of the directory representing the current image.
884
0
    pub fn ifd_pointer(&mut self) -> Option<IfdPointer> {
885
0
        self.current_ifd
886
0
    }
887
888
104k
    fn image(&self) -> &Image {
889
104k
        &self.image
890
104k
    }
<tiff::decoder::Decoder<std::io::cursor::Cursor<&[u8]>>>::image
Line
Count
Source
888
104k
    fn image(&self) -> &Image {
889
104k
        &self.image
890
104k
    }
Unexecuted instantiation: <tiff::decoder::Decoder<_>>::image
891
892
    /// Loads the IFD at the specified index in the list, if one exists
893
0
    pub fn seek_to_image(&mut self, ifd_index: usize) -> TiffResult<()> {
894
        // Check whether we have seen this IFD before, if so then the index will be less than the length of the list of ifd offsets
895
0
        if ifd_index >= self.ifd_offsets.len() {
896
            // We possibly need to load in the next IFD
897
0
            if self.next_ifd.is_none() {
898
0
                self.current_ifd = None;
899
900
0
                return Err(TiffError::FormatError(
901
0
                    TiffFormatError::ImageFileDirectoryNotFound,
902
0
                ));
903
0
            }
904
905
            loop {
906
                // Follow the list until we find the one we want, or we reach the end, whichever happens first
907
0
                let ifd = self.next_ifd()?;
908
909
0
                if ifd.next().is_none() {
910
0
                    break;
911
0
                }
912
913
0
                if ifd_index < self.ifd_offsets.len() {
914
0
                    break;
915
0
                }
916
            }
917
0
        }
918
919
        // If the index is within the list of ifds then we can load the selected image/IFD
920
0
        if let Some(ifd_offset) = self.ifd_offsets.get(ifd_index) {
921
0
            let ifd = self.value_reader.read_directory(*ifd_offset)?;
922
0
            self.next_ifd = ifd.next();
923
0
            self.current_ifd = Some(*ifd_offset);
924
0
            self.image = Image::from_reader(&mut self.value_reader, ifd)?;
925
926
0
            Ok(())
927
        } else {
928
0
            Err(TiffError::FormatError(
929
0
                TiffFormatError::ImageFileDirectoryNotFound,
930
0
            ))
931
        }
932
0
    }
933
934
19.7k
    fn next_ifd(&mut self) -> TiffResult<Directory> {
935
19.7k
        let Some(next_ifd) = self.next_ifd.take() else {
936
0
            return Err(TiffError::FormatError(
937
0
                TiffFormatError::ImageFileDirectoryNotFound,
938
0
            ));
939
        };
940
941
19.7k
        let ifd = self.value_reader.read_directory(next_ifd)?;
942
943
        // Ensure this walk does not get us into a cycle.
944
17.7k
        self.seen_ifds.insert_next(next_ifd, ifd.next())?;
945
946
        // Extend the list of known IFD offsets in this chain, if needed.
947
17.6k
        if self.ifd_offsets.last().copied() == self.current_ifd {
948
0
            self.ifd_offsets.push(next_ifd);
949
17.6k
        }
950
951
17.6k
        self.current_ifd = Some(next_ifd);
952
17.6k
        self.next_ifd = ifd.next();
953
954
17.6k
        Ok(ifd)
955
19.7k
    }
<tiff::decoder::Decoder<std::io::cursor::Cursor<&[u8]>>>::next_ifd
Line
Count
Source
934
19.7k
    fn next_ifd(&mut self) -> TiffResult<Directory> {
935
19.7k
        let Some(next_ifd) = self.next_ifd.take() else {
936
0
            return Err(TiffError::FormatError(
937
0
                TiffFormatError::ImageFileDirectoryNotFound,
938
0
            ));
939
        };
940
941
19.7k
        let ifd = self.value_reader.read_directory(next_ifd)?;
942
943
        // Ensure this walk does not get us into a cycle.
944
17.7k
        self.seen_ifds.insert_next(next_ifd, ifd.next())?;
945
946
        // Extend the list of known IFD offsets in this chain, if needed.
947
17.6k
        if self.ifd_offsets.last().copied() == self.current_ifd {
948
0
            self.ifd_offsets.push(next_ifd);
949
17.6k
        }
950
951
17.6k
        self.current_ifd = Some(next_ifd);
952
17.6k
        self.next_ifd = ifd.next();
953
954
17.6k
        Ok(ifd)
955
19.7k
    }
Unexecuted instantiation: <tiff::decoder::Decoder<_>>::next_ifd
956
957
    /// Reads in the next image.
958
    /// If there is no further image in the TIFF file a format error is returned.
959
    /// To determine whether there are more images call `TIFFDecoder::more_images` instead.
960
19.7k
    pub fn next_image(&mut self) -> TiffResult<()> {
961
19.7k
        let ifd = self.next_ifd()?;
962
17.6k
        self.image = Image::from_reader(&mut self.value_reader, ifd)?;
963
14.0k
        Ok(())
964
19.7k
    }
<tiff::decoder::Decoder<std::io::cursor::Cursor<&[u8]>>>::next_image
Line
Count
Source
960
19.7k
    pub fn next_image(&mut self) -> TiffResult<()> {
961
19.7k
        let ifd = self.next_ifd()?;
962
17.6k
        self.image = Image::from_reader(&mut self.value_reader, ifd)?;
963
14.0k
        Ok(())
964
19.7k
    }
Unexecuted instantiation: <tiff::decoder::Decoder<_>>::next_image
965
966
    /// Returns `true` if there is at least one more image available.
967
0
    pub fn more_images(&self) -> bool {
968
0
        self.next_ifd.is_some()
969
0
    }
970
971
    /// Returns the byte_order of the file.
972
    ///
973
    /// # Usage
974
    ///
975
    /// This is only relevant to interpreting raw bytes read from tags. The image decoding methods
976
    /// will correct to the host byte order automatically.
977
0
    pub fn byte_order(&self) -> ByteOrder {
978
0
        self.value_reader.reader.byte_order
979
0
    }
980
981
    #[inline]
982
0
    pub fn read_ifd_offset(&mut self) -> Result<u64, io::Error> {
983
0
        if self.value_reader.bigtiff {
984
0
            self.read_long8()
985
        } else {
986
0
            self.read_long().map(u64::from)
987
        }
988
0
    }
989
990
    /// Returns a mutable reference to the stream being decoded.
991
0
    pub fn inner(&mut self) -> &mut R {
992
0
        self.value_reader.reader.inner()
993
0
    }
994
995
    /// Reads a TIFF byte value
996
    #[inline]
997
0
    pub fn read_byte(&mut self) -> Result<u8, io::Error> {
998
0
        let mut buf = [0; 1];
999
0
        self.value_reader.reader.inner().read_exact(&mut buf)?;
1000
0
        Ok(buf[0])
1001
0
    }
1002
1003
    /// Reads a TIFF short value
1004
    #[inline]
1005
0
    pub fn read_short(&mut self) -> Result<u16, io::Error> {
1006
0
        self.value_reader.reader.read_u16()
1007
0
    }
1008
1009
    /// Reads a TIFF sshort value
1010
    #[inline]
1011
0
    pub fn read_sshort(&mut self) -> Result<i16, io::Error> {
1012
0
        self.value_reader.reader.read_i16()
1013
0
    }
1014
1015
    /// Reads a TIFF long value
1016
    #[inline]
1017
0
    pub fn read_long(&mut self) -> Result<u32, io::Error> {
1018
0
        self.value_reader.reader.read_u32()
1019
0
    }
1020
1021
    /// Reads a TIFF slong value
1022
    #[inline]
1023
0
    pub fn read_slong(&mut self) -> Result<i32, io::Error> {
1024
0
        self.value_reader.reader.read_i32()
1025
0
    }
1026
1027
    /// Reads a TIFF float value
1028
    #[inline]
1029
0
    pub fn read_float(&mut self) -> Result<f32, io::Error> {
1030
0
        self.value_reader.reader.read_f32()
1031
0
    }
1032
1033
    /// Reads a TIFF double value
1034
    #[inline]
1035
0
    pub fn read_double(&mut self) -> Result<f64, io::Error> {
1036
0
        self.value_reader.reader.read_f64()
1037
0
    }
1038
1039
    #[inline]
1040
0
    pub fn read_long8(&mut self) -> Result<u64, io::Error> {
1041
0
        self.value_reader.reader.read_u64()
1042
0
    }
1043
1044
    #[inline]
1045
0
    pub fn read_slong8(&mut self) -> Result<i64, io::Error> {
1046
0
        self.value_reader.reader.read_i64()
1047
0
    }
1048
1049
    /// Reads a string
1050
    #[inline]
1051
0
    pub fn read_string(&mut self, length: usize) -> TiffResult<String> {
1052
0
        let mut out = vec![0; length];
1053
0
        self.value_reader.reader.inner().read_exact(&mut out)?;
1054
        // Strings may be null-terminated, so we trim anything downstream of the null byte
1055
0
        if let Some(first) = out.iter().position(|&b| b == 0) {
1056
0
            out.truncate(first);
1057
0
        }
1058
0
        Ok(String::from_utf8(out)?)
1059
0
    }
1060
1061
    /// Reads a TIFF IFA offset/value field
1062
    #[inline]
1063
0
    pub fn read_offset(&mut self) -> TiffResult<[u8; 4]> {
1064
0
        if self.value_reader.bigtiff {
1065
0
            return Err(TiffError::FormatError(
1066
0
                TiffFormatError::InconsistentSizesEncountered,
1067
0
            ));
1068
0
        }
1069
0
        let mut val = [0; 4];
1070
0
        self.value_reader.reader.inner().read_exact(&mut val)?;
1071
0
        Ok(val)
1072
0
    }
1073
1074
    /// Reads a TIFF IFA offset/value field
1075
    #[inline]
1076
0
    pub fn read_offset_u64(&mut self) -> Result<[u8; 8], io::Error> {
1077
0
        let mut val = [0; 8];
1078
0
        self.value_reader.reader.inner().read_exact(&mut val)?;
1079
0
        Ok(val)
1080
0
    }
1081
1082
    /// Moves the cursor to the specified offset
1083
    #[inline]
1084
0
    pub fn goto_offset(&mut self, offset: u32) -> io::Result<()> {
1085
0
        self.goto_offset_u64(offset.into())
1086
0
    }
1087
1088
    #[inline]
1089
35.1k
    pub fn goto_offset_u64(&mut self, offset: u64) -> io::Result<()> {
1090
35.1k
        self.value_reader.reader.goto_offset(offset)
1091
35.1k
    }
<tiff::decoder::Decoder<std::io::cursor::Cursor<&[u8]>>>::goto_offset_u64
Line
Count
Source
1089
35.1k
    pub fn goto_offset_u64(&mut self, offset: u64) -> io::Result<()> {
1090
35.1k
        self.value_reader.reader.goto_offset(offset)
1091
35.1k
    }
Unexecuted instantiation: <tiff::decoder::Decoder<_>>::goto_offset_u64
1092
1093
    /// Read a tag-entry map from a known offset.
1094
    ///
1095
    /// A TIFF [`Directory`], aka. image file directory aka. IFD, refers to a map from
1096
    /// tags–identified by a `u16`–to a typed vector of elements. It is encoded as a list
1097
    /// of ascending tag values with the offset and type of their corresponding values. The
1098
    /// semantic interpretations of a tag and its type requirements depend on the context of the
1099
    /// directory. The main image directories, those iterated over by the `Decoder` after
1100
    /// construction, are represented by [`Tag`] and [`ifd::Value`]. Other forms are EXIF and GPS
1101
    /// data as well as thumbnail Sub-IFD representations associated with each image file.
1102
    ///
1103
    /// This method allows the decoding of a directory from an arbitrary offset in the image file
1104
    /// with no specific semantic interpretation. Such an offset is usually found as the value of
1105
    /// a tag, e.g. [`Tag::SubIfd`], [`Tag::ExifDirectory`], [`Tag::GpsDirectory`] and recovered
1106
    /// from the associated value by [`ifd::Value::into_ifd_pointer`].
1107
    ///
1108
    /// The library will not verify whether the offset overlaps any other directory or would form a
1109
    /// cycle with any other directory when calling this method. This will modify the position of
1110
    /// the reader, i.e. continuing with direct reads at a later point will require going back with
1111
    /// [`Self::goto_offset`].
1112
0
    pub fn read_directory(&mut self, ptr: IfdPointer) -> TiffResult<Directory> {
1113
0
        self.value_reader.read_directory(ptr)
1114
0
    }
1115
1116
0
    fn check_chunk_type(&self, expected: ChunkType) -> TiffResult<()> {
1117
0
        if expected != self.image().chunk_type {
1118
0
            return Err(TiffError::UsageError(UsageError::InvalidChunkType(
1119
0
                expected,
1120
0
                self.image().chunk_type,
1121
0
            )));
1122
0
        }
1123
1124
0
        Ok(())
1125
0
    }
1126
1127
    /// The chunk type (Strips / Tiles) of the image
1128
0
    pub fn get_chunk_type(&self) -> ChunkType {
1129
0
        self.image().chunk_type
1130
0
    }
1131
1132
    /// Number of strips in image
1133
0
    pub fn strip_count(&mut self) -> TiffResult<u32> {
1134
0
        self.check_chunk_type(ChunkType::Strip)?;
1135
0
        let rows_per_strip = self.image().strip_decoder.as_ref().unwrap().rows_per_strip;
1136
1137
0
        if rows_per_strip == 0 {
1138
0
            return Ok(0);
1139
0
        }
1140
1141
        // rows_per_strip - 1 can never fail since we know it's at least 1
1142
0
        let height = match self.image().height.checked_add(rows_per_strip - 1) {
1143
0
            Some(h) => h,
1144
0
            None => return Err(TiffError::IntSizeError),
1145
        };
1146
1147
0
        let strips = match self.image().planar_config {
1148
0
            PlanarConfiguration::Chunky => height / rows_per_strip,
1149
0
            PlanarConfiguration::Planar => height / rows_per_strip * self.image().samples as u32,
1150
        };
1151
1152
0
        Ok(strips)
1153
0
    }
1154
1155
    /// Number of tiles in image
1156
0
    pub fn tile_count(&mut self) -> TiffResult<u32> {
1157
0
        self.check_chunk_type(ChunkType::Tile)?;
1158
0
        Ok(u32::try_from(self.image().chunk_offsets.len())?)
1159
0
    }
1160
1161
0
    fn read_chunk_to_bytes(
1162
0
        &mut self,
1163
0
        buffer: &mut [u8],
1164
0
        chunk_index: u32,
1165
0
        layout: &image::ReadoutLayout,
1166
0
    ) -> TiffResult<()> {
1167
0
        let offset = self.image.chunk_file_range(chunk_index)?.0;
1168
0
        self.goto_offset_u64(offset)?;
1169
1170
0
        self.image
1171
0
            .expand_chunk(&mut self.value_reader, buffer, layout, chunk_index)?;
1172
1173
0
        Ok(())
1174
0
    }
1175
1176
    /// Returns the layout preferred to read the specified chunk with [`Self::read_chunk_bytes`].
1177
    ///
1178
    /// Returns the layout without being specific as to the underlying type for forward
1179
    /// compatibility. Note that, in general, a TIFF may contain an almost arbitrary number of
1180
    /// channels of individual *bit* length and format each.
1181
    ///
1182
    /// See [`Self::colortype`] to describe the sample types.
1183
0
    pub fn image_chunk_buffer_layout(
1184
0
        &mut self,
1185
0
        chunk_index: u32,
1186
0
    ) -> TiffResult<BufferLayoutPreference> {
1187
0
        let data_dims = self.image().chunk_data_dimensions(chunk_index)?;
1188
0
        let readout = self.image().readout_for_size(data_dims.0, data_dims.1)?;
1189
1190
0
        let extent = readout.result_extent_for_planes(0..1)?;
1191
0
        let sample_type = extent.sample_type();
1192
0
        let layout = extent.preferred_layout()?;
1193
1194
0
        let row_stride = core::num::NonZeroUsize::new(readout.minimum_row_stride);
1195
0
        let plane_stride = core::num::NonZeroUsize::new(readout.plane_stride);
1196
1197
0
        Ok(BufferLayoutPreference {
1198
0
            len: layout.size(),
1199
0
            row_stride,
1200
0
            planes: 1,
1201
0
            plane_stride,
1202
0
            complete_len: layout.size(),
1203
0
            sample_format: self.image().sample_format,
1204
0
            sample_type: Some(sample_type),
1205
0
        })
1206
0
    }
1207
1208
    /// Return the layout preferred to read several planes corresponding to the specified region.
1209
    ///
1210
    /// This is similar to [`Self::image_chunk_buffer_layout`] but can read chunks from all planes
1211
    /// at the corresponding coordinates of the image.
1212
    ///
1213
    /// # Bugs
1214
    ///
1215
    /// Sub-sampled images are not yet supported properly.
1216
0
    pub fn image_coding_unit_layout(
1217
0
        &mut self,
1218
0
        code_unit: TiffCodingUnit,
1219
0
    ) -> TiffResult<BufferLayoutPreference> {
1220
0
        match self.image().planar_config {
1221
0
            PlanarConfiguration::Chunky => return self.image_chunk_buffer_layout(code_unit.0),
1222
0
            PlanarConfiguration::Planar => {}
1223
        }
1224
1225
0
        let (width, height) = self.image().chunk_data_dimensions(code_unit.0)?;
1226
1227
0
        let layout = self
1228
0
            .image()
1229
0
            .readout_for_size(width, height)?
1230
0
            .to_plane_layout()?;
1231
1232
0
        if code_unit.0 >= layout.readout.chunks_per_plane {
1233
0
            return Err(TiffError::UsageError(UsageError::InvalidCodingUnit(
1234
0
                code_unit.0,
1235
0
                layout.readout.chunks_per_plane,
1236
0
            )));
1237
0
        }
1238
1239
0
        Ok(BufferLayoutPreference::from_planes(&layout))
1240
0
    }
1241
1242
    /// Read the specified chunk (at index `chunk_index`) and return the binary data as a Vector.
1243
    ///
1244
    /// Note that for planar images each chunk contains only one sample of the underlying data.
1245
0
    pub fn read_chunk(&mut self, chunk_index: u32) -> TiffResult<DecodingResult> {
1246
0
        let (width, height) = self.image().chunk_data_dimensions(chunk_index)?;
1247
1248
0
        let readout = self.image().readout_for_size(width, height)?;
1249
1250
0
        let mut result = readout
1251
0
            .result_extent_for_planes(0..1)?
1252
0
            .to_result_buffer(&self.value_reader.limits)?;
1253
1254
0
        self.read_chunk_to_bytes(result.as_buffer(0).as_bytes_mut(), chunk_index, &readout)?;
1255
1256
0
        Ok(result)
1257
0
    }
1258
1259
    /// Read the specified chunk (at index `chunk_index`) into an allocated buffer.
1260
    ///
1261
    /// Returns a [`TiffError::UsageError`] if the chunk is smaller than the size indicated with a
1262
    /// call to [`Self::image_chunk_buffer_layout`]. Note that the alignment may be arbitrary, but
1263
    /// an alignment smaller than the preferred alignment may perform worse.
1264
    ///
1265
    /// Note that for planar images each chunk contains only one sample of the underlying data.
1266
0
    pub fn read_chunk_bytes(&mut self, chunk_index: u32, buffer: &mut [u8]) -> TiffResult<()> {
1267
0
        let (width, height) = self.image().chunk_data_dimensions(chunk_index)?;
1268
1269
0
        let layout = self.image().readout_for_size(width, height)?;
1270
0
        layout.assert_min_layout(buffer)?;
1271
1272
0
        self.read_chunk_to_bytes(buffer, chunk_index, &layout)?;
1273
1274
0
        Ok(())
1275
0
    }
1276
1277
    /// Read the specified chunk (at index `chunk_index`) into a provide buffer.
1278
    ///
1279
    /// It will re-allocate the buffer into the correct type and size, within the decoder's
1280
    /// configured limits, and then pass it to the underlying method. This is essentially a
1281
    /// type-safe wrapper around the raw [`Self::read_chunk_bytes`] method.
1282
    ///
1283
    /// Note that for planar images each chunk contains only one sample of the underlying data.
1284
0
    pub fn read_chunk_to_buffer(
1285
0
        &mut self,
1286
0
        buffer: &mut DecodingResult,
1287
0
        chunk_index: u32,
1288
0
        output_width: usize,
1289
0
    ) -> TiffResult<()> {
1290
0
        let (width, height) = self.image().chunk_data_dimensions(chunk_index)?;
1291
1292
0
        let mut layout = self.image().readout_for_size(width, height)?;
1293
0
        layout.set_row_stride(output_width)?;
1294
1295
0
        let extent = layout.result_extent_for_planes(0..1)?;
1296
0
        buffer.resize_to_extent(extent, &self.value_reader.limits)?;
1297
1298
0
        self.read_chunk_to_bytes(buffer.as_buffer(0).as_bytes_mut(), chunk_index, &layout)?;
1299
1300
0
        Ok(())
1301
0
    }
1302
1303
    /// Read chunks corresponding to several planes of a region of pixels.
1304
    ///
1305
    /// For non planar images this is equivalent to [`Self::read_chunk_bytes`] as there is only one
1306
    /// plane in the image. For planar images the planes are stored consecutively into the output
1307
    /// buffer. Returns an error if not enough space for at least one plane is provided. Otherwise
1308
    /// reads all planes that can be stored completely in the provided output buffer.
1309
    ///
1310
    /// A region is a rectangular assortment of pixels in the image, depending on the chunk type
1311
    /// either strips or tiles. Borrowing terminology from JPEG we call the collection of all
1312
    /// chunks from all planes that encode samples from the same region a "coding unit".
1313
    ///
1314
    /// # Bugs
1315
    ///
1316
    /// Sub-sampled images are not yet supported properly.
1317
0
    pub fn read_coding_unit_bytes(
1318
0
        &mut self,
1319
0
        slice: TiffCodingUnit,
1320
0
        buffer: &mut [u8],
1321
0
    ) -> TiffResult<()> {
1322
0
        let (width, height) = self.image().chunk_data_dimensions(slice.0)?;
1323
0
        let readout = self.image().readout_for_size(width, height)?;
1324
1325
0
        let ref layout @ image::PlaneLayout {
1326
0
            ref plane_offsets,
1327
            // We assume that is correct, so really it can be ignored.
1328
            total_bytes: _,
1329
0
            ref readout,
1330
0
        } = readout.to_plane_layout()?;
1331
1332
0
        if slice.0 >= readout.chunks_per_plane {
1333
0
            return Err(TiffError::UsageError(UsageError::InvalidCodingUnit(
1334
0
                slice.0,
1335
0
                readout.chunks_per_plane,
1336
0
            )));
1337
0
        }
1338
1339
        // No subsamples planes support, for now.
1340
0
        let used_plane_offsets = usize::from(layout.used_planes(buffer)?);
1341
0
        debug_assert!(used_plane_offsets >= 1, "Should have errored");
1342
1343
0
        for (idx, &plane_offset) in plane_offsets[..used_plane_offsets].iter().enumerate() {
1344
0
            let chunk = slice.0 + idx as u32 * readout.chunks_per_plane;
1345
0
            self.goto_offset_u64(self.image().chunk_offsets[chunk as usize])?;
1346
1347
0
            self.image.expand_chunk(
1348
0
                &mut self.value_reader,
1349
0
                &mut buffer[plane_offset..],
1350
0
                readout,
1351
0
                chunk,
1352
0
            )?;
1353
        }
1354
1355
0
        Ok(())
1356
0
    }
1357
1358
    /// Returns the default chunk size for the current image. Any given chunk in the image is at most as large as
1359
    /// the value returned here. For the size of the data (chunk minus padding), use `chunk_data_dimensions`.
1360
0
    pub fn chunk_dimensions(&self) -> (u32, u32) {
1361
0
        self.image().chunk_dimensions().unwrap()
1362
0
    }
1363
1364
    /// Returns the size of the data in the chunk with the specified index. This is the default size of the chunk,
1365
    /// minus any padding.
1366
0
    pub fn chunk_data_dimensions(&self, chunk_index: u32) -> (u32, u32) {
1367
0
        self.image()
1368
0
            .chunk_data_dimensions(chunk_index)
1369
0
            .expect("invalid chunk_index")
1370
0
    }
1371
1372
    /// Returns the preferred buffer required to read the whole image with [`Self::read_image_bytes`].
1373
    ///
1374
    /// Returns the layout without being specific as to the underlying type for forward
1375
    /// compatibility. Note that, in general, a TIFF may contain an almost arbitrary number of
1376
    /// channels of individual *bit* length and format each.
1377
    ///
1378
    /// See [`Self::colortype`] to describe the sample types.
1379
    ///
1380
    /// # Bugs
1381
    ///
1382
    /// When the image is stored as a planar configuration, this method will currently only
1383
    /// indicate the layout needed to read the first data plane. This will be fixed in a future
1384
    /// major version of `tiff`.
1385
0
    pub fn image_buffer_layout(&mut self) -> TiffResult<BufferLayoutPreference> {
1386
0
        let layout = self.image().readout_for_image()?.to_plane_layout()?;
1387
0
        Ok(BufferLayoutPreference::from_planes(&layout))
1388
0
    }
1389
1390
    /// Decodes the entire image and return it as a Vector
1391
    ///
1392
    /// # Examples
1393
    ///
1394
    /// This method is deprecated. For replacement usage see `examples/decode.rs`.
1395
    ///
1396
    /// # Bugs
1397
    ///
1398
    /// When the image is stored as a planar configuration, this method will currently only read
1399
    /// the first sample's plane. This will be fixed in a future major version of `tiff`. To read
1400
    /// multiple planes, [`Self::read_image_to_buffer`] can be used instead.
1401
    ///
1402
    /// # Intent to deprecate
1403
    ///
1404
    /// Use [`Self::read_image_to_buffer`] or a combination of [`DecodingResult::resize_to`] and
1405
    /// [`Self::read_image_bytes`] instead where possible, preserving the buffer across multiple
1406
    /// calls. This old method will likely keep its bugged planar behavior until it is fully
1407
    /// replaced, to ensure that existing code will not run into unexpectedly large allocations
1408
    /// that will error on limits instead.
1409
0
    pub fn read_image(&mut self) -> TiffResult<DecodingResult> {
1410
0
        let readout = self.image().readout_for_image()?;
1411
1412
0
        let mut result = readout
1413
0
            .result_extent_for_planes(0..1)?
1414
0
            .to_result_buffer(&self.value_reader.limits)?;
1415
1416
0
        self.read_image_bytes(result.as_buffer(0).as_bytes_mut())?;
1417
1418
0
        Ok(result)
1419
0
    }
1420
1421
    /// Decodes the entire image into a provided buffer.
1422
    ///
1423
    /// It will re-allocate the buffer into the correct type and size, within the decoder's
1424
    /// configured limits, and then pass it to the underlying method. This is essentially a
1425
    /// type-safe wrapper around the raw [`Self::read_image_bytes`] method.
1426
    ///
1427
    /// ## Planar behavior
1428
    ///
1429
    /// If the image is stored as a planar configuration, an attempt is made to resize the buffer
1430
    /// to hold all planes. If that does not fit then only the first plane is read. Check the
1431
    /// buffer size against [`BufferLayoutPreference::complete_len`] to ensure that all planes were
1432
    /// read:
1433
    ///
1434
    /// ```
1435
    /// use tiff::decoder::{Decoder, DecodingResult};
1436
    /// let mut result = DecodingResult::U8(vec![]);
1437
    ///
1438
    /// let mut reader = /* */
1439
    /// # Decoder::new(std::io::Cursor::new(include_bytes!(concat!(
1440
    /// #   env!("CARGO_MANIFEST_DIR"), "/tests/images/tiled-gray-i1.tif"
1441
    /// # )))).unwrap();
1442
    /// let layout = reader.read_image_to_buffer(&mut result)?;
1443
    ///
1444
    /// if result.as_buffer(0).as_bytes().len() < layout.complete_len {
1445
    ///    println!("Only the first plane was read");
1446
    /// }
1447
    ///
1448
    /// # Ok::<_, tiff::TiffError>(())
1449
    /// ```
1450
    ///
1451
    /// # Examples
1452
    ///
1453
    /// ```
1454
    /// use tiff::decoder::{Decoder, DecodingResult, Limits};
1455
    ///
1456
    /// let mut result = DecodingResult::I8(vec![]);
1457
    ///
1458
    /// let mut reader = /* */
1459
    /// # Decoder::new(std::io::Cursor::new(include_bytes!(concat!(
1460
    /// #   env!("CARGO_MANIFEST_DIR"), "/tests/images/tiled-gray-i1.tif"
1461
    /// # )))).unwrap();
1462
    ///
1463
    /// reader.read_image_to_buffer(&mut result)?;
1464
    ///
1465
    /// # Ok::<_, tiff::TiffError>(())
1466
    /// ```
1467
13.7k
    pub fn read_image_to_buffer(
1468
13.7k
        &mut self,
1469
13.7k
        result: &mut DecodingResult,
1470
13.7k
    ) -> TiffResult<BufferLayoutPreference> {
1471
13.7k
        let readout = self.image().readout_for_image()?;
1472
13.7k
        let planes = readout.to_plane_layout()?;
1473
1474
13.7k
        let num_planes = if planes.total_bytes <= self.value_reader.limits.decoding_buffer_size {
1475
13.7k
            planes.plane_offsets.len() as u16
1476
        } else {
1477
37
            1
1478
        };
1479
1480
13.7k
        let layout = BufferLayoutPreference::from_planes(&planes);
1481
13.7k
        let extent = readout.result_extent_for_planes(0..num_planes)?;
1482
        // Compatibility: if this extent is too large our configured limits we will fall back to
1483
        // reading only the first plane.
1484
13.7k
        result.resize_to_extent(extent, &self.value_reader.limits)?;
1485
1486
13.7k
        self.read_image_bytes(result.as_buffer(0).as_bytes_mut())?;
1487
1488
3.77k
        Ok(layout)
1489
13.7k
    }
<tiff::decoder::Decoder<std::io::cursor::Cursor<&[u8]>>>::read_image_to_buffer
Line
Count
Source
1467
13.7k
    pub fn read_image_to_buffer(
1468
13.7k
        &mut self,
1469
13.7k
        result: &mut DecodingResult,
1470
13.7k
    ) -> TiffResult<BufferLayoutPreference> {
1471
13.7k
        let readout = self.image().readout_for_image()?;
1472
13.7k
        let planes = readout.to_plane_layout()?;
1473
1474
13.7k
        let num_planes = if planes.total_bytes <= self.value_reader.limits.decoding_buffer_size {
1475
13.7k
            planes.plane_offsets.len() as u16
1476
        } else {
1477
37
            1
1478
        };
1479
1480
13.7k
        let layout = BufferLayoutPreference::from_planes(&planes);
1481
13.7k
        let extent = readout.result_extent_for_planes(0..num_planes)?;
1482
        // Compatibility: if this extent is too large our configured limits we will fall back to
1483
        // reading only the first plane.
1484
13.7k
        result.resize_to_extent(extent, &self.value_reader.limits)?;
1485
1486
13.7k
        self.read_image_bytes(result.as_buffer(0).as_bytes_mut())?;
1487
1488
3.77k
        Ok(layout)
1489
13.7k
    }
Unexecuted instantiation: <tiff::decoder::Decoder<_>>::read_image_to_buffer
1490
1491
    /// Decodes the entire image into a provided buffer.
1492
    ///
1493
    /// Returns a [`TiffError::UsageError`] if the chunk is smaller than the size indicated with a
1494
    /// call to [`Self::image_buffer_layout`]. Note that the alignment may be arbitrary, but an
1495
    /// alignment smaller than the preferred alignment may perform worse.
1496
    ///
1497
    /// # Error
1498
    ///
1499
    /// Returns an error if the buffer fits less than one plane. In particular, for non-planar
1500
    /// images returns an error if the buffer does not fit the required size.
1501
13.7k
    pub fn read_image_bytes(&mut self, buffer: &mut [u8]) -> TiffResult<()> {
1502
13.7k
        let readout = self.image().readout_for_image()?;
1503
1504
13.7k
        let ref layout @ image::PlaneLayout {
1505
13.7k
            ref plane_offsets,
1506
            // We assume that is correct, so really it can be ignored.
1507
            total_bytes: _,
1508
13.7k
            ref readout,
1509
13.7k
        } = readout.to_plane_layout()?;
1510
1511
13.7k
        let used_plane_offsets = usize::from(layout.used_planes(buffer)?);
1512
13.7k
        debug_assert!(used_plane_offsets >= 1, "Should have errored");
1513
1514
        // For multi-band images, only the first band is read.
1515
        // Possible improvements:
1516
        // * pass requested band as parameter
1517
        // * collect bands to a RGB encoding result in case of RGB bands
1518
34.7k
        for chunk in 0..readout.chunks_per_plane {
1519
34.7k
            let x = (chunk % readout.chunks_across) as usize;
1520
34.7k
            let y = (chunk / readout.chunks_across) as usize;
1521
1522
34.7k
            let buffer_offset = y * readout.chunk_col_stride + x * readout.chunk_row_stride;
1523
1524
35.1k
            for (idx, &plane_offset) in plane_offsets[..used_plane_offsets].iter().enumerate() {
1525
35.1k
                let chunk = chunk + idx as u32 * readout.chunks_per_plane;
1526
35.1k
                self.goto_offset_u64(self.image().chunk_offsets[chunk as usize])?;
1527
1528
35.1k
                self.image.expand_chunk(
1529
35.1k
                    &mut self.value_reader,
1530
35.1k
                    &mut buffer[plane_offset..][buffer_offset..],
1531
35.1k
                    readout,
1532
35.1k
                    chunk,
1533
9.96k
                )?;
1534
            }
1535
        }
1536
1537
3.77k
        Ok(())
1538
13.7k
    }
<tiff::decoder::Decoder<std::io::cursor::Cursor<&[u8]>>>::read_image_bytes
Line
Count
Source
1501
13.7k
    pub fn read_image_bytes(&mut self, buffer: &mut [u8]) -> TiffResult<()> {
1502
13.7k
        let readout = self.image().readout_for_image()?;
1503
1504
13.7k
        let ref layout @ image::PlaneLayout {
1505
13.7k
            ref plane_offsets,
1506
            // We assume that is correct, so really it can be ignored.
1507
            total_bytes: _,
1508
13.7k
            ref readout,
1509
13.7k
        } = readout.to_plane_layout()?;
1510
1511
13.7k
        let used_plane_offsets = usize::from(layout.used_planes(buffer)?);
1512
13.7k
        debug_assert!(used_plane_offsets >= 1, "Should have errored");
1513
1514
        // For multi-band images, only the first band is read.
1515
        // Possible improvements:
1516
        // * pass requested band as parameter
1517
        // * collect bands to a RGB encoding result in case of RGB bands
1518
34.7k
        for chunk in 0..readout.chunks_per_plane {
1519
34.7k
            let x = (chunk % readout.chunks_across) as usize;
1520
34.7k
            let y = (chunk / readout.chunks_across) as usize;
1521
1522
34.7k
            let buffer_offset = y * readout.chunk_col_stride + x * readout.chunk_row_stride;
1523
1524
35.1k
            for (idx, &plane_offset) in plane_offsets[..used_plane_offsets].iter().enumerate() {
1525
35.1k
                let chunk = chunk + idx as u32 * readout.chunks_per_plane;
1526
35.1k
                self.goto_offset_u64(self.image().chunk_offsets[chunk as usize])?;
1527
1528
35.1k
                self.image.expand_chunk(
1529
35.1k
                    &mut self.value_reader,
1530
35.1k
                    &mut buffer[plane_offset..][buffer_offset..],
1531
35.1k
                    readout,
1532
35.1k
                    chunk,
1533
9.96k
                )?;
1534
            }
1535
        }
1536
1537
3.77k
        Ok(())
1538
13.7k
    }
Unexecuted instantiation: <tiff::decoder::Decoder<_>>::read_image_bytes
1539
1540
    /// Get the IFD decoder for our current image IFD.
1541
13.9k
    pub fn image_ifd(&mut self) -> IfdDecoder<'_> {
1542
13.9k
        IfdDecoder {
1543
13.9k
            inner: tag_reader::TagReader {
1544
13.9k
                decoder: &mut self.value_reader,
1545
13.9k
                ifd: self.image.ifd.as_ref().unwrap(),
1546
13.9k
            },
1547
13.9k
        }
1548
13.9k
    }
<tiff::decoder::Decoder<std::io::cursor::Cursor<&[u8]>>>::image_ifd
Line
Count
Source
1541
13.9k
    pub fn image_ifd(&mut self) -> IfdDecoder<'_> {
1542
13.9k
        IfdDecoder {
1543
13.9k
            inner: tag_reader::TagReader {
1544
13.9k
                decoder: &mut self.value_reader,
1545
13.9k
                ifd: self.image.ifd.as_ref().unwrap(),
1546
13.9k
            },
1547
13.9k
        }
1548
13.9k
    }
Unexecuted instantiation: <tiff::decoder::Decoder<_>>::image_ifd
1549
1550
    /// Prepare reading values for tags of a given directory.
1551
    ///
1552
    /// # Examples
1553
    ///
1554
    /// This method may be used to read the values of tags in directories that have been previously
1555
    /// read with [`Decoder::read_directory`].
1556
    ///
1557
    /// ```no_run
1558
    /// use tiff::decoder::Decoder;
1559
    /// use tiff::tags::Tag;
1560
    ///
1561
    /// # use std::io::Cursor;
1562
    /// # let mut data = Cursor::new(vec![0]);
1563
    /// let mut decoder = Decoder::new(&mut data).unwrap();
1564
    /// let sub_ifds = decoder.get_tag(Tag::SubIfd)?.into_ifd_vec()?;
1565
    ///
1566
    /// for ifd in sub_ifds {
1567
    ///     let subdir = decoder.read_directory(ifd)?;
1568
    ///     let subfile = decoder.read_directory_tags(&subdir).find_tag(Tag::SubfileType)?;
1569
    ///     // omitted: handle the subfiles, e.g. thumbnails
1570
    /// }
1571
    ///
1572
    /// # Ok::<_, tiff::TiffError>(())
1573
    /// ```
1574
0
    pub fn read_directory_tags<'ifd>(&'ifd mut self, ifd: &'ifd Directory) -> IfdDecoder<'ifd> {
1575
0
        IfdDecoder {
1576
0
            inner: tag_reader::TagReader {
1577
0
                decoder: &mut self.value_reader,
1578
0
                ifd,
1579
0
            },
1580
0
        }
1581
0
    }
1582
1583
    /// Tries to retrieve a tag from the current image directory.
1584
    /// Return `Ok(None)` if the tag is not present.
1585
0
    pub fn find_tag(&mut self, tag: Tag) -> TiffResult<Option<ifd::Value>> {
1586
0
        self.image_ifd().find_tag(tag)
1587
0
    }
Unexecuted instantiation: <tiff::decoder::Decoder<std::io::cursor::Cursor<&[u8]>>>::find_tag
Unexecuted instantiation: <tiff::decoder::Decoder<_>>::find_tag
1588
1589
    /// Tries to retrieve a tag in the current image directory and convert it to the desired
1590
    /// unsigned type.
1591
0
    pub fn find_tag_unsigned<T: TryFrom<u64>>(&mut self, tag: Tag) -> TiffResult<Option<T>> {
1592
0
        self.image_ifd().find_tag_unsigned(tag)
1593
0
    }
1594
1595
    /// Tries to retrieve a vector of all a tag's values and convert them to the desired unsigned
1596
    /// type.
1597
13.9k
    pub fn find_tag_unsigned_vec<T: TryFrom<u64>>(
1598
13.9k
        &mut self,
1599
13.9k
        tag: Tag,
1600
13.9k
    ) -> TiffResult<Option<Vec<T>>> {
1601
13.9k
        self.image_ifd().find_tag_unsigned_vec(tag)
1602
13.9k
    }
<tiff::decoder::Decoder<std::io::cursor::Cursor<&[u8]>>>::find_tag_unsigned_vec::<u16>
Line
Count
Source
1597
13.9k
    pub fn find_tag_unsigned_vec<T: TryFrom<u64>>(
1598
13.9k
        &mut self,
1599
13.9k
        tag: Tag,
1600
13.9k
    ) -> TiffResult<Option<Vec<T>>> {
1601
13.9k
        self.image_ifd().find_tag_unsigned_vec(tag)
1602
13.9k
    }
Unexecuted instantiation: <tiff::decoder::Decoder<_>>::find_tag_unsigned_vec::<_>
1603
1604
    /// Tries to retrieve a tag from the current image directory and convert it to the desired
1605
    /// unsigned type. Returns an error if the tag is not present.
1606
0
    pub fn get_tag_unsigned<T: TryFrom<u64>>(&mut self, tag: Tag) -> TiffResult<T> {
1607
0
        self.image_ifd().get_tag_unsigned(tag)
1608
0
    }
1609
1610
    /// Tries to retrieve a tag from the current image directory.
1611
    /// Returns an error if the tag is not present
1612
0
    pub fn get_tag(&mut self, tag: Tag) -> TiffResult<ifd::Value> {
1613
0
        self.image_ifd().get_tag(tag)
1614
0
    }
Unexecuted instantiation: <tiff::decoder::Decoder<std::io::cursor::Cursor<&[u8]>>>::get_tag
Unexecuted instantiation: <tiff::decoder::Decoder<_>>::get_tag
1615
1616
0
    pub fn get_tag_u32(&mut self, tag: Tag) -> TiffResult<u32> {
1617
0
        self.get_tag(tag)?.into_u32()
1618
0
    }
1619
1620
0
    pub fn get_tag_u64(&mut self, tag: Tag) -> TiffResult<u64> {
1621
0
        self.get_tag(tag)?.into_u64()
1622
0
    }
1623
1624
    /// Tries to retrieve a tag and convert it to the desired type.
1625
0
    pub fn get_tag_f32(&mut self, tag: Tag) -> TiffResult<f32> {
1626
0
        self.get_tag(tag)?.into_f32()
1627
0
    }
1628
1629
    /// Tries to retrieve a tag and convert it to the desired type.
1630
0
    pub fn get_tag_f64(&mut self, tag: Tag) -> TiffResult<f64> {
1631
0
        self.get_tag(tag)?.into_f64()
1632
0
    }
1633
1634
    /// Tries to retrieve a tag and convert it to the desired type.
1635
0
    pub fn get_tag_u32_vec(&mut self, tag: Tag) -> TiffResult<Vec<u32>> {
1636
0
        self.get_tag(tag)?.into_u32_vec()
1637
0
    }
1638
1639
0
    pub fn get_tag_u16_vec(&mut self, tag: Tag) -> TiffResult<Vec<u16>> {
1640
0
        self.get_tag(tag)?.into_u16_vec()
1641
0
    }
1642
1643
0
    pub fn get_tag_u64_vec(&mut self, tag: Tag) -> TiffResult<Vec<u64>> {
1644
0
        self.get_tag(tag)?.into_u64_vec()
1645
0
    }
1646
1647
    /// Tries to retrieve a tag and convert it to the desired type.
1648
0
    pub fn get_tag_f32_vec(&mut self, tag: Tag) -> TiffResult<Vec<f32>> {
1649
0
        self.get_tag(tag)?.into_f32_vec()
1650
0
    }
1651
1652
    /// Tries to retrieve a tag and convert it to the desired type.
1653
0
    pub fn get_tag_f64_vec(&mut self, tag: Tag) -> TiffResult<Vec<f64>> {
1654
0
        self.get_tag(tag)?.into_f64_vec()
1655
0
    }
1656
1657
    /// Tries to retrieve a tag and convert it to a 8bit vector.
1658
0
    pub fn get_tag_u8_vec(&mut self, tag: Tag) -> TiffResult<Vec<u8>> {
1659
0
        self.get_tag(tag)?.into_u8_vec()
1660
0
    }
Unexecuted instantiation: <tiff::decoder::Decoder<std::io::cursor::Cursor<&[u8]>>>::get_tag_u8_vec
Unexecuted instantiation: <tiff::decoder::Decoder<_>>::get_tag_u8_vec
1661
1662
    /// Tries to retrieve a tag and convert it to a ascii vector.
1663
0
    pub fn get_tag_ascii_string(&mut self, tag: Tag) -> TiffResult<String> {
1664
0
        self.get_tag(tag)?.into_string()
1665
0
    }
1666
1667
0
    pub fn tag_iter(&mut self) -> impl Iterator<Item = TiffResult<(Tag, ifd::Value)>> + '_ {
1668
0
        self.image_ifd().tag_iter()
1669
0
    }
1670
}
1671
1672
impl<R: Seek + Read> ValueReader<R> {
1673
19.7k
    pub(crate) fn read_directory(&mut self, ptr: IfdPointer) -> Result<Directory, TiffError> {
1674
19.7k
        Self::read_ifd(&mut self.reader, self.bigtiff, ptr)
1675
19.7k
    }
<tiff::decoder::ValueReader<std::io::cursor::Cursor<&[u8]>>>::read_directory
Line
Count
Source
1673
19.7k
    pub(crate) fn read_directory(&mut self, ptr: IfdPointer) -> Result<Directory, TiffError> {
1674
19.7k
        Self::read_ifd(&mut self.reader, self.bigtiff, ptr)
1675
19.7k
    }
Unexecuted instantiation: <tiff::decoder::ValueReader<_>>::read_directory
1676
1677
    /// Reads a IFD entry.
1678
    // An IFD entry has four fields:
1679
    //
1680
    // Tag   2 bytes
1681
    // Type  2 bytes
1682
    // Count 4 bytes
1683
    // Value 4 bytes either a pointer the value itself
1684
1.73M
    fn read_entry(
1685
1.73M
        reader: &mut EndianReader<R>,
1686
1.73M
        bigtiff: bool,
1687
1.73M
    ) -> TiffResult<Option<(Tag, ifd::Entry)>> {
1688
1.73M
        let tag = Tag::from_u16_exhaustive(reader.read_u16()?);
1689
1.73M
        let type_ = match Type::from_u16(reader.read_u16()?) {
1690
445k
            Some(t) => t,
1691
            None => {
1692
                // Unknown type. Skip this entry according to spec.
1693
1.29M
                reader.read_u32()?;
1694
1.29M
                reader.read_u32()?;
1695
1.29M
                return Ok(None);
1696
            }
1697
        };
1698
445k
        let entry = if bigtiff {
1699
9.87k
            let mut offset = [0; 8];
1700
1701
9.87k
            let count = reader.read_u64()?;
1702
9.86k
            reader.inner().read_exact(&mut offset)?;
1703
9.85k
            ifd::Entry::new_u64(type_, count, offset)
1704
        } else {
1705
436k
            let mut offset = [0; 4];
1706
1707
436k
            let count = reader.read_u32()?;
1708
435k
            reader.inner().read_exact(&mut offset)?;
1709
435k
            ifd::Entry::new(type_, count, offset)
1710
        };
1711
445k
        Ok(Some((tag, entry)))
1712
1.73M
    }
<tiff::decoder::ValueReader<std::io::cursor::Cursor<&[u8]>>>::read_entry
Line
Count
Source
1684
1.73M
    fn read_entry(
1685
1.73M
        reader: &mut EndianReader<R>,
1686
1.73M
        bigtiff: bool,
1687
1.73M
    ) -> TiffResult<Option<(Tag, ifd::Entry)>> {
1688
1.73M
        let tag = Tag::from_u16_exhaustive(reader.read_u16()?);
1689
1.73M
        let type_ = match Type::from_u16(reader.read_u16()?) {
1690
445k
            Some(t) => t,
1691
            None => {
1692
                // Unknown type. Skip this entry according to spec.
1693
1.29M
                reader.read_u32()?;
1694
1.29M
                reader.read_u32()?;
1695
1.29M
                return Ok(None);
1696
            }
1697
        };
1698
445k
        let entry = if bigtiff {
1699
9.87k
            let mut offset = [0; 8];
1700
1701
9.87k
            let count = reader.read_u64()?;
1702
9.86k
            reader.inner().read_exact(&mut offset)?;
1703
9.85k
            ifd::Entry::new_u64(type_, count, offset)
1704
        } else {
1705
436k
            let mut offset = [0; 4];
1706
1707
436k
            let count = reader.read_u32()?;
1708
435k
            reader.inner().read_exact(&mut offset)?;
1709
435k
            ifd::Entry::new(type_, count, offset)
1710
        };
1711
445k
        Ok(Some((tag, entry)))
1712
1.73M
    }
Unexecuted instantiation: <tiff::decoder::ValueReader<_>>::read_entry
1713
1714
    /// Reads the IFD starting at the indicated location.
1715
19.7k
    fn read_ifd(
1716
19.7k
        reader: &mut EndianReader<R>,
1717
19.7k
        bigtiff: bool,
1718
19.7k
        ifd_location: IfdPointer,
1719
19.7k
    ) -> TiffResult<Directory> {
1720
19.7k
        reader.goto_offset(ifd_location.0)?;
1721
1722
19.7k
        let mut entries: BTreeMap<_, _> = BTreeMap::new();
1723
1724
19.7k
        let num_tags = if bigtiff {
1725
476
            reader.read_u64()?
1726
        } else {
1727
19.2k
            reader.read_u16()?.into()
1728
        };
1729
1730
19.7k
        for _ in 0..num_tags {
1731
1.73M
            let (tag, entry) = match Self::read_entry(reader, bigtiff)? {
1732
445k
                Some(val) => val,
1733
                None => {
1734
1.29M
                    continue;
1735
                } // Unknown data type in tag, skip
1736
            };
1737
1738
445k
            entries.insert(tag.to_u16(), entry);
1739
        }
1740
1741
17.7k
        let next_ifd = if bigtiff {
1742
337
            reader.read_u64()?
1743
        } else {
1744
17.3k
            reader.read_u32()?.into()
1745
        };
1746
1747
17.7k
        let next_ifd = core::num::NonZeroU64::new(next_ifd);
1748
1749
17.7k
        Ok(Directory { entries, next_ifd })
1750
19.7k
    }
<tiff::decoder::ValueReader<std::io::cursor::Cursor<&[u8]>>>::read_ifd
Line
Count
Source
1715
19.7k
    fn read_ifd(
1716
19.7k
        reader: &mut EndianReader<R>,
1717
19.7k
        bigtiff: bool,
1718
19.7k
        ifd_location: IfdPointer,
1719
19.7k
    ) -> TiffResult<Directory> {
1720
19.7k
        reader.goto_offset(ifd_location.0)?;
1721
1722
19.7k
        let mut entries: BTreeMap<_, _> = BTreeMap::new();
1723
1724
19.7k
        let num_tags = if bigtiff {
1725
476
            reader.read_u64()?
1726
        } else {
1727
19.2k
            reader.read_u16()?.into()
1728
        };
1729
1730
19.7k
        for _ in 0..num_tags {
1731
1.73M
            let (tag, entry) = match Self::read_entry(reader, bigtiff)? {
1732
445k
                Some(val) => val,
1733
                None => {
1734
1.29M
                    continue;
1735
                } // Unknown data type in tag, skip
1736
            };
1737
1738
445k
            entries.insert(tag.to_u16(), entry);
1739
        }
1740
1741
17.7k
        let next_ifd = if bigtiff {
1742
337
            reader.read_u64()?
1743
        } else {
1744
17.3k
            reader.read_u32()?.into()
1745
        };
1746
1747
17.7k
        let next_ifd = core::num::NonZeroU64::new(next_ifd);
1748
1749
17.7k
        Ok(Directory { entries, next_ifd })
1750
19.7k
    }
Unexecuted instantiation: <tiff::decoder::ValueReader<_>>::read_ifd
1751
}
1752
1753
impl IfdDecoder<'_> {
1754
    /// Retrieve the IFD entry for a given tag, if it exists.
1755
    ///
1756
    /// The entry contains the metadata of the value, that is its type and count from which we can
1757
    /// calculate a total byte size.
1758
0
    pub fn find_entry(&self, tag: Tag) -> Option<ifd::Entry> {
1759
0
        self.inner.ifd.get(tag).cloned()
1760
0
    }
1761
1762
    /// Tries to retrieve a tag.
1763
    /// Return `Ok(None)` if the tag is not present.
1764
13.9k
    pub fn find_tag(&mut self, tag: Tag) -> TiffResult<Option<ifd::Value>> {
1765
13.9k
        self.inner.find_tag(tag)
1766
13.9k
    }
1767
1768
    /// Retrieve a tag and reproduce its bytes into the provided buffer.
1769
    ///
1770
    /// The buffer is unmodified if the tag is not present.
1771
0
    pub fn find_tag_buf(
1772
0
        &mut self,
1773
0
        tag: Tag,
1774
0
        buf: &mut ValueBuffer,
1775
0
    ) -> TiffResult<Option<ifd::Entry>> {
1776
0
        self.inner.find_tag_buf(tag, buf)
1777
0
    }
1778
1779
    /// Read bytes of a tag's value into a byte buffer.
1780
0
    pub fn find_tag_bytes(
1781
0
        &mut self,
1782
0
        tag: Tag,
1783
0
        buf: &mut [u8],
1784
0
        offset: u64,
1785
0
    ) -> TiffResult<Option<usize>> {
1786
0
        self.inner.find_tag_raw(tag, buf, offset)
1787
0
    }
1788
1789
    /// Tries to retrieve a tag and convert it to the desired unsigned type.
1790
0
    pub fn find_tag_unsigned<T: TryFrom<u64>>(&mut self, tag: Tag) -> TiffResult<Option<T>> {
1791
0
        self.find_tag(tag)?
1792
0
            .map(|v| v.into_u64())
1793
0
            .transpose()?
1794
0
            .map(|value| {
1795
0
                T::try_from(value).map_err(|_| TiffFormatError::InvalidTagValueType(tag).into())
1796
0
            })
1797
0
            .transpose()
1798
0
    }
1799
1800
    /// Tries to retrieve a vector of all a tag's values and convert them to
1801
    /// the desired unsigned type.
1802
13.9k
    pub fn find_tag_unsigned_vec<T: TryFrom<u64>>(
1803
13.9k
        &mut self,
1804
13.9k
        tag: Tag,
1805
13.9k
    ) -> TiffResult<Option<Vec<T>>> {
1806
13.9k
        self.find_tag(tag)?
1807
13.9k
            .map(|v| v.into_u64_vec())
<tiff::decoder::IfdDecoder>::find_tag_unsigned_vec::<u16>::{closure#0}
Line
Count
Source
1807
2.23k
            .map(|v| v.into_u64_vec())
Unexecuted instantiation: <tiff::decoder::IfdDecoder>::find_tag_unsigned_vec::<_>::{closure#0}
1808
13.9k
            .transpose()?
1809
13.9k
            .map(|v| {
1810
2.23k
                v.into_iter()
1811
71.5k
                    .map(|u| {
1812
71.5k
                        T::try_from(u).map_err(|_| TiffFormatError::InvalidTagValueType(tag).into())
Unexecuted instantiation: <tiff::decoder::IfdDecoder>::find_tag_unsigned_vec::<u16>::{closure#1}::{closure#0}::{closure#0}
Unexecuted instantiation: <tiff::decoder::IfdDecoder>::find_tag_unsigned_vec::<_>::{closure#1}::{closure#0}::{closure#0}
1813
71.5k
                    })
<tiff::decoder::IfdDecoder>::find_tag_unsigned_vec::<u16>::{closure#1}::{closure#0}
Line
Count
Source
1811
71.5k
                    .map(|u| {
1812
71.5k
                        T::try_from(u).map_err(|_| TiffFormatError::InvalidTagValueType(tag).into())
1813
71.5k
                    })
Unexecuted instantiation: <tiff::decoder::IfdDecoder>::find_tag_unsigned_vec::<_>::{closure#1}::{closure#0}
1814
2.23k
                    .collect()
1815
2.23k
            })
<tiff::decoder::IfdDecoder>::find_tag_unsigned_vec::<u16>::{closure#1}
Line
Count
Source
1809
2.23k
            .map(|v| {
1810
2.23k
                v.into_iter()
1811
2.23k
                    .map(|u| {
1812
                        T::try_from(u).map_err(|_| TiffFormatError::InvalidTagValueType(tag).into())
1813
                    })
1814
2.23k
                    .collect()
1815
2.23k
            })
Unexecuted instantiation: <tiff::decoder::IfdDecoder>::find_tag_unsigned_vec::<_>::{closure#1}
1816
13.9k
            .transpose()
1817
13.9k
    }
<tiff::decoder::IfdDecoder>::find_tag_unsigned_vec::<u16>
Line
Count
Source
1802
13.9k
    pub fn find_tag_unsigned_vec<T: TryFrom<u64>>(
1803
13.9k
        &mut self,
1804
13.9k
        tag: Tag,
1805
13.9k
    ) -> TiffResult<Option<Vec<T>>> {
1806
13.9k
        self.find_tag(tag)?
1807
13.9k
            .map(|v| v.into_u64_vec())
1808
13.9k
            .transpose()?
1809
13.9k
            .map(|v| {
1810
                v.into_iter()
1811
                    .map(|u| {
1812
                        T::try_from(u).map_err(|_| TiffFormatError::InvalidTagValueType(tag).into())
1813
                    })
1814
                    .collect()
1815
            })
1816
13.9k
            .transpose()
1817
13.9k
    }
Unexecuted instantiation: <tiff::decoder::IfdDecoder>::find_tag_unsigned_vec::<_>
1818
1819
    /// Tries to retrieve a tag and convert it to the desired unsigned type.
1820
    /// Returns an error if the tag is not present.
1821
0
    pub fn get_tag_unsigned<T: TryFrom<u64>>(&mut self, tag: Tag) -> TiffResult<T> {
1822
0
        self.find_tag_unsigned(tag)?
1823
0
            .ok_or_else(|| TiffFormatError::RequiredTagNotFound(tag).into())
1824
0
    }
1825
1826
    /// Tries to retrieve a tag.
1827
    /// Returns an error if the tag is not present
1828
0
    pub fn get_tag(&mut self, tag: Tag) -> TiffResult<ifd::Value> {
1829
0
        match self.find_tag(tag)? {
1830
0
            Some(val) => Ok(val),
1831
0
            None => Err(TiffError::FormatError(
1832
0
                TiffFormatError::RequiredTagNotFound(tag),
1833
0
            )),
1834
        }
1835
0
    }
1836
1837
    /// Tries to retrieve a tag and convert it to the desired type.
1838
0
    pub fn get_tag_u32(&mut self, tag: Tag) -> TiffResult<u32> {
1839
0
        self.get_tag(tag)?.into_u32()
1840
0
    }
1841
1842
0
    pub fn get_tag_u64(&mut self, tag: Tag) -> TiffResult<u64> {
1843
0
        self.get_tag(tag)?.into_u64()
1844
0
    }
1845
1846
    /// Tries to retrieve a tag and convert it to the desired type.
1847
0
    pub fn get_tag_f32(&mut self, tag: Tag) -> TiffResult<f32> {
1848
0
        self.get_tag(tag)?.into_f32()
1849
0
    }
1850
1851
    /// Tries to retrieve a tag and convert it to the desired type.
1852
0
    pub fn get_tag_f64(&mut self, tag: Tag) -> TiffResult<f64> {
1853
0
        self.get_tag(tag)?.into_f64()
1854
0
    }
1855
1856
    /// Tries to retrieve a tag and convert it to the desired type.
1857
0
    pub fn get_tag_u32_vec(&mut self, tag: Tag) -> TiffResult<Vec<u32>> {
1858
0
        self.get_tag(tag)?.into_u32_vec()
1859
0
    }
1860
1861
0
    pub fn get_tag_u16_vec(&mut self, tag: Tag) -> TiffResult<Vec<u16>> {
1862
0
        self.get_tag(tag)?.into_u16_vec()
1863
0
    }
1864
1865
0
    pub fn get_tag_u64_vec(&mut self, tag: Tag) -> TiffResult<Vec<u64>> {
1866
0
        self.get_tag(tag)?.into_u64_vec()
1867
0
    }
1868
1869
    /// Tries to retrieve a tag and convert it to the desired type.
1870
0
    pub fn get_tag_f32_vec(&mut self, tag: Tag) -> TiffResult<Vec<f32>> {
1871
0
        self.get_tag(tag)?.into_f32_vec()
1872
0
    }
1873
1874
    /// Tries to retrieve a tag and convert it to the desired type.
1875
0
    pub fn get_tag_f64_vec(&mut self, tag: Tag) -> TiffResult<Vec<f64>> {
1876
0
        self.get_tag(tag)?.into_f64_vec()
1877
0
    }
1878
1879
    /// Tries to retrieve a tag and convert it to a 8bit vector.
1880
0
    pub fn get_tag_u8_vec(&mut self, tag: Tag) -> TiffResult<Vec<u8>> {
1881
0
        self.get_tag(tag)?.into_u8_vec()
1882
0
    }
1883
1884
    /// Tries to retrieve a tag and convert it to a ascii vector.
1885
0
    pub fn get_tag_ascii_string(&mut self, tag: Tag) -> TiffResult<String> {
1886
0
        self.get_tag(tag)?.into_string()
1887
0
    }
1888
1889
    /// Inspect the raw underlying directory.
1890
0
    pub fn directory(&self) -> &Directory {
1891
0
        self.inner.ifd
1892
0
    }
1893
}
1894
1895
impl<'l> IfdDecoder<'l> {
1896
    /// Returns an iterator over all tags in the current image, along with their values.
1897
0
    pub fn tag_iter(self) -> impl Iterator<Item = TiffResult<(Tag, ifd::Value)>> + 'l {
1898
0
        self.inner
1899
0
            .ifd
1900
0
            .iter()
1901
0
            .map(|(tag, entry)| match self.inner.decoder.entry_val(entry) {
1902
0
                Ok(value) => Ok((tag, value)),
1903
0
                Err(err) => Err(err),
1904
0
            })
1905
0
    }
1906
}
1907
1908
#[cfg(test)]
1909
mod tests {
1910
    use super::Decoder;
1911
    use crate::{
1912
        bytecast,
1913
        tags::{ByteOrder, Tag, ValueBuffer},
1914
    };
1915
1916
    #[test]
1917
    fn equivalence_of_tag_readers() {
1918
        let file = std::fs::File::open(concat!(
1919
            env!("CARGO_MANIFEST_DIR"),
1920
            "/tests/images/int8_rgb.tif"
1921
        ))
1922
        .unwrap();
1923
1924
        let mut decoder = Decoder::new(file).unwrap();
1925
        let file_bo = decoder.byte_order();
1926
        let mut ifd = decoder.image_ifd();
1927
1928
        {
1929
            let value = ifd
1930
                .find_tag(Tag::BitsPerSample)
1931
                .unwrap()
1932
                .expect("must have BitsPerSample");
1933
1934
            let samples = value.into_u16_vec().unwrap();
1935
            assert_eq!(samples.as_slice(), [8, 8, 8]);
1936
        }
1937
1938
        {
1939
            let mut value = ValueBuffer::from_value(&[0u16; 4]);
1940
            let _entry = ifd
1941
                .find_tag_buf(Tag::BitsPerSample, &mut value)
1942
                .unwrap()
1943
                .expect("must have BitsPerSample");
1944
1945
            value.set_byte_order(ByteOrder::native());
1946
            assert_eq!(value.as_bytes(), bytecast::u16_as_ne_bytes(&[8, 8, 8]));
1947
        }
1948
1949
        {
1950
            let mut by_bytes = [0u16; 4];
1951
            let entry = ifd
1952
                .find_entry(Tag::BitsPerSample)
1953
                .expect("must have BitsPerSample");
1954
1955
            let byte_len = ifd
1956
                .find_tag_bytes(
1957
                    Tag::BitsPerSample,
1958
                    bytecast::u16_as_ne_mut_bytes(&mut by_bytes),
1959
                    0,
1960
                )
1961
                .unwrap()
1962
                .expect("must have BitsPerSample");
1963
            assert_eq!(byte_len, 3 * std::mem::size_of::<u16>());
1964
1965
            file_bo.convert(
1966
                entry.field_type(),
1967
                bytecast::u16_as_ne_mut_bytes(&mut by_bytes[..3]),
1968
                ByteOrder::native(),
1969
            );
1970
            assert_eq!(&by_bytes[..3], &[8, 8, 8]);
1971
        }
1972
    }
1973
}