tiff/decoder/
mod.rs

1use std::alloc::{Layout, LayoutError};
2use std::collections::BTreeMap;
3use std::io::{self, Read, Seek};
4use std::num::NonZeroUsize;
5
6use crate::tags::{
7    CompressionMethod, IfdPointer, PhotometricInterpretation, PlanarConfiguration, Predictor,
8    SampleFormat, Tag, Type,
9};
10use crate::{
11    bytecast, ColorType, Directory, TiffError, TiffFormatError, TiffResult, TiffUnsupportedError,
12    UsageError,
13};
14use half::f16;
15
16use self::image::Image;
17use self::stream::{ByteOrder, EndianReader};
18
19mod cycles;
20pub mod ifd;
21mod image;
22mod stream;
23mod tag_reader;
24
25/// Result of a decoding process
26#[derive(Debug)]
27pub enum DecodingResult {
28    /// A vector of unsigned bytes
29    U8(Vec<u8>),
30    /// A vector of unsigned words
31    U16(Vec<u16>),
32    /// A vector of 32 bit unsigned ints
33    U32(Vec<u32>),
34    /// A vector of 64 bit unsigned ints
35    U64(Vec<u64>),
36    /// A vector of 16 bit IEEE floats (held in u16)
37    F16(Vec<f16>),
38    /// A vector of 32 bit IEEE floats
39    F32(Vec<f32>),
40    /// A vector of 64 bit IEEE floats
41    F64(Vec<f64>),
42    /// A vector of 8 bit signed ints
43    I8(Vec<i8>),
44    /// A vector of 16 bit signed ints
45    I16(Vec<i16>),
46    /// A vector of 32 bit signed ints
47    I32(Vec<i32>),
48    /// A vector of 64 bit signed ints
49    I64(Vec<i64>),
50}
51
52impl DecodingResult {
53    fn new_u8(size: usize, limits: &Limits) -> TiffResult<DecodingResult> {
54        if size > limits.decoding_buffer_size {
55            Err(TiffError::LimitsExceeded)
56        } else {
57            Ok(DecodingResult::U8(vec![0; size]))
58        }
59    }
60
61    fn new_u16(size: usize, limits: &Limits) -> TiffResult<DecodingResult> {
62        if size > limits.decoding_buffer_size / 2 {
63            Err(TiffError::LimitsExceeded)
64        } else {
65            Ok(DecodingResult::U16(vec![0; size]))
66        }
67    }
68
69    fn new_u32(size: usize, limits: &Limits) -> TiffResult<DecodingResult> {
70        if size > limits.decoding_buffer_size / 4 {
71            Err(TiffError::LimitsExceeded)
72        } else {
73            Ok(DecodingResult::U32(vec![0; size]))
74        }
75    }
76
77    fn new_u64(size: usize, limits: &Limits) -> TiffResult<DecodingResult> {
78        if size > limits.decoding_buffer_size / 8 {
79            Err(TiffError::LimitsExceeded)
80        } else {
81            Ok(DecodingResult::U64(vec![0; size]))
82        }
83    }
84
85    fn new_f32(size: usize, limits: &Limits) -> TiffResult<DecodingResult> {
86        if size > limits.decoding_buffer_size / std::mem::size_of::<f32>() {
87            Err(TiffError::LimitsExceeded)
88        } else {
89            Ok(DecodingResult::F32(vec![0.0; size]))
90        }
91    }
92
93    fn new_f64(size: usize, limits: &Limits) -> TiffResult<DecodingResult> {
94        if size > limits.decoding_buffer_size / std::mem::size_of::<f64>() {
95            Err(TiffError::LimitsExceeded)
96        } else {
97            Ok(DecodingResult::F64(vec![0.0; size]))
98        }
99    }
100
101    fn new_f16(size: usize, limits: &Limits) -> TiffResult<DecodingResult> {
102        if size > limits.decoding_buffer_size / std::mem::size_of::<u16>() {
103            Err(TiffError::LimitsExceeded)
104        } else {
105            Ok(DecodingResult::F16(vec![f16::ZERO; size]))
106        }
107    }
108
109    fn new_i8(size: usize, limits: &Limits) -> TiffResult<DecodingResult> {
110        if size > limits.decoding_buffer_size / std::mem::size_of::<i8>() {
111            Err(TiffError::LimitsExceeded)
112        } else {
113            Ok(DecodingResult::I8(vec![0; size]))
114        }
115    }
116
117    fn new_i16(size: usize, limits: &Limits) -> TiffResult<DecodingResult> {
118        if size > limits.decoding_buffer_size / 2 {
119            Err(TiffError::LimitsExceeded)
120        } else {
121            Ok(DecodingResult::I16(vec![0; size]))
122        }
123    }
124
125    fn new_i32(size: usize, limits: &Limits) -> TiffResult<DecodingResult> {
126        if size > limits.decoding_buffer_size / 4 {
127            Err(TiffError::LimitsExceeded)
128        } else {
129            Ok(DecodingResult::I32(vec![0; size]))
130        }
131    }
132
133    fn new_i64(size: usize, limits: &Limits) -> TiffResult<DecodingResult> {
134        if size > limits.decoding_buffer_size / 8 {
135            Err(TiffError::LimitsExceeded)
136        } else {
137            Ok(DecodingResult::I64(vec![0; size]))
138        }
139    }
140
141    pub fn as_buffer(&mut self, start: usize) -> DecodingBuffer<'_> {
142        match *self {
143            DecodingResult::U8(ref mut buf) => DecodingBuffer::U8(&mut buf[start..]),
144            DecodingResult::U16(ref mut buf) => DecodingBuffer::U16(&mut buf[start..]),
145            DecodingResult::U32(ref mut buf) => DecodingBuffer::U32(&mut buf[start..]),
146            DecodingResult::U64(ref mut buf) => DecodingBuffer::U64(&mut buf[start..]),
147            DecodingResult::F16(ref mut buf) => DecodingBuffer::F16(&mut buf[start..]),
148            DecodingResult::F32(ref mut buf) => DecodingBuffer::F32(&mut buf[start..]),
149            DecodingResult::F64(ref mut buf) => DecodingBuffer::F64(&mut buf[start..]),
150            DecodingResult::I8(ref mut buf) => DecodingBuffer::I8(&mut buf[start..]),
151            DecodingResult::I16(ref mut buf) => DecodingBuffer::I16(&mut buf[start..]),
152            DecodingResult::I32(ref mut buf) => DecodingBuffer::I32(&mut buf[start..]),
153            DecodingResult::I64(ref mut buf) => DecodingBuffer::I64(&mut buf[start..]),
154        }
155    }
156}
157
158// A buffer for image decoding
159pub enum DecodingBuffer<'a> {
160    /// A slice of unsigned bytes
161    U8(&'a mut [u8]),
162    /// A slice of unsigned words
163    U16(&'a mut [u16]),
164    /// A slice of 32 bit unsigned ints
165    U32(&'a mut [u32]),
166    /// A slice of 64 bit unsigned ints
167    U64(&'a mut [u64]),
168    /// A slice of 16 bit IEEE floats
169    F16(&'a mut [f16]),
170    /// A slice of 32 bit IEEE floats
171    F32(&'a mut [f32]),
172    /// A slice of 64 bit IEEE floats
173    F64(&'a mut [f64]),
174    /// A slice of 8 bits signed ints
175    I8(&'a mut [i8]),
176    /// A slice of 16 bits signed ints
177    I16(&'a mut [i16]),
178    /// A slice of 32 bits signed ints
179    I32(&'a mut [i32]),
180    /// A slice of 64 bits signed ints
181    I64(&'a mut [i64]),
182}
183
184impl<'a> DecodingBuffer<'a> {
185    fn as_bytes_mut(&mut self) -> &mut [u8] {
186        match self {
187            DecodingBuffer::U8(ref mut buf) => buf,
188            DecodingBuffer::I8(buf) => bytecast::i8_as_ne_mut_bytes(buf),
189            DecodingBuffer::U16(buf) => bytecast::u16_as_ne_mut_bytes(buf),
190            DecodingBuffer::I16(buf) => bytecast::i16_as_ne_mut_bytes(buf),
191            DecodingBuffer::U32(buf) => bytecast::u32_as_ne_mut_bytes(buf),
192            DecodingBuffer::I32(buf) => bytecast::i32_as_ne_mut_bytes(buf),
193            DecodingBuffer::U64(buf) => bytecast::u64_as_ne_mut_bytes(buf),
194            DecodingBuffer::I64(buf) => bytecast::i64_as_ne_mut_bytes(buf),
195            DecodingBuffer::F16(buf) => bytecast::f16_as_ne_mut_bytes(buf),
196            DecodingBuffer::F32(buf) => bytecast::f32_as_ne_mut_bytes(buf),
197            DecodingBuffer::F64(buf) => bytecast::f64_as_ne_mut_bytes(buf),
198        }
199    }
200}
201
202/// Information on the byte buffer that should be supplied to the decoder.
203///
204/// This is relevant for [`Decoder::read_image_bytes`] and [`Decoder::read_chunk_bytes`] where the
205/// caller provided buffer must fit the expectations of the decoder to be filled with data from the
206/// current image.
207#[non_exhaustive]
208pub struct BufferLayoutPreference {
209    /// Minimum byte size of the buffer to read image data.
210    pub len: usize,
211    /// Minimum number of bytes to represent a row of image data of the requested content.
212    pub row_stride: Option<NonZeroUsize>,
213}
214
215/// The count and matching discriminant for a `DecodingBuffer`.
216#[derive(Clone)]
217enum DecodingExtent {
218    U8(usize),
219    U16(usize),
220    U32(usize),
221    U64(usize),
222    F16(usize),
223    F32(usize),
224    F64(usize),
225    I8(usize),
226    I16(usize),
227    I32(usize),
228    I64(usize),
229}
230
231impl DecodingExtent {
232    fn to_result_buffer(&self, limits: &Limits) -> TiffResult<DecodingResult> {
233        match *self {
234            DecodingExtent::U8(count) => DecodingResult::new_u8(count, limits),
235            DecodingExtent::U16(count) => DecodingResult::new_u16(count, limits),
236            DecodingExtent::U32(count) => DecodingResult::new_u32(count, limits),
237            DecodingExtent::U64(count) => DecodingResult::new_u64(count, limits),
238            DecodingExtent::F16(count) => DecodingResult::new_f16(count, limits),
239            DecodingExtent::F32(count) => DecodingResult::new_f32(count, limits),
240            DecodingExtent::F64(count) => DecodingResult::new_f64(count, limits),
241            DecodingExtent::I8(count) => DecodingResult::new_i8(count, limits),
242            DecodingExtent::I16(count) => DecodingResult::new_i16(count, limits),
243            DecodingExtent::I32(count) => DecodingResult::new_i32(count, limits),
244            DecodingExtent::I64(count) => DecodingResult::new_i64(count, limits),
245        }
246    }
247
248    fn preferred_layout(self) -> TiffResult<Layout> {
249        fn overflow(_: LayoutError) -> TiffError {
250            TiffError::LimitsExceeded
251        }
252
253        match self {
254            DecodingExtent::U8(count) => Layout::array::<u8>(count),
255            DecodingExtent::U16(count) => Layout::array::<u16>(count),
256            DecodingExtent::U32(count) => Layout::array::<u32>(count),
257            DecodingExtent::U64(count) => Layout::array::<u64>(count),
258            DecodingExtent::F16(count) => Layout::array::<f16>(count),
259            DecodingExtent::F32(count) => Layout::array::<f32>(count),
260            DecodingExtent::F64(count) => Layout::array::<f64>(count),
261            DecodingExtent::I8(count) => Layout::array::<i8>(count),
262            DecodingExtent::I16(count) => Layout::array::<i16>(count),
263            DecodingExtent::I32(count) => Layout::array::<i32>(count),
264            DecodingExtent::I64(count) => Layout::array::<i64>(count),
265        }
266        .map_err(overflow)
267    }
268
269    fn assert_layout(self, buffer: usize) -> TiffResult<()> {
270        let needed_bytes = self.preferred_layout()?.size();
271        if buffer < needed_bytes {
272            Err(TiffError::UsageError(
273                UsageError::InsufficientOutputBufferSize {
274                    needed: needed_bytes,
275                    provided: buffer,
276                },
277            ))
278        } else {
279            Ok(())
280        }
281    }
282}
283
284#[derive(Debug, Copy, Clone, PartialEq)]
285/// Chunk type of the internal representation
286pub enum ChunkType {
287    Strip,
288    Tile,
289}
290
291/// Decoding limits
292#[derive(Clone, Debug)]
293#[non_exhaustive]
294pub struct Limits {
295    /// The maximum size of any `DecodingResult` in bytes, the default is
296    /// 256MiB. If the entire image is decoded at once, then this will
297    /// be the maximum size of the image. If it is decoded one strip at a
298    /// time, this will be the maximum size of a strip.
299    pub decoding_buffer_size: usize,
300    /// The maximum size of any ifd value in bytes, the default is
301    /// 1MiB.
302    pub ifd_value_size: usize,
303    /// Maximum size for intermediate buffer which may be used to limit the amount of data read per
304    /// segment even if the entire image is decoded at once.
305    pub intermediate_buffer_size: usize,
306}
307
308impl Limits {
309    /// A configuration that does not impose any limits.
310    ///
311    /// This is a good start if the caller only wants to impose selective limits, contrary to the
312    /// default limits which allows selectively disabling limits.
313    ///
314    /// Note that this configuration is likely to crash on excessively large images since,
315    /// naturally, the machine running the program does not have infinite memory.
316    pub fn unlimited() -> Limits {
317        Limits {
318            decoding_buffer_size: usize::MAX,
319            ifd_value_size: usize::MAX,
320            intermediate_buffer_size: usize::MAX,
321        }
322    }
323}
324
325impl Default for Limits {
326    fn default() -> Limits {
327        Limits {
328            decoding_buffer_size: 256 * 1024 * 1024,
329            intermediate_buffer_size: 128 * 1024 * 1024,
330            ifd_value_size: 1024 * 1024,
331        }
332    }
333}
334
335/// The representation of a TIFF decoder
336///
337/// Currently does not support decoding of interlaced images
338#[derive(Debug)]
339pub struct Decoder<R>
340where
341    R: Read + Seek,
342{
343    /// There are grouped for borrow checker reasons. This allows us to implement methods that
344    /// borrow the stream access and the other fields mutably at the same time.
345    value_reader: ValueReader<R>,
346    current_ifd: Option<IfdPointer>,
347    next_ifd: Option<IfdPointer>,
348    /// The IFDs we visited already in this chain of IFDs.
349    ifd_offsets: Vec<IfdPointer>,
350    /// Map from the ifd into the `ifd_offsets` ordered list.
351    seen_ifds: cycles::IfdCycles,
352    image: Image,
353}
354
355/// All the information needed to read and interpret byte slices from the underlying file, i.e. to
356/// turn an entry of a tag into an `ifd::Value` or otherwise fetch arrays of similar types. Used
357/// only as the type of the field [`Decoder::value_reader`] and passed to submodules.
358#[derive(Debug)]
359struct ValueReader<R> {
360    reader: EndianReader<R>,
361    bigtiff: bool,
362    limits: Limits,
363}
364
365/// Reads a directory's tag values from an underlying stream.
366pub struct IfdDecoder<'lt> {
367    inner: tag_reader::TagReader<'lt, dyn tag_reader::EntryDecoder + 'lt>,
368}
369
370fn rev_hpredict_nsamp(buf: &mut [u8], bit_depth: u8, samples: usize) {
371    match bit_depth {
372        0..=8 => {
373            for i in samples..buf.len() {
374                buf[i] = buf[i].wrapping_add(buf[i - samples]);
375            }
376        }
377        9..=16 => {
378            for i in (samples * 2..buf.len()).step_by(2) {
379                let v = u16::from_ne_bytes(buf[i..][..2].try_into().unwrap());
380                let p = u16::from_ne_bytes(buf[i - 2 * samples..][..2].try_into().unwrap());
381                buf[i..][..2].copy_from_slice(&(v.wrapping_add(p)).to_ne_bytes());
382            }
383        }
384        17..=32 => {
385            for i in (samples * 4..buf.len()).step_by(4) {
386                let v = u32::from_ne_bytes(buf[i..][..4].try_into().unwrap());
387                let p = u32::from_ne_bytes(buf[i - 4 * samples..][..4].try_into().unwrap());
388                buf[i..][..4].copy_from_slice(&(v.wrapping_add(p)).to_ne_bytes());
389            }
390        }
391        33..=64 => {
392            for i in (samples * 8..buf.len()).step_by(8) {
393                let v = u64::from_ne_bytes(buf[i..][..8].try_into().unwrap());
394                let p = u64::from_ne_bytes(buf[i - 8 * samples..][..8].try_into().unwrap());
395                buf[i..][..8].copy_from_slice(&(v.wrapping_add(p)).to_ne_bytes());
396            }
397        }
398        _ => {
399            unreachable!("Caller should have validated arguments. Please file a bug.")
400        }
401    }
402}
403
404fn predict_f32(input: &mut [u8], output: &mut [u8], samples: usize) {
405    for i in samples..input.len() {
406        input[i] = input[i].wrapping_add(input[i - samples]);
407    }
408
409    for (i, chunk) in output.chunks_mut(4).enumerate() {
410        chunk.copy_from_slice(&u32::to_ne_bytes(u32::from_be_bytes([
411            input[i],
412            input[input.len() / 4 + i],
413            input[input.len() / 4 * 2 + i],
414            input[input.len() / 4 * 3 + i],
415        ])));
416    }
417}
418
419fn predict_f16(input: &mut [u8], output: &mut [u8], samples: usize) {
420    for i in samples..input.len() {
421        input[i] = input[i].wrapping_add(input[i - samples]);
422    }
423
424    for (i, chunk) in output.chunks_mut(2).enumerate() {
425        chunk.copy_from_slice(&u16::to_ne_bytes(u16::from_be_bytes([
426            input[i],
427            input[input.len() / 2 + i],
428        ])));
429    }
430}
431
432fn predict_f64(input: &mut [u8], output: &mut [u8], samples: usize) {
433    for i in samples..input.len() {
434        input[i] = input[i].wrapping_add(input[i - samples]);
435    }
436
437    for (i, chunk) in output.chunks_mut(8).enumerate() {
438        chunk.copy_from_slice(&u64::to_ne_bytes(u64::from_be_bytes([
439            input[i],
440            input[input.len() / 8 + i],
441            input[input.len() / 8 * 2 + i],
442            input[input.len() / 8 * 3 + i],
443            input[input.len() / 8 * 4 + i],
444            input[input.len() / 8 * 5 + i],
445            input[input.len() / 8 * 6 + i],
446            input[input.len() / 8 * 7 + i],
447        ])));
448    }
449}
450
451fn fix_endianness_and_predict(
452    buf: &mut [u8],
453    bit_depth: u8,
454    samples: usize,
455    byte_order: ByteOrder,
456    predictor: Predictor,
457) {
458    match predictor {
459        Predictor::None => {
460            fix_endianness(buf, byte_order, bit_depth);
461        }
462        Predictor::Horizontal => {
463            fix_endianness(buf, byte_order, bit_depth);
464            rev_hpredict_nsamp(buf, bit_depth, samples);
465        }
466        Predictor::FloatingPoint => {
467            let mut buffer_copy = buf.to_vec();
468            match bit_depth {
469                16 => predict_f16(&mut buffer_copy, buf, samples),
470                32 => predict_f32(&mut buffer_copy, buf, samples),
471                64 => predict_f64(&mut buffer_copy, buf, samples),
472                _ => unreachable!("Caller should have validated arguments. Please file a bug."),
473            }
474        }
475    }
476}
477
478fn invert_colors(
479    buf: &mut [u8],
480    color_type: ColorType,
481    sample_format: SampleFormat,
482) -> TiffResult<()> {
483    match (color_type, sample_format) {
484        // Where pixels do not cross a byte boundary
485        (ColorType::Gray(1 | 2 | 4 | 8), SampleFormat::Uint) => {
486            for x in buf {
487                // Equivalent to both of the following:
488                //
489                // *x = 0xff - *x
490                // *x = !*x
491                //
492                // since -x = !x+1
493                *x = !*x;
494            }
495        }
496        (ColorType::Gray(16), SampleFormat::Uint) => {
497            for x in buf.chunks_mut(2) {
498                let v = u16::from_ne_bytes(x.try_into().unwrap());
499                x.copy_from_slice(&(0xffff - v).to_ne_bytes());
500            }
501        }
502        (ColorType::Gray(32), SampleFormat::Uint) => {
503            for x in buf.chunks_mut(4) {
504                let v = u32::from_ne_bytes(x.try_into().unwrap());
505                x.copy_from_slice(&(0xffff_ffff - v).to_ne_bytes());
506            }
507        }
508        (ColorType::Gray(64), SampleFormat::Uint) => {
509            for x in buf.chunks_mut(8) {
510                let v = u64::from_ne_bytes(x.try_into().unwrap());
511                x.copy_from_slice(&(0xffff_ffff_ffff_ffff - v).to_ne_bytes());
512            }
513        }
514        (ColorType::Gray(32), SampleFormat::IEEEFP) => {
515            for x in buf.chunks_mut(4) {
516                let v = f32::from_ne_bytes(x.try_into().unwrap());
517                x.copy_from_slice(&(1.0 - v).to_ne_bytes());
518            }
519        }
520        (ColorType::Gray(64), SampleFormat::IEEEFP) => {
521            for x in buf.chunks_mut(8) {
522                let v = f64::from_ne_bytes(x.try_into().unwrap());
523                x.copy_from_slice(&(1.0 - v).to_ne_bytes());
524            }
525        }
526        _ => {
527            return Err(TiffError::UnsupportedError(
528                TiffUnsupportedError::UnknownInterpretation,
529            ))
530        }
531    }
532
533    Ok(())
534}
535
536/// Fix endianness. If `byte_order` matches the host, then conversion is a no-op.
537fn fix_endianness(buf: &mut [u8], byte_order: ByteOrder, bit_depth: u8) {
538    match byte_order {
539        ByteOrder::LittleEndian => match bit_depth {
540            0..=8 => {}
541            9..=16 => buf.chunks_exact_mut(2).for_each(|v| {
542                v.copy_from_slice(&u16::from_le_bytes((*v).try_into().unwrap()).to_ne_bytes())
543            }),
544            17..=32 => buf.chunks_exact_mut(4).for_each(|v| {
545                v.copy_from_slice(&u32::from_le_bytes((*v).try_into().unwrap()).to_ne_bytes())
546            }),
547            _ => buf.chunks_exact_mut(8).for_each(|v| {
548                v.copy_from_slice(&u64::from_le_bytes((*v).try_into().unwrap()).to_ne_bytes())
549            }),
550        },
551        ByteOrder::BigEndian => match bit_depth {
552            0..=8 => {}
553            9..=16 => buf.chunks_exact_mut(2).for_each(|v| {
554                v.copy_from_slice(&u16::from_be_bytes((*v).try_into().unwrap()).to_ne_bytes())
555            }),
556            17..=32 => buf.chunks_exact_mut(4).for_each(|v| {
557                v.copy_from_slice(&u32::from_be_bytes((*v).try_into().unwrap()).to_ne_bytes())
558            }),
559            _ => buf.chunks_exact_mut(8).for_each(|v| {
560                v.copy_from_slice(&u64::from_be_bytes((*v).try_into().unwrap()).to_ne_bytes())
561            }),
562        },
563    };
564}
565
566impl<R: Read + Seek> Decoder<R> {
567    pub fn new(mut r: R) -> TiffResult<Decoder<R>> {
568        let mut endianess = Vec::with_capacity(2);
569        (&mut r).take(2).read_to_end(&mut endianess)?;
570        let byte_order = match &*endianess {
571            b"II" => ByteOrder::LittleEndian,
572            b"MM" => ByteOrder::BigEndian,
573            _ => {
574                return Err(TiffError::FormatError(
575                    TiffFormatError::TiffSignatureNotFound,
576                ))
577            }
578        };
579        let mut reader = EndianReader::new(r, byte_order);
580
581        let bigtiff = match reader.read_u16()? {
582            42 => false,
583            43 => {
584                // Read bytesize of offsets (in bigtiff it's alway 8 but provide a way to move to 16 some day)
585                if reader.read_u16()? != 8 {
586                    return Err(TiffError::FormatError(
587                        TiffFormatError::TiffSignatureNotFound,
588                    ));
589                }
590                // This constant should always be 0
591                if reader.read_u16()? != 0 {
592                    return Err(TiffError::FormatError(
593                        TiffFormatError::TiffSignatureNotFound,
594                    ));
595                }
596                true
597            }
598            _ => {
599                return Err(TiffError::FormatError(
600                    TiffFormatError::TiffSignatureInvalid,
601                ))
602            }
603        };
604
605        let next_ifd = if bigtiff {
606            Some(reader.read_u64()?)
607        } else {
608            Some(u64::from(reader.read_u32()?))
609        }
610        .map(IfdPointer);
611
612        let current_ifd = *next_ifd.as_ref().unwrap();
613        let ifd_offsets = vec![current_ifd];
614
615        let mut decoder = Decoder {
616            value_reader: ValueReader {
617                reader,
618                bigtiff,
619                limits: Default::default(),
620            },
621            next_ifd,
622            ifd_offsets,
623            current_ifd: None,
624            seen_ifds: cycles::IfdCycles::new(),
625            image: Image {
626                ifd: None,
627                width: 0,
628                height: 0,
629                bits_per_sample: 1,
630                samples: 1,
631                sample_format: SampleFormat::Uint,
632                photometric_interpretation: PhotometricInterpretation::BlackIsZero,
633                compression_method: CompressionMethod::None,
634                jpeg_tables: None,
635                predictor: Predictor::None,
636                chunk_type: ChunkType::Strip,
637                planar_config: PlanarConfiguration::Chunky,
638                strip_decoder: None,
639                tile_attributes: None,
640                chunk_offsets: Vec::new(),
641                chunk_bytes: Vec::new(),
642            },
643        };
644        decoder.next_image()?;
645        Ok(decoder)
646    }
647
648    pub fn with_limits(mut self, limits: Limits) -> Decoder<R> {
649        self.value_reader.limits = limits;
650        self
651    }
652
653    pub fn dimensions(&mut self) -> TiffResult<(u32, u32)> {
654        Ok((self.image().width, self.image().height))
655    }
656
657    pub fn colortype(&mut self) -> TiffResult<ColorType> {
658        self.image().colortype()
659    }
660
661    /// The offset of the directory representing the current image.
662    pub fn ifd_pointer(&mut self) -> Option<IfdPointer> {
663        self.current_ifd
664    }
665
666    fn image(&self) -> &Image {
667        &self.image
668    }
669
670    /// Loads the IFD at the specified index in the list, if one exists
671    pub fn seek_to_image(&mut self, ifd_index: usize) -> TiffResult<()> {
672        // 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
673        if ifd_index >= self.ifd_offsets.len() {
674            // We possibly need to load in the next IFD
675            if self.next_ifd.is_none() {
676                self.current_ifd = None;
677
678                return Err(TiffError::FormatError(
679                    TiffFormatError::ImageFileDirectoryNotFound,
680                ));
681            }
682
683            loop {
684                // Follow the list until we find the one we want, or we reach the end, whichever happens first
685                let ifd = self.next_ifd()?;
686
687                if ifd.next().is_none() {
688                    break;
689                }
690
691                if ifd_index < self.ifd_offsets.len() {
692                    break;
693                }
694            }
695        }
696
697        // If the index is within the list of ifds then we can load the selected image/IFD
698        if let Some(ifd_offset) = self.ifd_offsets.get(ifd_index) {
699            let ifd = self.value_reader.read_directory(*ifd_offset)?;
700            self.next_ifd = ifd.next();
701            self.current_ifd = Some(*ifd_offset);
702            self.image = Image::from_reader(&mut self.value_reader, ifd)?;
703
704            Ok(())
705        } else {
706            Err(TiffError::FormatError(
707                TiffFormatError::ImageFileDirectoryNotFound,
708            ))
709        }
710    }
711
712    fn next_ifd(&mut self) -> TiffResult<Directory> {
713        let Some(next_ifd) = self.next_ifd.take() else {
714            return Err(TiffError::FormatError(
715                TiffFormatError::ImageFileDirectoryNotFound,
716            ));
717        };
718
719        let ifd = self.value_reader.read_directory(next_ifd)?;
720
721        // Ensure this walk does not get us into a cycle.
722        self.seen_ifds.insert_next(next_ifd, ifd.next())?;
723
724        // Extend the list of known IFD offsets in this chain, if needed.
725        if self.ifd_offsets.last().copied() == self.current_ifd {
726            self.ifd_offsets.push(next_ifd);
727        }
728
729        self.current_ifd = Some(next_ifd);
730        self.next_ifd = ifd.next();
731
732        Ok(ifd)
733    }
734
735    /// Reads in the next image.
736    /// If there is no further image in the TIFF file a format error is returned.
737    /// To determine whether there are more images call `TIFFDecoder::more_images` instead.
738    pub fn next_image(&mut self) -> TiffResult<()> {
739        let ifd = self.next_ifd()?;
740        self.image = Image::from_reader(&mut self.value_reader, ifd)?;
741        Ok(())
742    }
743
744    /// Returns `true` if there is at least one more image available.
745    pub fn more_images(&self) -> bool {
746        self.next_ifd.is_some()
747    }
748
749    /// Returns the byte_order of the file.
750    pub fn byte_order(&self) -> ByteOrder {
751        self.value_reader.reader.byte_order
752    }
753
754    #[inline]
755    pub fn read_ifd_offset(&mut self) -> Result<u64, io::Error> {
756        if self.value_reader.bigtiff {
757            self.read_long8()
758        } else {
759            self.read_long().map(u64::from)
760        }
761    }
762
763    /// Returns a mutable reference to the stream being decoded.
764    pub fn inner(&mut self) -> &mut R {
765        self.value_reader.reader.inner()
766    }
767
768    /// Reads a TIFF byte value
769    #[inline]
770    pub fn read_byte(&mut self) -> Result<u8, io::Error> {
771        let mut buf = [0; 1];
772        self.value_reader.reader.inner().read_exact(&mut buf)?;
773        Ok(buf[0])
774    }
775
776    /// Reads a TIFF short value
777    #[inline]
778    pub fn read_short(&mut self) -> Result<u16, io::Error> {
779        self.value_reader.reader.read_u16()
780    }
781
782    /// Reads a TIFF sshort value
783    #[inline]
784    pub fn read_sshort(&mut self) -> Result<i16, io::Error> {
785        self.value_reader.reader.read_i16()
786    }
787
788    /// Reads a TIFF long value
789    #[inline]
790    pub fn read_long(&mut self) -> Result<u32, io::Error> {
791        self.value_reader.reader.read_u32()
792    }
793
794    /// Reads a TIFF slong value
795    #[inline]
796    pub fn read_slong(&mut self) -> Result<i32, io::Error> {
797        self.value_reader.reader.read_i32()
798    }
799
800    /// Reads a TIFF float value
801    #[inline]
802    pub fn read_float(&mut self) -> Result<f32, io::Error> {
803        self.value_reader.reader.read_f32()
804    }
805
806    /// Reads a TIFF double value
807    #[inline]
808    pub fn read_double(&mut self) -> Result<f64, io::Error> {
809        self.value_reader.reader.read_f64()
810    }
811
812    #[inline]
813    pub fn read_long8(&mut self) -> Result<u64, io::Error> {
814        self.value_reader.reader.read_u64()
815    }
816
817    #[inline]
818    pub fn read_slong8(&mut self) -> Result<i64, io::Error> {
819        self.value_reader.reader.read_i64()
820    }
821
822    /// Reads a string
823    #[inline]
824    pub fn read_string(&mut self, length: usize) -> TiffResult<String> {
825        let mut out = vec![0; length];
826        self.value_reader.reader.inner().read_exact(&mut out)?;
827        // Strings may be null-terminated, so we trim anything downstream of the null byte
828        if let Some(first) = out.iter().position(|&b| b == 0) {
829            out.truncate(first);
830        }
831        Ok(String::from_utf8(out)?)
832    }
833
834    /// Reads a TIFF IFA offset/value field
835    #[inline]
836    pub fn read_offset(&mut self) -> TiffResult<[u8; 4]> {
837        if self.value_reader.bigtiff {
838            return Err(TiffError::FormatError(
839                TiffFormatError::InconsistentSizesEncountered,
840            ));
841        }
842        let mut val = [0; 4];
843        self.value_reader.reader.inner().read_exact(&mut val)?;
844        Ok(val)
845    }
846
847    /// Reads a TIFF IFA offset/value field
848    #[inline]
849    pub fn read_offset_u64(&mut self) -> Result<[u8; 8], io::Error> {
850        let mut val = [0; 8];
851        self.value_reader.reader.inner().read_exact(&mut val)?;
852        Ok(val)
853    }
854
855    /// Moves the cursor to the specified offset
856    #[inline]
857    pub fn goto_offset(&mut self, offset: u32) -> io::Result<()> {
858        self.goto_offset_u64(offset.into())
859    }
860
861    #[inline]
862    pub fn goto_offset_u64(&mut self, offset: u64) -> io::Result<()> {
863        self.value_reader.reader.goto_offset(offset)
864    }
865
866    /// Read a tag-entry map from a known offset.
867    ///
868    /// A TIFF [`Directory`], aka. image file directory aka. IFD, refers to a map from
869    /// tags–identified by a `u16`–to a typed vector of elements. It is encoded as a list
870    /// of ascending tag values with the offset and type of their corresponding values. The
871    /// semantic interpretations of a tag and its type requirements depend on the context of the
872    /// directory. The main image directories, those iterated over by the `Decoder` after
873    /// construction, are represented by [`Tag`] and [`ifd::Value`]. Other forms are EXIF and GPS
874    /// data as well as thumbnail Sub-IFD representations associated with each image file.
875    ///
876    /// This method allows the decoding of a directory from an arbitrary offset in the image file
877    /// with no specific semantic interpretation. Such an offset is usually found as the value of
878    /// a tag, e.g. [`Tag::SubIfd`], [`Tag::ExifDirectory`], [`Tag::GpsDirectory`] and recovered
879    /// from the associated value by [`ifd::Value::into_ifd_pointer`].
880    ///
881    /// The library will not verify whether the offset overlaps any other directory or would form a
882    /// cycle with any other directory when calling this method. This will modify the position of
883    /// the reader, i.e. continuing with direct reads at a later point will require going back with
884    /// [`Self::goto_offset`].
885    pub fn read_directory(&mut self, ptr: IfdPointer) -> TiffResult<Directory> {
886        self.value_reader.read_directory(ptr)
887    }
888
889    fn check_chunk_type(&self, expected: ChunkType) -> TiffResult<()> {
890        if expected != self.image().chunk_type {
891            return Err(TiffError::UsageError(UsageError::InvalidChunkType(
892                expected,
893                self.image().chunk_type,
894            )));
895        }
896
897        Ok(())
898    }
899
900    /// The chunk type (Strips / Tiles) of the image
901    pub fn get_chunk_type(&self) -> ChunkType {
902        self.image().chunk_type
903    }
904
905    /// Number of strips in image
906    pub fn strip_count(&mut self) -> TiffResult<u32> {
907        self.check_chunk_type(ChunkType::Strip)?;
908        let rows_per_strip = self.image().strip_decoder.as_ref().unwrap().rows_per_strip;
909
910        if rows_per_strip == 0 {
911            return Ok(0);
912        }
913
914        // rows_per_strip - 1 can never fail since we know it's at least 1
915        let height = match self.image().height.checked_add(rows_per_strip - 1) {
916            Some(h) => h,
917            None => return Err(TiffError::IntSizeError),
918        };
919
920        let strips = match self.image().planar_config {
921            PlanarConfiguration::Chunky => height / rows_per_strip,
922            PlanarConfiguration::Planar => height / rows_per_strip * self.image().samples as u32,
923        };
924
925        Ok(strips)
926    }
927
928    /// Number of tiles in image
929    pub fn tile_count(&mut self) -> TiffResult<u32> {
930        self.check_chunk_type(ChunkType::Tile)?;
931        Ok(u32::try_from(self.image().chunk_offsets.len())?)
932    }
933
934    pub fn read_chunk_to_buffer(
935        &mut self,
936        mut buffer: DecodingBuffer,
937        chunk_index: u32,
938        output_width: usize,
939    ) -> TiffResult<()> {
940        let output_row_stride = (output_width as u64)
941            .saturating_mul(self.image.samples_per_pixel() as u64)
942            .saturating_mul(self.image.bits_per_sample as u64)
943            .div_ceil(8);
944
945        self.read_chunk_to_bytes(buffer.as_bytes_mut(), chunk_index, output_row_stride)
946    }
947
948    fn read_chunk_to_bytes(
949        &mut self,
950        buffer: &mut [u8],
951        chunk_index: u32,
952        output_row_stride: u64,
953    ) -> TiffResult<()> {
954        let offset = self.image.chunk_file_range(chunk_index)?.0;
955        self.goto_offset_u64(offset)?;
956
957        self.image.expand_chunk(
958            &mut self.value_reader,
959            buffer,
960            output_row_stride.try_into()?,
961            chunk_index,
962        )?;
963
964        Ok(())
965    }
966
967    fn result_buffer(&self, width: usize, height: usize) -> TiffResult<DecodingResult> {
968        self.result_extent(width, height)?
969            .to_result_buffer(&self.value_reader.limits)
970    }
971
972    // FIXME: it's unusual for this method to take a `usize` dimension parameter since those would
973    // typically come from the image data. The preferred consistent representation should be `u32`
974    // and that would avoid some unusual casts `usize -> u64` with a `u64::from` instead.
975    fn result_extent(&self, width: usize, height: usize) -> TiffResult<DecodingExtent> {
976        let bits_per_sample = self.image.bits_per_sample;
977
978        // If samples take up more than one byte, we expand it to a full number (integer or float)
979        // and the number of samples in that integer type just counts the number in the underlying
980        // image itself. Otherwise, a row is represented as the byte slice of bitfields without
981        // expansion.
982        let row_samples = if bits_per_sample >= 8 {
983            width
984        } else {
985            ((width as u64) * bits_per_sample as u64)
986                .div_ceil(8)
987                .try_into()
988                .map_err(|_| TiffError::LimitsExceeded)?
989        };
990
991        let buffer_size = row_samples
992            .checked_mul(height)
993            .and_then(|x| x.checked_mul(self.image.samples_per_pixel()))
994            .ok_or(TiffError::LimitsExceeded)?;
995
996        Ok(match self.image().sample_format {
997            SampleFormat::Uint => match bits_per_sample {
998                n if n <= 8 => DecodingExtent::U8(buffer_size),
999                n if n <= 16 => DecodingExtent::U16(buffer_size),
1000                n if n <= 32 => DecodingExtent::U32(buffer_size),
1001                n if n <= 64 => DecodingExtent::U64(buffer_size),
1002                n => {
1003                    return Err(TiffError::UnsupportedError(
1004                        TiffUnsupportedError::UnsupportedBitsPerChannel(n),
1005                    ))
1006                }
1007            },
1008            SampleFormat::IEEEFP => match bits_per_sample {
1009                16 => DecodingExtent::F16(buffer_size),
1010                32 => DecodingExtent::F32(buffer_size),
1011                64 => DecodingExtent::F64(buffer_size),
1012                n => {
1013                    return Err(TiffError::UnsupportedError(
1014                        TiffUnsupportedError::UnsupportedBitsPerChannel(n),
1015                    ))
1016                }
1017            },
1018            SampleFormat::Int => match bits_per_sample {
1019                n if n <= 8 => DecodingExtent::I8(buffer_size),
1020                n if n <= 16 => DecodingExtent::I16(buffer_size),
1021                n if n <= 32 => DecodingExtent::I32(buffer_size),
1022                n if n <= 64 => DecodingExtent::I64(buffer_size),
1023                n => {
1024                    return Err(TiffError::UnsupportedError(
1025                        TiffUnsupportedError::UnsupportedBitsPerChannel(n),
1026                    ))
1027                }
1028            },
1029            format => {
1030                return Err(TiffUnsupportedError::UnsupportedSampleFormat(vec![format]).into())
1031            }
1032        })
1033    }
1034
1035    /// Returns the layout preferred to read the specified chunk with [`Self::read_chunk_bytes`].
1036    ///
1037    /// Returns the layout without being specific as to the underlying type for forward
1038    /// compatibility. Note that, in general, a TIFF may contain an almost arbitrary number of
1039    /// channels of individual *bit* length and format each.
1040    ///
1041    /// See [`Self::colortype`] to describe the sample types.
1042    ///
1043    /// # Bugs
1044    ///
1045    /// When the image is stored as a planar configuration, this method will currently only
1046    /// indicate the layout needed to read the first data plane. This will be fixed in a future
1047    /// major version of `tiff`.
1048    pub fn image_chunk_buffer_layout(
1049        &mut self,
1050        chunk_index: u32,
1051    ) -> TiffResult<BufferLayoutPreference> {
1052        let data_dims = self.image().chunk_data_dimensions(chunk_index)?;
1053        let layout = self
1054            .result_extent(data_dims.0 as usize, data_dims.1 as usize)?
1055            .preferred_layout()?;
1056
1057        let row_stride = self.image.minimum_row_stride(data_dims);
1058
1059        Ok(BufferLayoutPreference {
1060            len: layout.size(),
1061            row_stride,
1062        })
1063    }
1064
1065    /// Read the specified chunk (at index `chunk_index`) and return the binary data as a Vector.
1066    ///
1067    /// # Bugs
1068    ///
1069    /// When the image is stored as a planar configuration, this method will currently only read
1070    /// the first sample's plane. This will be fixed in a future major version of `tiff`.
1071    pub fn read_chunk(&mut self, chunk_index: u32) -> TiffResult<DecodingResult> {
1072        let data_dims = self.image().chunk_data_dimensions(chunk_index)?;
1073
1074        let mut result = self.result_buffer(data_dims.0 as usize, data_dims.1 as usize)?;
1075
1076        self.read_chunk_to_buffer(result.as_buffer(0), chunk_index, data_dims.0 as usize)?;
1077
1078        Ok(result)
1079    }
1080
1081    /// Read the specified chunk (at index `chunk_index`) into an allocated buffer.
1082    ///
1083    /// Returns a [`TiffError::UsageError`] if the chunk is smaller than the size indicated with a
1084    /// call to [`Self::image_chunk_buffer_layout`]. Note that the alignment may be arbitrary, but
1085    /// an alignment smaller than the preferred alignment may perform worse.
1086    ///
1087    /// # Bugs
1088    ///
1089    /// When the image is stored as a planar configuration, this method will currently only read
1090    /// the first sample's plane. This will be fixed in a future major version of `tiff`.
1091    pub fn read_chunk_bytes(&mut self, chunk_index: u32, buffer: &mut [u8]) -> TiffResult<()> {
1092        let data_dims = self.image().chunk_data_dimensions(chunk_index)?;
1093
1094        let extent = self.result_extent(data_dims.0 as usize, data_dims.1 as usize)?;
1095        extent.assert_layout(buffer.len())?;
1096
1097        let output_row_stride = u64::from(data_dims.0)
1098            .saturating_mul(self.image.samples_per_pixel() as u64)
1099            .saturating_mul(self.image.bits_per_sample as u64)
1100            .div_ceil(8);
1101
1102        self.read_chunk_to_bytes(buffer, chunk_index, output_row_stride)?;
1103
1104        Ok(())
1105    }
1106
1107    /// Returns the default chunk size for the current image. Any given chunk in the image is at most as large as
1108    /// the value returned here. For the size of the data (chunk minus padding), use `chunk_data_dimensions`.
1109    pub fn chunk_dimensions(&self) -> (u32, u32) {
1110        self.image().chunk_dimensions().unwrap()
1111    }
1112
1113    /// Returns the size of the data in the chunk with the specified index. This is the default size of the chunk,
1114    /// minus any padding.
1115    pub fn chunk_data_dimensions(&self, chunk_index: u32) -> (u32, u32) {
1116        self.image()
1117            .chunk_data_dimensions(chunk_index)
1118            .expect("invalid chunk_index")
1119    }
1120
1121    /// Returns the preferred buffer required to read the whole image with [`Self::read_image_bytes`].
1122    ///
1123    /// Returns the layout without being specific as to the underlying type for forward
1124    /// compatibility. Note that, in general, a TIFF may contain an almost arbitrary number of
1125    /// channels of individual *bit* length and format each.
1126    ///
1127    /// See [`Self::colortype`] to describe the sample types.
1128    ///
1129    /// # Bugs
1130    ///
1131    /// When the image is stored as a planar configuration, this method will currently only
1132    /// indicate the layout needed to read the first data plane. This will be fixed in a future
1133    /// major version of `tiff`.
1134    pub fn image_buffer_layout(&mut self) -> TiffResult<BufferLayoutPreference> {
1135        let data_dims @ (width, height) = (self.image.width, self.image.height);
1136
1137        let layout = self
1138            .result_extent(width as usize, height as usize)?
1139            .preferred_layout()?;
1140
1141        let row_stride = self.image.minimum_row_stride(data_dims);
1142
1143        Ok(BufferLayoutPreference {
1144            len: layout.size(),
1145            row_stride,
1146        })
1147    }
1148
1149    /// Decodes the entire image and return it as a Vector
1150    ///
1151    /// # Bugs
1152    ///
1153    /// When the image is stored as a planar configuration, this method will currently only read
1154    /// the first sample's plane. This will be fixed in a future major version of `tiff`.
1155    pub fn read_image(&mut self) -> TiffResult<DecodingResult> {
1156        let width = self.image().width;
1157        let height = self.image().height;
1158
1159        let mut result = self.result_buffer(width as usize, height as usize)?;
1160        self.read_image_bytes(result.as_buffer(0).as_bytes_mut())?;
1161
1162        Ok(result)
1163    }
1164
1165    /// Decodes the entire image into a provided buffer.
1166    ///
1167    /// Returns a [`TiffError::UsageError`] if the chunk is smaller than the size indicated with a
1168    /// call to [`Self::image_buffer_layout`]. Note that the alignment may be arbitrary, but an
1169    /// alignment smaller than the preferred alignment may perform worse.
1170    ///
1171    /// # Bugs
1172    ///
1173    /// When the image is stored as a planar configuration, this method will currently only read
1174    /// the first sample's plane. This will be fixed in a future major version of `tiff`.
1175    pub fn read_image_bytes(&mut self, buffer: &mut [u8]) -> TiffResult<()> {
1176        let width = self.image().width;
1177        let height = self.image().height;
1178
1179        let extent = self.result_extent(width as usize, height as usize)?;
1180        extent.assert_layout(buffer.len())?;
1181
1182        if width == 0 || height == 0 {
1183            return Ok(());
1184        }
1185
1186        let chunk_dimensions = self.image().chunk_dimensions()?;
1187        let chunk_dimensions = (
1188            chunk_dimensions.0.min(width),
1189            chunk_dimensions.1.min(height),
1190        );
1191        if chunk_dimensions.0 == 0 || chunk_dimensions.1 == 0 {
1192            return Err(TiffError::FormatError(
1193                TiffFormatError::InconsistentSizesEncountered,
1194            ));
1195        }
1196
1197        let samples = self.image().samples_per_pixel();
1198        if samples == 0 {
1199            return Err(TiffError::FormatError(
1200                TiffFormatError::InconsistentSizesEncountered,
1201            ));
1202        }
1203
1204        let output_row_bits = (width as u64 * self.image.bits_per_sample as u64)
1205            .checked_mul(samples as u64)
1206            .ok_or(TiffError::LimitsExceeded)?;
1207        let output_row_stride: usize = output_row_bits.div_ceil(8).try_into()?;
1208
1209        let chunk_row_bits = (chunk_dimensions.0 as u64 * self.image.bits_per_sample as u64)
1210            .checked_mul(samples as u64)
1211            .ok_or(TiffError::LimitsExceeded)?;
1212        let chunk_row_bytes: usize = chunk_row_bits.div_ceil(8).try_into()?;
1213
1214        let chunks_across = ((width - 1) / chunk_dimensions.0 + 1) as usize;
1215
1216        if chunks_across > 1 && chunk_row_bits % 8 != 0 {
1217            return Err(TiffError::UnsupportedError(
1218                TiffUnsupportedError::MisalignedTileBoundaries,
1219            ));
1220        }
1221
1222        let image_chunks = self.image().chunk_offsets.len() / self.image().strips_per_pixel();
1223        // For multi-band images, only the first band is read.
1224        // Possible improvements:
1225        // * pass requested band as parameter
1226        // * collect bands to a RGB encoding result in case of RGB bands
1227        for chunk in 0..image_chunks {
1228            self.goto_offset_u64(self.image().chunk_offsets[chunk])?;
1229
1230            let x = chunk % chunks_across;
1231            let y = chunk / chunks_across;
1232            let buffer_offset =
1233                y * output_row_stride * chunk_dimensions.1 as usize + x * chunk_row_bytes;
1234            self.image.expand_chunk(
1235                &mut self.value_reader,
1236                &mut buffer[buffer_offset..],
1237                output_row_stride,
1238                chunk as u32,
1239            )?;
1240        }
1241
1242        Ok(())
1243    }
1244
1245    /// Get the IFD decoder for our current image IFD.
1246    fn image_ifd(&mut self) -> IfdDecoder<'_> {
1247        IfdDecoder {
1248            inner: tag_reader::TagReader {
1249                decoder: &mut self.value_reader,
1250                ifd: self.image.ifd.as_ref().unwrap(),
1251            },
1252        }
1253    }
1254
1255    /// Prepare reading values for tags of a given directory.
1256    ///
1257    /// # Examples
1258    ///
1259    /// This method may be used to read the values of tags in directories that have been previously
1260    /// read with [`Decoder::read_directory`].
1261    ///
1262    /// ```no_run
1263    /// use tiff::decoder::Decoder;
1264    /// use tiff::tags::Tag;
1265    ///
1266    /// # use std::io::Cursor;
1267    /// # let mut data = Cursor::new(vec![0]);
1268    /// let mut decoder = Decoder::new(&mut data).unwrap();
1269    /// let sub_ifds = decoder.get_tag(Tag::SubIfd)?.into_ifd_vec()?;
1270    ///
1271    /// for ifd in sub_ifds {
1272    ///     let subdir = decoder.read_directory(ifd)?;
1273    ///     let subfile = decoder.read_directory_tags(&subdir).find_tag(Tag::SubfileType)?;
1274    ///     // omitted: handle the subfiles, e.g. thumbnails
1275    /// }
1276    ///
1277    /// # Ok::<_, tiff::TiffError>(())
1278    /// ```
1279    pub fn read_directory_tags<'ifd>(&'ifd mut self, ifd: &'ifd Directory) -> IfdDecoder<'ifd> {
1280        IfdDecoder {
1281            inner: tag_reader::TagReader {
1282                decoder: &mut self.value_reader,
1283                ifd,
1284            },
1285        }
1286    }
1287
1288    /// Tries to retrieve a tag from the current image directory.
1289    /// Return `Ok(None)` if the tag is not present.
1290    pub fn find_tag(&mut self, tag: Tag) -> TiffResult<Option<ifd::Value>> {
1291        self.image_ifd().find_tag(tag)
1292    }
1293
1294    /// Tries to retrieve a tag in the current image directory and convert it to the desired
1295    /// unsigned type.
1296    pub fn find_tag_unsigned<T: TryFrom<u64>>(&mut self, tag: Tag) -> TiffResult<Option<T>> {
1297        self.image_ifd().find_tag_unsigned(tag)
1298    }
1299
1300    /// Tries to retrieve a vector of all a tag's values and convert them to the desired unsigned
1301    /// type.
1302    pub fn find_tag_unsigned_vec<T: TryFrom<u64>>(
1303        &mut self,
1304        tag: Tag,
1305    ) -> TiffResult<Option<Vec<T>>> {
1306        self.image_ifd().find_tag_unsigned_vec(tag)
1307    }
1308
1309    /// Tries to retrieve a tag from the current image directory and convert it to the desired
1310    /// unsigned type. Returns an error if the tag is not present.
1311    pub fn get_tag_unsigned<T: TryFrom<u64>>(&mut self, tag: Tag) -> TiffResult<T> {
1312        self.image_ifd().get_tag_unsigned(tag)
1313    }
1314
1315    /// Tries to retrieve a tag from the current image directory.
1316    /// Returns an error if the tag is not present
1317    pub fn get_tag(&mut self, tag: Tag) -> TiffResult<ifd::Value> {
1318        self.image_ifd().get_tag(tag)
1319    }
1320
1321    pub fn get_tag_u32(&mut self, tag: Tag) -> TiffResult<u32> {
1322        self.get_tag(tag)?.into_u32()
1323    }
1324
1325    pub fn get_tag_u64(&mut self, tag: Tag) -> TiffResult<u64> {
1326        self.get_tag(tag)?.into_u64()
1327    }
1328
1329    /// Tries to retrieve a tag and convert it to the desired type.
1330    pub fn get_tag_f32(&mut self, tag: Tag) -> TiffResult<f32> {
1331        self.get_tag(tag)?.into_f32()
1332    }
1333
1334    /// Tries to retrieve a tag and convert it to the desired type.
1335    pub fn get_tag_f64(&mut self, tag: Tag) -> TiffResult<f64> {
1336        self.get_tag(tag)?.into_f64()
1337    }
1338
1339    /// Tries to retrieve a tag and convert it to the desired type.
1340    pub fn get_tag_u32_vec(&mut self, tag: Tag) -> TiffResult<Vec<u32>> {
1341        self.get_tag(tag)?.into_u32_vec()
1342    }
1343
1344    pub fn get_tag_u16_vec(&mut self, tag: Tag) -> TiffResult<Vec<u16>> {
1345        self.get_tag(tag)?.into_u16_vec()
1346    }
1347
1348    pub fn get_tag_u64_vec(&mut self, tag: Tag) -> TiffResult<Vec<u64>> {
1349        self.get_tag(tag)?.into_u64_vec()
1350    }
1351
1352    /// Tries to retrieve a tag and convert it to the desired type.
1353    pub fn get_tag_f32_vec(&mut self, tag: Tag) -> TiffResult<Vec<f32>> {
1354        self.get_tag(tag)?.into_f32_vec()
1355    }
1356
1357    /// Tries to retrieve a tag and convert it to the desired type.
1358    pub fn get_tag_f64_vec(&mut self, tag: Tag) -> TiffResult<Vec<f64>> {
1359        self.get_tag(tag)?.into_f64_vec()
1360    }
1361
1362    /// Tries to retrieve a tag and convert it to a 8bit vector.
1363    pub fn get_tag_u8_vec(&mut self, tag: Tag) -> TiffResult<Vec<u8>> {
1364        self.get_tag(tag)?.into_u8_vec()
1365    }
1366
1367    /// Tries to retrieve a tag and convert it to a ascii vector.
1368    pub fn get_tag_ascii_string(&mut self, tag: Tag) -> TiffResult<String> {
1369        self.get_tag(tag)?.into_string()
1370    }
1371
1372    pub fn tag_iter(&mut self) -> impl Iterator<Item = TiffResult<(Tag, ifd::Value)>> + '_ {
1373        self.image_ifd().tag_iter()
1374    }
1375}
1376
1377impl<R: Seek + Read> ValueReader<R> {
1378    pub(crate) fn read_directory(&mut self, ptr: IfdPointer) -> Result<Directory, TiffError> {
1379        Self::read_ifd(&mut self.reader, self.bigtiff, ptr)
1380    }
1381
1382    /// Reads a IFD entry.
1383    // An IFD entry has four fields:
1384    //
1385    // Tag   2 bytes
1386    // Type  2 bytes
1387    // Count 4 bytes
1388    // Value 4 bytes either a pointer the value itself
1389    fn read_entry(
1390        reader: &mut EndianReader<R>,
1391        bigtiff: bool,
1392    ) -> TiffResult<Option<(Tag, ifd::Entry)>> {
1393        let tag = Tag::from_u16_exhaustive(reader.read_u16()?);
1394        let type_ = match Type::from_u16(reader.read_u16()?) {
1395            Some(t) => t,
1396            None => {
1397                // Unknown type. Skip this entry according to spec.
1398                reader.read_u32()?;
1399                reader.read_u32()?;
1400                return Ok(None);
1401            }
1402        };
1403        let entry = if bigtiff {
1404            let mut offset = [0; 8];
1405
1406            let count = reader.read_u64()?;
1407            reader.inner().read_exact(&mut offset)?;
1408            ifd::Entry::new_u64(type_, count, offset)
1409        } else {
1410            let mut offset = [0; 4];
1411
1412            let count = reader.read_u32()?;
1413            reader.inner().read_exact(&mut offset)?;
1414            ifd::Entry::new(type_, count, offset)
1415        };
1416        Ok(Some((tag, entry)))
1417    }
1418
1419    /// Reads the IFD starting at the indicated location.
1420    fn read_ifd(
1421        reader: &mut EndianReader<R>,
1422        bigtiff: bool,
1423        ifd_location: IfdPointer,
1424    ) -> TiffResult<Directory> {
1425        reader.goto_offset(ifd_location.0)?;
1426
1427        let mut entries: BTreeMap<_, _> = BTreeMap::new();
1428
1429        let num_tags = if bigtiff {
1430            reader.read_u64()?
1431        } else {
1432            reader.read_u16()?.into()
1433        };
1434
1435        for _ in 0..num_tags {
1436            let (tag, entry) = match Self::read_entry(reader, bigtiff)? {
1437                Some(val) => val,
1438                None => {
1439                    continue;
1440                } // Unknown data type in tag, skip
1441            };
1442
1443            entries.insert(tag.to_u16(), entry);
1444        }
1445
1446        let next_ifd = if bigtiff {
1447            reader.read_u64()?
1448        } else {
1449            reader.read_u32()?.into()
1450        };
1451
1452        let next_ifd = core::num::NonZeroU64::new(next_ifd);
1453
1454        Ok(Directory { entries, next_ifd })
1455    }
1456}
1457
1458impl IfdDecoder<'_> {
1459    /// Tries to retrieve a tag.
1460    /// Return `Ok(None)` if the tag is not present.
1461    pub fn find_tag(&mut self, tag: Tag) -> TiffResult<Option<ifd::Value>> {
1462        self.inner.find_tag(tag)
1463    }
1464
1465    /// Tries to retrieve a tag and convert it to the desired unsigned type.
1466    pub fn find_tag_unsigned<T: TryFrom<u64>>(&mut self, tag: Tag) -> TiffResult<Option<T>> {
1467        self.find_tag(tag)?
1468            .map(|v| v.into_u64())
1469            .transpose()?
1470            .map(|value| {
1471                T::try_from(value).map_err(|_| TiffFormatError::InvalidTagValueType(tag).into())
1472            })
1473            .transpose()
1474    }
1475
1476    /// Tries to retrieve a vector of all a tag's values and convert them to
1477    /// the desired unsigned type.
1478    pub fn find_tag_unsigned_vec<T: TryFrom<u64>>(
1479        &mut self,
1480        tag: Tag,
1481    ) -> TiffResult<Option<Vec<T>>> {
1482        self.find_tag(tag)?
1483            .map(|v| v.into_u64_vec())
1484            .transpose()?
1485            .map(|v| {
1486                v.into_iter()
1487                    .map(|u| {
1488                        T::try_from(u).map_err(|_| TiffFormatError::InvalidTagValueType(tag).into())
1489                    })
1490                    .collect()
1491            })
1492            .transpose()
1493    }
1494
1495    /// Tries to retrieve a tag and convert it to the desired unsigned type.
1496    /// Returns an error if the tag is not present.
1497    pub fn get_tag_unsigned<T: TryFrom<u64>>(&mut self, tag: Tag) -> TiffResult<T> {
1498        self.find_tag_unsigned(tag)?
1499            .ok_or_else(|| TiffFormatError::RequiredTagNotFound(tag).into())
1500    }
1501
1502    /// Tries to retrieve a tag.
1503    /// Returns an error if the tag is not present
1504    pub fn get_tag(&mut self, tag: Tag) -> TiffResult<ifd::Value> {
1505        match self.find_tag(tag)? {
1506            Some(val) => Ok(val),
1507            None => Err(TiffError::FormatError(
1508                TiffFormatError::RequiredTagNotFound(tag),
1509            )),
1510        }
1511    }
1512
1513    /// Tries to retrieve a tag and convert it to the desired type.
1514    pub fn get_tag_u32(&mut self, tag: Tag) -> TiffResult<u32> {
1515        self.get_tag(tag)?.into_u32()
1516    }
1517
1518    pub fn get_tag_u64(&mut self, tag: Tag) -> TiffResult<u64> {
1519        self.get_tag(tag)?.into_u64()
1520    }
1521
1522    /// Tries to retrieve a tag and convert it to the desired type.
1523    pub fn get_tag_f32(&mut self, tag: Tag) -> TiffResult<f32> {
1524        self.get_tag(tag)?.into_f32()
1525    }
1526
1527    /// Tries to retrieve a tag and convert it to the desired type.
1528    pub fn get_tag_f64(&mut self, tag: Tag) -> TiffResult<f64> {
1529        self.get_tag(tag)?.into_f64()
1530    }
1531
1532    /// Tries to retrieve a tag and convert it to the desired type.
1533    pub fn get_tag_u32_vec(&mut self, tag: Tag) -> TiffResult<Vec<u32>> {
1534        self.get_tag(tag)?.into_u32_vec()
1535    }
1536
1537    pub fn get_tag_u16_vec(&mut self, tag: Tag) -> TiffResult<Vec<u16>> {
1538        self.get_tag(tag)?.into_u16_vec()
1539    }
1540
1541    pub fn get_tag_u64_vec(&mut self, tag: Tag) -> TiffResult<Vec<u64>> {
1542        self.get_tag(tag)?.into_u64_vec()
1543    }
1544
1545    /// Tries to retrieve a tag and convert it to the desired type.
1546    pub fn get_tag_f32_vec(&mut self, tag: Tag) -> TiffResult<Vec<f32>> {
1547        self.get_tag(tag)?.into_f32_vec()
1548    }
1549
1550    /// Tries to retrieve a tag and convert it to the desired type.
1551    pub fn get_tag_f64_vec(&mut self, tag: Tag) -> TiffResult<Vec<f64>> {
1552        self.get_tag(tag)?.into_f64_vec()
1553    }
1554
1555    /// Tries to retrieve a tag and convert it to a 8bit vector.
1556    pub fn get_tag_u8_vec(&mut self, tag: Tag) -> TiffResult<Vec<u8>> {
1557        self.get_tag(tag)?.into_u8_vec()
1558    }
1559
1560    /// Tries to retrieve a tag and convert it to a ascii vector.
1561    pub fn get_tag_ascii_string(&mut self, tag: Tag) -> TiffResult<String> {
1562        self.get_tag(tag)?.into_string()
1563    }
1564}
1565
1566impl<'l> IfdDecoder<'l> {
1567    /// Returns an iterator over all tags in the current image, along with their values.
1568    pub fn tag_iter(self) -> impl Iterator<Item = TiffResult<(Tag, ifd::Value)>> + 'l {
1569        self.inner
1570            .ifd
1571            .iter()
1572            .map(|(tag, entry)| match self.inner.decoder.entry_val(entry) {
1573                Ok(value) => Ok((tag, value)),
1574                Err(err) => Err(err),
1575            })
1576    }
1577}