tiff/decoder/
ifd.rs

1//! Function for reading TIFF tags
2
3use std::collections::HashMap;
4use std::convert::{TryFrom, TryInto};
5use std::io::{self, Read, Seek};
6use std::mem;
7use std::str;
8
9use super::stream::{ByteOrder, EndianReader, SmartReader};
10use crate::tags::{Tag, Type};
11use crate::{TiffError, TiffFormatError, TiffResult};
12
13use self::Value::{
14    Ascii, Byte, Double, Float, Ifd, IfdBig, List, Rational, RationalBig, SRational, SRationalBig,
15    Short, Signed, SignedBig, Unsigned, UnsignedBig,
16};
17
18#[allow(unused_qualifications)]
19#[derive(Debug, Clone, PartialEq)]
20#[non_exhaustive]
21pub enum Value {
22    Byte(u8),
23    Short(u16),
24    Signed(i32),
25    SignedBig(i64),
26    Unsigned(u32),
27    UnsignedBig(u64),
28    Float(f32),
29    Double(f64),
30    List(Vec<Value>),
31    Rational(u32, u32),
32    RationalBig(u64, u64),
33    SRational(i32, i32),
34    SRationalBig(i64, i64),
35    Ascii(String),
36    Ifd(u32),
37    IfdBig(u64),
38}
39
40impl Value {
41    pub fn into_u8(self) -> TiffResult<u8> {
42        match self {
43            Byte(val) => Ok(val),
44            val => Err(TiffError::FormatError(TiffFormatError::ByteExpected(val))),
45        }
46    }
47
48    pub fn into_u16(self) -> TiffResult<u16> {
49        match self {
50            Short(val) => Ok(val),
51            Unsigned(val) => Ok(u16::try_from(val)?),
52            UnsignedBig(val) => Ok(u16::try_from(val)?),
53            val => Err(TiffError::FormatError(
54                TiffFormatError::UnsignedIntegerExpected(val),
55            )),
56        }
57    }
58
59    pub fn into_u32(self) -> TiffResult<u32> {
60        match self {
61            Short(val) => Ok(val.into()),
62            Unsigned(val) => Ok(val),
63            UnsignedBig(val) => Ok(u32::try_from(val)?),
64            Ifd(val) => Ok(val),
65            IfdBig(val) => Ok(u32::try_from(val)?),
66            val => Err(TiffError::FormatError(
67                TiffFormatError::UnsignedIntegerExpected(val),
68            )),
69        }
70    }
71
72    pub fn into_i32(self) -> TiffResult<i32> {
73        match self {
74            Signed(val) => Ok(val),
75            SignedBig(val) => Ok(i32::try_from(val)?),
76            val => Err(TiffError::FormatError(
77                TiffFormatError::SignedIntegerExpected(val),
78            )),
79        }
80    }
81
82    pub fn into_u64(self) -> TiffResult<u64> {
83        match self {
84            Short(val) => Ok(val.into()),
85            Unsigned(val) => Ok(val.into()),
86            UnsignedBig(val) => Ok(val),
87            Ifd(val) => Ok(val.into()),
88            IfdBig(val) => Ok(val),
89            val => Err(TiffError::FormatError(
90                TiffFormatError::UnsignedIntegerExpected(val),
91            )),
92        }
93    }
94
95    pub fn into_i64(self) -> TiffResult<i64> {
96        match self {
97            Signed(val) => Ok(val.into()),
98            SignedBig(val) => Ok(val),
99            val => Err(TiffError::FormatError(
100                TiffFormatError::SignedIntegerExpected(val),
101            )),
102        }
103    }
104
105    pub fn into_f32(self) -> TiffResult<f32> {
106        match self {
107            Float(val) => Ok(val),
108            val => Err(TiffError::FormatError(
109                TiffFormatError::SignedIntegerExpected(val),
110            )),
111        }
112    }
113
114    pub fn into_f64(self) -> TiffResult<f64> {
115        match self {
116            Double(val) => Ok(val),
117            val => Err(TiffError::FormatError(
118                TiffFormatError::SignedIntegerExpected(val),
119            )),
120        }
121    }
122
123    pub fn into_string(self) -> TiffResult<String> {
124        match self {
125            Ascii(val) => Ok(val),
126            val => Err(TiffError::FormatError(
127                TiffFormatError::SignedIntegerExpected(val),
128            )),
129        }
130    }
131
132    pub fn into_u32_vec(self) -> TiffResult<Vec<u32>> {
133        match self {
134            List(vec) => {
135                let mut new_vec = Vec::with_capacity(vec.len());
136                for v in vec {
137                    new_vec.push(v.into_u32()?)
138                }
139                Ok(new_vec)
140            }
141            Unsigned(val) => Ok(vec![val]),
142            UnsignedBig(val) => Ok(vec![u32::try_from(val)?]),
143            Rational(numerator, denominator) => Ok(vec![numerator, denominator]),
144            RationalBig(numerator, denominator) => {
145                Ok(vec![u32::try_from(numerator)?, u32::try_from(denominator)?])
146            }
147            Ifd(val) => Ok(vec![val]),
148            IfdBig(val) => Ok(vec![u32::try_from(val)?]),
149            Ascii(val) => Ok(val.chars().map(u32::from).collect()),
150            val => Err(TiffError::FormatError(
151                TiffFormatError::UnsignedIntegerExpected(val),
152            )),
153        }
154    }
155
156    pub fn into_u8_vec(self) -> TiffResult<Vec<u8>> {
157        match self {
158            List(vec) => {
159                let mut new_vec = Vec::with_capacity(vec.len());
160                for v in vec {
161                    new_vec.push(v.into_u8()?)
162                }
163                Ok(new_vec)
164            }
165            Byte(val) => Ok(vec![val]),
166
167            val => Err(TiffError::FormatError(
168                TiffFormatError::UnsignedIntegerExpected(val),
169            )),
170        }
171    }
172
173    pub fn into_u16_vec(self) -> TiffResult<Vec<u16>> {
174        match self {
175            List(vec) => {
176                let mut new_vec = Vec::with_capacity(vec.len());
177                for v in vec {
178                    new_vec.push(v.into_u16()?)
179                }
180                Ok(new_vec)
181            }
182            Short(val) => Ok(vec![val]),
183            val => Err(TiffError::FormatError(
184                TiffFormatError::UnsignedIntegerExpected(val),
185            )),
186        }
187    }
188
189    pub fn into_i32_vec(self) -> TiffResult<Vec<i32>> {
190        match self {
191            List(vec) => {
192                let mut new_vec = Vec::with_capacity(vec.len());
193                for v in vec {
194                    match v {
195                        SRational(numerator, denominator) => {
196                            new_vec.push(numerator);
197                            new_vec.push(denominator);
198                        }
199                        SRationalBig(numerator, denominator) => {
200                            new_vec.push(i32::try_from(numerator)?);
201                            new_vec.push(i32::try_from(denominator)?);
202                        }
203                        _ => new_vec.push(v.into_i32()?),
204                    }
205                }
206                Ok(new_vec)
207            }
208            Signed(val) => Ok(vec![val]),
209            SignedBig(val) => Ok(vec![i32::try_from(val)?]),
210            SRational(numerator, denominator) => Ok(vec![numerator, denominator]),
211            SRationalBig(numerator, denominator) => {
212                Ok(vec![i32::try_from(numerator)?, i32::try_from(denominator)?])
213            }
214            val => Err(TiffError::FormatError(
215                TiffFormatError::SignedIntegerExpected(val),
216            )),
217        }
218    }
219
220    pub fn into_f32_vec(self) -> TiffResult<Vec<f32>> {
221        match self {
222            List(vec) => {
223                let mut new_vec = Vec::with_capacity(vec.len());
224                for v in vec {
225                    new_vec.push(v.into_f32()?)
226                }
227                Ok(new_vec)
228            }
229            Float(val) => Ok(vec![val]),
230            val => Err(TiffError::FormatError(
231                TiffFormatError::UnsignedIntegerExpected(val),
232            )),
233        }
234    }
235
236    pub fn into_f64_vec(self) -> TiffResult<Vec<f64>> {
237        match self {
238            List(vec) => {
239                let mut new_vec = Vec::with_capacity(vec.len());
240                for v in vec {
241                    new_vec.push(v.into_f64()?)
242                }
243                Ok(new_vec)
244            }
245            Double(val) => Ok(vec![val]),
246            val => Err(TiffError::FormatError(
247                TiffFormatError::UnsignedIntegerExpected(val),
248            )),
249        }
250    }
251
252    pub fn into_u64_vec(self) -> TiffResult<Vec<u64>> {
253        match self {
254            List(vec) => {
255                let mut new_vec = Vec::with_capacity(vec.len());
256                for v in vec {
257                    new_vec.push(v.into_u64()?)
258                }
259                Ok(new_vec)
260            }
261            Unsigned(val) => Ok(vec![val.into()]),
262            UnsignedBig(val) => Ok(vec![val]),
263            Rational(numerator, denominator) => Ok(vec![numerator.into(), denominator.into()]),
264            RationalBig(numerator, denominator) => Ok(vec![numerator, denominator]),
265            Ifd(val) => Ok(vec![val.into()]),
266            IfdBig(val) => Ok(vec![val]),
267            Ascii(val) => Ok(val.chars().map(u32::from).map(u64::from).collect()),
268            val => Err(TiffError::FormatError(
269                TiffFormatError::UnsignedIntegerExpected(val),
270            )),
271        }
272    }
273
274    pub fn into_i64_vec(self) -> TiffResult<Vec<i64>> {
275        match self {
276            List(vec) => {
277                let mut new_vec = Vec::with_capacity(vec.len());
278                for v in vec {
279                    match v {
280                        SRational(numerator, denominator) => {
281                            new_vec.push(numerator.into());
282                            new_vec.push(denominator.into());
283                        }
284                        SRationalBig(numerator, denominator) => {
285                            new_vec.push(numerator);
286                            new_vec.push(denominator);
287                        }
288                        _ => new_vec.push(v.into_i64()?),
289                    }
290                }
291                Ok(new_vec)
292            }
293            Signed(val) => Ok(vec![val.into()]),
294            SignedBig(val) => Ok(vec![val]),
295            SRational(numerator, denominator) => Ok(vec![numerator.into(), denominator.into()]),
296            SRationalBig(numerator, denominator) => Ok(vec![numerator, denominator]),
297            val => Err(TiffError::FormatError(
298                TiffFormatError::SignedIntegerExpected(val),
299            )),
300        }
301    }
302}
303
304#[derive(Clone)]
305pub struct Entry {
306    type_: Type,
307    count: u64,
308    offset: [u8; 8],
309}
310
311impl ::std::fmt::Debug for Entry {
312    fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
313        fmt.write_str(&format!(
314            "Entry {{ type_: {:?}, count: {:?}, offset: {:?} }}",
315            self.type_, self.count, &self.offset
316        ))
317    }
318}
319
320impl Entry {
321    pub fn new(type_: Type, count: u32, offset: [u8; 4]) -> Entry {
322        let mut offset = offset.to_vec();
323        offset.append(&mut vec![0; 4]);
324        Entry::new_u64(type_, count.into(), offset[..].try_into().unwrap())
325    }
326
327    pub fn new_u64(type_: Type, count: u64, offset: [u8; 8]) -> Entry {
328        Entry {
329            type_,
330            count,
331            offset,
332        }
333    }
334
335    /// Returns a mem_reader for the offset/value field
336    fn r(&self, byte_order: ByteOrder) -> SmartReader<io::Cursor<Vec<u8>>> {
337        SmartReader::wrap(io::Cursor::new(self.offset.to_vec()), byte_order)
338    }
339
340    pub fn val<R: Read + Seek>(
341        &self,
342        limits: &super::Limits,
343        bigtiff: bool,
344        reader: &mut SmartReader<R>,
345    ) -> TiffResult<Value> {
346        // Case 1: there are no values so we can return immediately.
347        if self.count == 0 {
348            return Ok(List(Vec::new()));
349        }
350
351        let bo = reader.byte_order();
352
353        let tag_size = match self.type_ {
354            Type::BYTE | Type::SBYTE | Type::ASCII | Type::UNDEFINED => 1,
355            Type::SHORT | Type::SSHORT => 2,
356            Type::LONG | Type::SLONG | Type::FLOAT | Type::IFD => 4,
357            Type::LONG8
358            | Type::SLONG8
359            | Type::DOUBLE
360            | Type::RATIONAL
361            | Type::SRATIONAL
362            | Type::IFD8 => 8,
363        };
364
365        let value_bytes = match self.count.checked_mul(tag_size) {
366            Some(n) => n,
367            None => {
368                return Err(TiffError::LimitsExceeded);
369            }
370        };
371
372        // Case 2: there is one value.
373        if self.count == 1 {
374            // 2a: the value is 5-8 bytes and we're in BigTiff mode.
375            if bigtiff && value_bytes > 4 && value_bytes <= 8 {
376                return Ok(match self.type_ {
377                    Type::LONG8 => UnsignedBig(self.r(bo).read_u64()?),
378                    Type::SLONG8 => SignedBig(self.r(bo).read_i64()?),
379                    Type::DOUBLE => Double(self.r(bo).read_f64()?),
380                    Type::RATIONAL => {
381                        let mut r = self.r(bo);
382                        Rational(r.read_u32()?, r.read_u32()?)
383                    }
384                    Type::SRATIONAL => {
385                        let mut r = self.r(bo);
386                        SRational(r.read_i32()?, r.read_i32()?)
387                    }
388                    Type::IFD8 => IfdBig(self.r(bo).read_u64()?),
389                    Type::BYTE
390                    | Type::SBYTE
391                    | Type::ASCII
392                    | Type::UNDEFINED
393                    | Type::SHORT
394                    | Type::SSHORT
395                    | Type::LONG
396                    | Type::SLONG
397                    | Type::FLOAT
398                    | Type::IFD => unreachable!(),
399                });
400            }
401
402            // 2b: the value is at most 4 bytes or doesn't fit in the offset field.
403            return Ok(match self.type_ {
404                Type::BYTE => Unsigned(u32::from(self.offset[0])),
405                Type::SBYTE => Signed(i32::from(self.offset[0] as i8)),
406                Type::UNDEFINED => Byte(self.offset[0]),
407                Type::SHORT => Unsigned(u32::from(self.r(bo).read_u16()?)),
408                Type::SSHORT => Signed(i32::from(self.r(bo).read_i16()?)),
409                Type::LONG => Unsigned(self.r(bo).read_u32()?),
410                Type::SLONG => Signed(self.r(bo).read_i32()?),
411                Type::FLOAT => Float(self.r(bo).read_f32()?),
412                Type::ASCII => {
413                    if self.offset[0] == 0 {
414                        Ascii("".to_string())
415                    } else {
416                        return Err(TiffError::FormatError(TiffFormatError::InvalidTag));
417                    }
418                }
419                Type::LONG8 => {
420                    reader.goto_offset(self.r(bo).read_u32()?.into())?;
421                    UnsignedBig(reader.read_u64()?)
422                }
423                Type::SLONG8 => {
424                    reader.goto_offset(self.r(bo).read_u32()?.into())?;
425                    SignedBig(reader.read_i64()?)
426                }
427                Type::DOUBLE => {
428                    reader.goto_offset(self.r(bo).read_u32()?.into())?;
429                    Double(reader.read_f64()?)
430                }
431                Type::RATIONAL => {
432                    reader.goto_offset(self.r(bo).read_u32()?.into())?;
433                    Rational(reader.read_u32()?, reader.read_u32()?)
434                }
435                Type::SRATIONAL => {
436                    reader.goto_offset(self.r(bo).read_u32()?.into())?;
437                    SRational(reader.read_i32()?, reader.read_i32()?)
438                }
439                Type::IFD => Ifd(self.r(bo).read_u32()?),
440                Type::IFD8 => {
441                    reader.goto_offset(self.r(bo).read_u32()?.into())?;
442                    IfdBig(reader.read_u64()?)
443                }
444            });
445        }
446
447        // Case 3: There is more than one value, but it fits in the offset field.
448        if value_bytes <= 4 || bigtiff && value_bytes <= 8 {
449            match self.type_ {
450                Type::BYTE => return offset_to_bytes(self.count as usize, self),
451                Type::SBYTE => return offset_to_sbytes(self.count as usize, self),
452                Type::ASCII => {
453                    let mut buf = vec![0; self.count as usize];
454                    self.r(bo).read_exact(&mut buf)?;
455                    if buf.is_ascii() && buf.ends_with(&[0]) {
456                        let v = str::from_utf8(&buf)?;
457                        let v = v.trim_matches(char::from(0));
458                        return Ok(Ascii(v.into()));
459                    } else {
460                        return Err(TiffError::FormatError(TiffFormatError::InvalidTag));
461                    }
462                }
463                Type::UNDEFINED => {
464                    return Ok(List(
465                        self.offset[0..self.count as usize]
466                            .iter()
467                            .map(|&b| Byte(b))
468                            .collect(),
469                    ));
470                }
471                Type::SHORT => {
472                    let mut r = self.r(bo);
473                    let mut v = Vec::new();
474                    for _ in 0..self.count {
475                        v.push(Short(r.read_u16()?));
476                    }
477                    return Ok(List(v));
478                }
479                Type::SSHORT => {
480                    let mut r = self.r(bo);
481                    let mut v = Vec::new();
482                    for _ in 0..self.count {
483                        v.push(Signed(i32::from(r.read_i16()?)));
484                    }
485                    return Ok(List(v));
486                }
487                Type::LONG => {
488                    let mut r = self.r(bo);
489                    let mut v = Vec::new();
490                    for _ in 0..self.count {
491                        v.push(Unsigned(r.read_u32()?));
492                    }
493                    return Ok(List(v));
494                }
495                Type::SLONG => {
496                    let mut r = self.r(bo);
497                    let mut v = Vec::new();
498                    for _ in 0..self.count {
499                        v.push(Signed(r.read_i32()?));
500                    }
501                    return Ok(List(v));
502                }
503                Type::FLOAT => {
504                    let mut r = self.r(bo);
505                    let mut v = Vec::new();
506                    for _ in 0..self.count {
507                        v.push(Float(r.read_f32()?));
508                    }
509                    return Ok(List(v));
510                }
511                Type::IFD => {
512                    let mut r = self.r(bo);
513                    let mut v = Vec::new();
514                    for _ in 0..self.count {
515                        v.push(Ifd(r.read_u32()?));
516                    }
517                    return Ok(List(v));
518                }
519                Type::LONG8
520                | Type::SLONG8
521                | Type::RATIONAL
522                | Type::SRATIONAL
523                | Type::DOUBLE
524                | Type::IFD8 => {
525                    unreachable!()
526                }
527            }
528        }
529
530        // Case 4: there is more than one value, and it doesn't fit in the offset field.
531        match self.type_ {
532            // TODO check if this could give wrong results
533            // at a different endianess of file/computer.
534            Type::BYTE => self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| {
535                let mut buf = [0; 1];
536                reader.read_exact(&mut buf)?;
537                Ok(UnsignedBig(u64::from(buf[0])))
538            }),
539            Type::SBYTE => self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| {
540                Ok(SignedBig(i64::from(reader.read_i8()?)))
541            }),
542            Type::SHORT => self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| {
543                Ok(UnsignedBig(u64::from(reader.read_u16()?)))
544            }),
545            Type::SSHORT => self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| {
546                Ok(SignedBig(i64::from(reader.read_i16()?)))
547            }),
548            Type::LONG => self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| {
549                Ok(Unsigned(reader.read_u32()?))
550            }),
551            Type::SLONG => self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| {
552                Ok(Signed(reader.read_i32()?))
553            }),
554            Type::FLOAT => self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| {
555                Ok(Float(reader.read_f32()?))
556            }),
557            Type::DOUBLE => self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| {
558                Ok(Double(reader.read_f64()?))
559            }),
560            Type::RATIONAL => {
561                self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| {
562                    Ok(Rational(reader.read_u32()?, reader.read_u32()?))
563                })
564            }
565            Type::SRATIONAL => {
566                self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| {
567                    Ok(SRational(reader.read_i32()?, reader.read_i32()?))
568                })
569            }
570            Type::LONG8 => self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| {
571                Ok(UnsignedBig(reader.read_u64()?))
572            }),
573            Type::SLONG8 => self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| {
574                Ok(SignedBig(reader.read_i64()?))
575            }),
576            Type::IFD => self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| {
577                Ok(Ifd(reader.read_u32()?))
578            }),
579            Type::IFD8 => self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| {
580                Ok(IfdBig(reader.read_u64()?))
581            }),
582            Type::UNDEFINED => {
583                self.decode_offset(self.count, bo, bigtiff, limits, reader, |reader| {
584                    let mut buf = [0; 1];
585                    reader.read_exact(&mut buf)?;
586                    Ok(Byte(buf[0]))
587                })
588            }
589            Type::ASCII => {
590                let n = usize::try_from(self.count)?;
591                if n > limits.decoding_buffer_size {
592                    return Err(TiffError::LimitsExceeded);
593                }
594
595                if bigtiff {
596                    reader.goto_offset(self.r(bo).read_u64()?)?
597                } else {
598                    reader.goto_offset(self.r(bo).read_u32()?.into())?
599                }
600
601                let mut out = vec![0; n];
602                reader.read_exact(&mut out)?;
603                // Strings may be null-terminated, so we trim anything downstream of the null byte
604                if let Some(first) = out.iter().position(|&b| b == 0) {
605                    out.truncate(first);
606                }
607                Ok(Ascii(String::from_utf8(out)?))
608            }
609        }
610    }
611
612    #[inline]
613    fn decode_offset<R, F>(
614        &self,
615        value_count: u64,
616        bo: ByteOrder,
617        bigtiff: bool,
618        limits: &super::Limits,
619        reader: &mut SmartReader<R>,
620        decode_fn: F,
621    ) -> TiffResult<Value>
622    where
623        R: Read + Seek,
624        F: Fn(&mut SmartReader<R>) -> TiffResult<Value>,
625    {
626        let value_count = usize::try_from(value_count)?;
627        if value_count > limits.decoding_buffer_size / mem::size_of::<Value>() {
628            return Err(TiffError::LimitsExceeded);
629        }
630
631        let mut v = Vec::with_capacity(value_count);
632
633        let offset = if bigtiff {
634            self.r(bo).read_u64()?
635        } else {
636            self.r(bo).read_u32()?.into()
637        };
638        reader.goto_offset(offset)?;
639
640        for _ in 0..value_count {
641            v.push(decode_fn(reader)?)
642        }
643        Ok(List(v))
644    }
645}
646
647/// Extracts a list of BYTE tags stored in an offset
648#[inline]
649fn offset_to_bytes(n: usize, entry: &Entry) -> TiffResult<Value> {
650    Ok(List(
651        entry.offset[0..n]
652            .iter()
653            .map(|&e| Unsigned(u32::from(e)))
654            .collect(),
655    ))
656}
657
658/// Extracts a list of SBYTE tags stored in an offset
659#[inline]
660fn offset_to_sbytes(n: usize, entry: &Entry) -> TiffResult<Value> {
661    Ok(List(
662        entry.offset[0..n]
663            .iter()
664            .map(|&e| Signed(i32::from(e as i8)))
665            .collect(),
666    ))
667}
668
669/// Type representing an Image File Directory
670pub type Directory = HashMap<Tag, Entry>;