Skip to main content

rawler/formats/tiff/
reader.rs

1// SPDX-License-Identifier: MIT
2// Copyright 2021 Daniel Vogelbacher <daniel@chaospixel.com>
3
4use super::{Entry, IFD, Result, TiffError, apply_corr, entry::RawEntry, file::TiffFile};
5use crate::{
6  bits::Endian,
7  tags::{ExifTag, TiffCommonTag, TiffTag},
8};
9use byteorder::{BigEndian, LittleEndian, ReadBytesExt};
10use serde::{Deserialize, Serialize};
11use std::io::{Cursor, Read, Seek, SeekFrom};
12
13pub trait TiffReader {
14  fn file(&self) -> &TiffFile;
15  fn file_mut(&mut self) -> &mut TiffFile;
16
17  fn chains(&self) -> &Vec<IFD> {
18    &self.file().chain
19  }
20
21  fn get_endian(&self) -> Endian {
22    self.root_ifd().endian
23  }
24
25  /// Returns a list of well-known tags representing SubIFDs.
26  fn wellknown_sub_ifd_tags(&self) -> Vec<u16> {
27    vec![
28      TiffCommonTag::SubIFDs.into(),
29      TiffCommonTag::ExifIFDPointer.into(),
30      ExifTag::GPSInfo.into(),
31      ExifTag::IccProfile.into(),
32    ]
33  }
34
35  fn root_ifd(&self) -> &IFD {
36    if self.file().chain.is_empty() {
37      panic!("TIFF must have at least one root IFD but the IFD list is empty");
38    }
39    &self.file().chain[0]
40  }
41
42  fn get_entry<T: TiffTag>(&self, tag: T) -> Option<&Entry> {
43    for ifd in &self.file().chain {
44      if let Some(x) = ifd.get_entry(tag) {
45        return Some(x);
46      }
47    }
48    None
49  }
50
51  fn get_entry_raw<'a, T: TiffTag, R: Read + Seek>(&'a self, tag: T, file: &mut R) -> Result<Option<RawEntry<'a>>> {
52    for ifd in &self.file().chain {
53      if let Some(entry) = ifd.get_entry_raw(tag, file)? {
54        return Ok(Some(entry));
55      }
56    }
57    Ok(None)
58  }
59
60  fn has_entry<T: TiffTag>(&self, tag: T) -> bool {
61    self.get_entry(tag).is_some()
62  }
63
64  fn find_ifds_with_tag<T: TiffTag>(&self, tag: T) -> Vec<&IFD> {
65    let mut ifds = Vec::new();
66    for ifd in &self.file().chain {
67      if ifd.has_entry(tag) {
68        ifds.push(ifd);
69      }
70      // Now search in all sub IFDs
71      for subs in ifd.sub_ifds() {
72        for ifd in subs.1 {
73          if ifd.has_entry(tag) {
74            ifds.push(ifd);
75          }
76        }
77      }
78    }
79    ifds
80  }
81
82  fn find_ifds_with_filter<F: Fn(&IFD) -> bool>(&self, filter: F) -> Vec<&IFD> {
83    let mut ifds = Vec::new();
84    for ifd in &self.file().chain {
85      if filter(ifd) {
86        ifds.push(ifd);
87      }
88      // Now search in all sub IFDs
89      for subs in ifd.sub_ifds() {
90        for ifd in subs.1 {
91          if filter(ifd) {
92            ifds.push(ifd);
93          }
94        }
95      }
96    }
97    ifds
98  }
99
100  fn find_ifd_with_new_subfile_type(&self, typ: u32) -> Option<&IFD> {
101    let list = self.find_ifds_with_tag(TiffCommonTag::NewSubFileType);
102    list
103      .iter()
104      .find(|ifd| ifd.get_entry(TiffCommonTag::NewSubFileType).expect("IFD must contain this entry").force_u32(0) == typ)
105      .copied()
106  }
107
108  // TODO: legacy wrapper
109  fn find_first_ifd<T: TiffTag>(&self, tag: T) -> Option<&IFD> {
110    self.find_first_ifd_with_tag(tag)
111  }
112
113  fn find_first_ifd_with_tag<T: TiffTag>(&self, tag: T) -> Option<&IFD> {
114    let ifds = self.find_ifds_with_tag(tag);
115    if ifds.is_empty() { None } else { Some(ifds[0]) }
116  }
117
118  fn get_first_entry(&self, _tag: u16) -> Option<Entry> {
119    unimplemented!();
120    /*
121    Some(Entry {
122      value: (32 as u16).into(),
123      embedded: None,
124    })
125     */
126  }
127
128  fn read_data<R: Read + Seek>(&self, file: &mut R, uncorr_offset: u32, buffer: &mut [u8]) -> Result<()> {
129    file.seek(SeekFrom::Start(apply_corr(uncorr_offset, self.file().corr) as u64))?;
130    file.read_exact(buffer)?;
131    Ok(())
132  }
133
134  fn parse_ifd<R: Read + Seek>(&self, reader: &mut R, offset: u32, base: u32, corr: i32, endian: Endian, sub_tags: &[u16]) -> Result<IFD> {
135    IFD::new(reader, offset, base, corr, endian, sub_tags)
136  }
137
138  /// Construct a TIFF reader from Read capable objects
139  ///
140  /// `corr` is a correction value that should be applied to offsets received
141  /// from file structure.
142  fn parse_file<R: Read + Seek>(&mut self, file: &mut R, max_chained: Option<usize>, sub_tags: &[u16]) -> Result<()> {
143    let endian = match file.read_u16::<LittleEndian>()? {
144      0x4949 => Endian::Little,
145      0x4d4d => Endian::Big,
146      x => {
147        return Err(TiffError::General(format!("TIFF: don't know marker 0x{:x}", x)));
148      }
149    };
150    let mut reader = EndianReader::new(file, endian);
151    let magic = reader.read_u16()?;
152    if magic != 42 {
153      //return Err(TiffError::General(format!("Invalid magic marker for TIFF: {}", magic)));
154    }
155    let mut next_ifd = reader.read_u32()?;
156    if next_ifd == 0 {
157      return Err(TiffError::General("Invalid TIFF header, contains no root IFD".to_string()));
158    }
159
160    let reader = reader.into_inner();
161
162    next_ifd = apply_corr(next_ifd, self.file().corr);
163    let mut chain = Vec::new();
164    while next_ifd != 0 {
165      // TODO: check if offset is in range
166      let mut multi_sub_tags = self.wellknown_sub_ifd_tags();
167      multi_sub_tags.extend_from_slice(sub_tags);
168      let ifd = IFD::new(reader, next_ifd, self.file().base, self.file().corr, endian, &multi_sub_tags)?;
169      if ifd.entries.is_empty() {
170        return Err(TiffError::General("TIFF is invalid, IFD must contain at least one entry".to_string()));
171      }
172      next_ifd = ifd.next_ifd;
173      chain.push(ifd);
174      if let Some(max) = max_chained {
175        if chain.len() > max {
176          break;
177        }
178      }
179    }
180
181    if chain.is_empty() {
182      return Err(TiffError::General("TIFF is invalid, must contain at least one IFD".to_string()));
183    }
184    self.file_mut().chain = chain;
185    Ok(())
186  }
187}
188
189/// Reader for TIFF files
190#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
191pub struct GenericTiffReader {
192  file: TiffFile,
193}
194
195impl TiffReader for GenericTiffReader {
196  fn file(&self) -> &TiffFile {
197    &self.file
198  }
199
200  fn file_mut(&mut self) -> &mut TiffFile {
201    &mut self.file
202  }
203}
204
205impl GenericTiffReader {
206  /// Check if buffer looks like a TIFF file
207  pub fn is_tiff<T: AsRef<[u8]>>(buffer: T) -> bool {
208    let buffer = buffer.as_ref();
209    buffer[0] == 0x49 || buffer[0] == 0x4d // TODO
210  }
211
212  pub fn little_endian(&self) -> bool {
213    self.file.chain.first().unwrap().endian == Endian::Little
214  }
215
216  /// Construct a TIFF reader from a byte buffer
217  ///
218  /// Byte buffer must be a full TIFF file structure, endianess is detected from TIFF
219  /// header.
220  ///
221  /// `corr` is a correction value that should be applied to offsets received
222  /// from file structure.
223  pub fn new_with_buffer<T: AsRef<[u8]>>(buffer: T, base: u32, corr: i32, max_chained: Option<usize>) -> Result<Self> {
224    let mut cursor = Cursor::new(buffer.as_ref());
225    cursor.seek(SeekFrom::Start(base as u64))?;
226    Self::new(&mut cursor, base, corr, max_chained, &[])
227  }
228
229  /// Construct a TIFF reader from Read capable objects
230  ///
231  /// `corr` is a correction value that should be applied to offsets received
232  /// from file structure.
233  pub fn new<R: Read + Seek>(file: &mut R, base: u32, corr: i32, max_chained: Option<usize>, sub_tags: &[u16]) -> Result<Self> {
234    let mut ins = Self {
235      file: TiffFile::new(base, corr),
236    };
237    ins.parse_file(file, max_chained, sub_tags)?;
238    Ok(ins)
239  }
240}
241
242pub trait ReadByteOrder {
243  fn read_u8(&mut self) -> std::io::Result<u8>;
244  fn read_i8(&mut self) -> std::io::Result<i8>;
245  fn read_u16(&mut self) -> std::io::Result<u16>;
246  fn read_i16(&mut self) -> std::io::Result<i16>;
247  fn read_u32(&mut self) -> std::io::Result<u32>;
248  fn read_i32(&mut self) -> std::io::Result<i32>;
249  fn read_u64(&mut self) -> std::io::Result<u64>;
250  fn read_i64(&mut self) -> std::io::Result<i64>;
251  fn read_f32(&mut self) -> std::io::Result<f32>;
252  fn read_f64(&mut self) -> std::io::Result<f64>;
253
254  fn read_u8_into(&mut self, dst: &mut [u8]) -> std::io::Result<()>;
255  fn read_i8_into(&mut self, dst: &mut [i8]) -> std::io::Result<()>;
256  fn read_u16_into(&mut self, dst: &mut [u16]) -> std::io::Result<()>;
257  fn read_i16_into(&mut self, dst: &mut [i16]) -> std::io::Result<()>;
258  fn read_u32_into(&mut self, dst: &mut [u32]) -> std::io::Result<()>;
259  fn read_i32_into(&mut self, dst: &mut [i32]) -> std::io::Result<()>;
260  fn read_u64_into(&mut self, dst: &mut [u64]) -> std::io::Result<()>;
261  fn read_i64_into(&mut self, dst: &mut [i64]) -> std::io::Result<()>;
262  fn read_f32_into(&mut self, dst: &mut [f32]) -> std::io::Result<()>;
263  fn read_f64_into(&mut self, dst: &mut [f64]) -> std::io::Result<()>;
264}
265
266pub struct EndianReader<'a, R: Read + Seek + 'a> {
267  endian: Endian,
268  inner: &'a mut R,
269}
270
271impl<'a, R: Read + Seek + 'a> EndianReader<'a, R> {
272  pub fn new(inner: &'a mut R, endian: Endian) -> Self {
273    Self { endian, inner }
274  }
275
276  pub fn into_inner(self) -> &'a mut R {
277    self.inner
278  }
279
280  pub fn inner(&'a mut self) -> &'a mut R {
281    self.inner
282  }
283
284  pub fn position(&mut self) -> Result<u32> {
285    Ok(self.inner.stream_position().map(|v| v as u32)?)
286  }
287
288  // TODO: try_from?
289
290  pub fn goto(&mut self, offset: u32) -> Result<()> {
291    self.inner.seek(SeekFrom::Start(offset as u64))?;
292    Ok(())
293
294    // TODO: try_from?
295  }
296}
297
298impl<'a, R: Read + Seek + 'a> ReadByteOrder for EndianReader<'a, R> {
299  fn read_u16(&mut self) -> std::io::Result<u16> {
300    match self.endian {
301      Endian::Little => self.inner.read_u16::<LittleEndian>(),
302      Endian::Big => self.inner.read_u16::<BigEndian>(),
303    }
304  }
305
306  fn read_u8(&mut self) -> std::io::Result<u8> {
307    self.inner.read_u8()
308  }
309
310  fn read_i8(&mut self) -> std::io::Result<i8> {
311    match self.endian {
312      Endian::Little => self.inner.read_i8(),
313      Endian::Big => self.inner.read_i8(),
314    }
315  }
316
317  fn read_i16(&mut self) -> std::io::Result<i16> {
318    match self.endian {
319      Endian::Little => self.inner.read_i16::<LittleEndian>(),
320      Endian::Big => self.inner.read_i16::<BigEndian>(),
321    }
322  }
323
324  fn read_u32(&mut self) -> std::io::Result<u32> {
325    match self.endian {
326      Endian::Little => self.inner.read_u32::<LittleEndian>(),
327      Endian::Big => self.inner.read_u32::<BigEndian>(),
328    }
329  }
330
331  fn read_i32(&mut self) -> std::io::Result<i32> {
332    match self.endian {
333      Endian::Little => self.inner.read_i32::<LittleEndian>(),
334      Endian::Big => self.inner.read_i32::<BigEndian>(),
335    }
336  }
337
338  fn read_u64(&mut self) -> std::io::Result<u64> {
339    match self.endian {
340      Endian::Little => self.inner.read_u64::<LittleEndian>(),
341      Endian::Big => self.inner.read_u64::<BigEndian>(),
342    }
343  }
344
345  fn read_i64(&mut self) -> std::io::Result<i64> {
346    match self.endian {
347      Endian::Little => self.inner.read_i64::<LittleEndian>(),
348      Endian::Big => self.inner.read_i64::<BigEndian>(),
349    }
350  }
351
352  fn read_f32(&mut self) -> std::io::Result<f32> {
353    match self.endian {
354      Endian::Little => self.inner.read_f32::<LittleEndian>(),
355      Endian::Big => self.inner.read_f32::<BigEndian>(),
356    }
357  }
358
359  fn read_f64(&mut self) -> std::io::Result<f64> {
360    match self.endian {
361      Endian::Little => self.inner.read_f64::<LittleEndian>(),
362      Endian::Big => self.inner.read_f64::<BigEndian>(),
363    }
364  }
365
366  fn read_u8_into(&mut self, dst: &mut [u8]) -> std::io::Result<()> {
367    self.inner.read_exact(dst)
368  }
369
370  fn read_i8_into(&mut self, dst: &mut [i8]) -> std::io::Result<()> {
371    self.inner.read_i8_into(dst)
372  }
373
374  fn read_u16_into(&mut self, dst: &mut [u16]) -> std::io::Result<()> {
375    match self.endian {
376      Endian::Little => self.inner.read_u16_into::<LittleEndian>(dst),
377      Endian::Big => self.inner.read_u16_into::<BigEndian>(dst),
378    }
379  }
380
381  fn read_i16_into(&mut self, dst: &mut [i16]) -> std::io::Result<()> {
382    match self.endian {
383      Endian::Little => self.inner.read_i16_into::<LittleEndian>(dst),
384      Endian::Big => self.inner.read_i16_into::<BigEndian>(dst),
385    }
386  }
387
388  fn read_u32_into(&mut self, dst: &mut [u32]) -> std::io::Result<()> {
389    match self.endian {
390      Endian::Little => self.inner.read_u32_into::<LittleEndian>(dst),
391      Endian::Big => self.inner.read_u32_into::<BigEndian>(dst),
392    }
393  }
394
395  fn read_i32_into(&mut self, dst: &mut [i32]) -> std::io::Result<()> {
396    match self.endian {
397      Endian::Little => self.inner.read_i32_into::<LittleEndian>(dst),
398      Endian::Big => self.inner.read_i32_into::<BigEndian>(dst),
399    }
400  }
401
402  fn read_u64_into(&mut self, dst: &mut [u64]) -> std::io::Result<()> {
403    match self.endian {
404      Endian::Little => self.inner.read_u64_into::<LittleEndian>(dst),
405      Endian::Big => self.inner.read_u64_into::<BigEndian>(dst),
406    }
407  }
408
409  fn read_i64_into(&mut self, dst: &mut [i64]) -> std::io::Result<()> {
410    match self.endian {
411      Endian::Little => self.inner.read_i64_into::<LittleEndian>(dst),
412      Endian::Big => self.inner.read_i64_into::<BigEndian>(dst),
413    }
414  }
415
416  fn read_f32_into(&mut self, dst: &mut [f32]) -> std::io::Result<()> {
417    match self.endian {
418      Endian::Little => self.inner.read_f32_into::<LittleEndian>(dst),
419      Endian::Big => self.inner.read_f32_into::<BigEndian>(dst),
420    }
421  }
422
423  fn read_f64_into(&mut self, dst: &mut [f64]) -> std::io::Result<()> {
424    match self.endian {
425      Endian::Little => self.inner.read_f64_into::<LittleEndian>(dst),
426      Endian::Big => self.inner.read_f64_into::<BigEndian>(dst),
427    }
428  }
429}