rawloader/decoders/
tiff.rs

1use std::collections::HashMap;
2use std::str;
3
4use crate::decoders::basics::*;
5
6#[derive(Debug, Copy, Clone, PartialEq, enumn::N)]
7#[repr(u16)]
8pub enum Tag {
9  PanaWidth        = 0x0002,
10  PanaLength       = 0x0003,
11  NefWB0           = 0x000C,
12  PanaWBsR         = 0x0011,
13  PanaWBsB         = 0x0012,
14  NrwWB            = 0x0014,
15  NefSerial        = 0x001d,
16  PanaWBs2R        = 0x0024,
17  PanaWBs2G        = 0x0025,
18  PanaWBs2B        = 0x0026,
19  Cr2PowerShotWB   = 0x0029,
20  NewSubFileType   = 0x00FE,
21  Cr2OldOffset     = 0x0081,
22  NefMeta1         = 0x008c,
23  NefMeta2         = 0x0096,
24  NefWB1           = 0x0097,
25  Cr2OldWB         = 0x00A4,
26  NefKey           = 0x00a7,
27  ImageWidth       = 0x0100,
28  ImageLength      = 0x0101,
29  BitsPerSample    = 0x0102,
30  Compression      = 0x0103,
31  PhotometricInt   = 0x0106,
32  Make             = 0x010F,
33  Model            = 0x0110,
34  StripOffsets     = 0x0111,
35  Orientation      = 0x0112,
36  SamplesPerPixel  = 0x0115,
37  StripByteCounts  = 0x0117,
38  PanaOffsets      = 0x0118,
39  GrayResponse     = 0x0123,
40  Software         = 0x0131,
41  TileWidth        = 0x0142,
42  TileLength       = 0x0143,
43  TileOffsets      = 0x0144,
44  SubIFDs          = 0x014A,
45  PefBlackLevels   = 0x0200,
46  PefWB            = 0x0201,
47  PefHuffman       = 0x0220,
48  Xmp              = 0x02BC,
49  DcrWB            = 0x03FD,
50  OrfBlackLevels   = 0x0600,
51  DcrLinearization = 0x090D,
52  EpsonWB          = 0x0E80,
53  KodakWB          = 0x0F00,
54  OlympusRedMul    = 0x1017,
55  OlympusBlueMul   = 0x1018,
56  OlympusImgProc   = 0x2040,
57  RafOldWB         = 0x2ff0,
58  Cr2ColorData     = 0x4001,
59  SonyCurve        = 0x7010,
60  SonyOffset       = 0x7200,
61  SonyLength       = 0x7201,
62  SonyKey          = 0x7221,
63  SonyGRBG         = 0x7303,
64  SonyRGGB         = 0x7313,
65  CFAPattern       = 0x828E,
66  KodakIFD         = 0x8290,
67  LeafMetadata     = 0x8606,
68  ExifIFDPointer   = 0x8769,
69  Makernote        = 0x927C,
70  SrwSensorAreas   = 0xA010,
71  SrwRGGBLevels    = 0xA021,
72  SrwRGGBBlacks    = 0xA028,
73  Cr2Id            = 0xc5d8,
74  DNGVersion       = 0xC612,
75  Linearization    = 0xC618,
76  BlackLevels      = 0xC61A,
77  WhiteLevel       = 0xC61D,
78  ColorMatrix1     = 0xC621,
79  ColorMatrix2     = 0xC622,
80  AsShotNeutral    = 0xC628,
81  DNGPrivateArea   = 0xC634,
82  Cr2StripeWidths  = 0xC640,
83  ActiveArea       = 0xC68D,
84  MaskedAreas      = 0xC68E,
85  RafRawSubIFD     = 0xF000,
86  RafImageWidth    = 0xF001,
87  RafImageLength   = 0xF002,
88  RafBitsPerSample = 0xF003,
89  RafOffsets       = 0xF007,
90  RafWBGRB         = 0xF00E,
91  KdcWB            = 0xFA2A,
92  KdcWidth         = 0xFD00,
93  KdcLength        = 0xFD01,
94  KdcOffset        = 0xFD04,
95  KdcIFD           = 0xFE00,
96}
97
98                          // 0-1-2-3-4-5-6-7-8-9-10-11-12-13
99const DATASHIFTS: [u8;14] = [0,0,0,1,2,3,0,0,1,2, 3, 2, 3, 2];
100
101fn t (tag: Tag) -> u16 {
102  tag as u16
103}
104
105#[derive(Debug, Copy, Clone)]
106pub struct TiffEntry<'a> {
107  tag: u16,
108  typ: u16,
109  count: usize,
110  parent_offset: usize,
111  doffset: usize,
112  data: &'a [u8],
113  endian: Endian,
114}
115
116#[derive(Debug, Clone)]
117pub struct TiffIFD<'a> {
118  entries: HashMap<u16,TiffEntry<'a>>,
119  subifds: Vec<TiffIFD<'a>>,
120  nextifd: usize,
121  start_offset: usize,
122  endian: Endian,
123}
124
125impl<'a> TiffIFD<'a> {
126  pub fn new_file(buf: &'a[u8]) -> Result<TiffIFD<'a>, String> {
127    if buf[0..8] == b"FUJIFILM"[..] {
128      let ifd1 = TiffIFD::new_root(buf, (BEu32(buf, 84)+12) as usize)?;
129      let endian = ifd1.get_endian();
130      let mut subifds = vec![ifd1];
131      let mut entries = HashMap::new();
132
133      let ioffset = BEu32(buf, 100) as usize;
134      match TiffIFD::new_root(buf, ioffset) {
135        Ok(val) => {subifds.push(val);}
136        Err(_) => {
137          entries.insert(Tag::RafOffsets as u16, TiffEntry{
138            tag: t(Tag::RafOffsets),
139            typ: 4, // Long
140            count: 1,
141            parent_offset: 0,
142            doffset: 100,
143            data: &buf[100..104],
144            endian: BIG_ENDIAN,
145          });
146        },
147      }
148      match TiffIFD::new_fuji(buf, BEu32(buf, 92) as usize) {
149        Ok(val) => subifds.push(val),
150        Err(_) => {}
151      }
152
153      Ok(TiffIFD {
154        entries: entries,
155        subifds: subifds,
156        nextifd: 0,
157        start_offset: 0,
158        endian: endian,
159      })
160    } else {
161      TiffIFD::new_root(buf, 0)
162    }
163  }
164
165  pub fn new_root(buf: &'a[u8], offset: usize) -> Result<TiffIFD<'a>, String> {
166    let mut subifds = Vec::new();
167
168    let endian = match LEu16(buf, offset) {
169      0x4949 => LITTLE_ENDIAN,
170      0x4d4d => BIG_ENDIAN,
171      x => {return Err(format!("TIFF: don't know marker 0x{:x}", x).to_string())},
172    };
173    let mut nextifd = endian.ru32(buf, offset+4) as usize;
174    for _ in 0..100 { // Never read more than 100 IFDs
175      let ifd = TiffIFD::new(&buf[offset..], nextifd, 0, offset, 0, endian)?;
176      nextifd = ifd.nextifd;
177      subifds.push(ifd);
178      if nextifd == 0 {
179        break
180      }
181    }
182
183    Ok(TiffIFD {
184      entries: HashMap::new(),
185      subifds: subifds,
186      nextifd: 0,
187      start_offset: offset,
188      endian: endian,
189    })
190  }
191
192  pub fn new(buf: &'a[u8], offset: usize, base_offset: usize, start_offset: usize, depth: u32, e: Endian) -> Result<TiffIFD<'a>, String> {
193    let mut entries = HashMap::new();
194    let mut subifds = Vec::new();
195
196    let num = e.ru16(buf, offset); // Directory entries in this IFD
197    if num > 4000 {
198      return Err(format!("too many entries in IFD ({})", num).to_string())
199    }
200    for i in 0..num {
201      let entry_offset: usize = offset + 2 + (i as usize)*12;
202      if Tag::n(e.ru16(buf, entry_offset)).is_none() {
203        // Skip entries we don't know about to speedup decoding
204        continue;
205      }
206      let entry = TiffEntry::new(buf, entry_offset, base_offset, offset, e);
207
208      if entry.tag == t(Tag::SubIFDs)
209      || entry.tag == t(Tag::ExifIFDPointer)
210      || entry.tag == t(Tag::RafRawSubIFD)
211      || entry.tag == t(Tag::KodakIFD)
212      || entry.tag == t(Tag::KdcIFD) {
213        if depth < 10 { // Avoid infinite looping IFDs
214          for i in 0..entry.count {
215            let ifd = TiffIFD::new(buf, entry.get_u32(i as usize) as usize, base_offset, start_offset, depth+1, e);
216            match ifd {
217              Ok(val) => {subifds.push(val);},
218              Err(_) => {entries.insert(entry.tag, entry);}, // Ignore unparsable IFDs
219            }
220          }
221        }
222      } else if entry.tag == t(Tag::Makernote) {
223        if depth < 10 { // Avoid infinite looping IFDs
224          let ifd = TiffIFD::new_makernote(buf, entry.doffset(), base_offset, depth+1, e);
225          match ifd {
226            Ok(val) => {subifds.push(val);},
227            Err(_) => {entries.insert(entry.tag, entry);}, // Ignore unparsable IFDs
228          }
229        }
230      } else {
231        entries.insert(entry.tag, entry);
232      }
233    }
234
235    Ok(TiffIFD {
236      entries: entries,
237      subifds: subifds,
238      nextifd: e.ru32(buf, offset + (2+num*12) as usize) as usize,
239      start_offset: start_offset,
240      endian: e,
241    })
242  }
243
244  pub fn new_makernote(buf: &'a[u8], offset: usize, base_offset: usize, depth: u32, e: Endian) -> Result<TiffIFD<'a>, String> {
245    let mut off = 0;
246    let data = &buf[offset..];
247    let mut endian = e;
248
249    // Olympus starts the makernote with their own name, sometimes truncated
250    if data[0..5] == b"OLYMP"[..] {
251      off += 8;
252      if data[0..7] == b"OLYMPUS"[..] {
253        off += 4;
254      }
255
256      let mut mainifd = TiffIFD::new(buf, offset+off, base_offset, 0, depth, endian)?;
257
258      if off == 12 {
259        // Parse the Olympus ImgProc section if it exists
260        let ioff = if let Some(entry) = mainifd.find_entry(Tag::OlympusImgProc) {
261          entry.get_usize(0)
262        } else { 0 };
263        if ioff != 0 {
264          let iprocifd = TiffIFD::new(&buf[offset+ioff..], 0, ioff, 0, depth, endian)?;
265          mainifd.subifds.push(iprocifd);
266        }
267      }
268
269      return Ok(mainifd)
270    }
271
272    // Epson starts the makernote with its own name
273    if data[0..5] == b"EPSON"[..] {
274      off += 8;
275    }
276
277    // Pentax makernote starts with AOC\0 - If it's there, skip it
278    if data[0..4] == b"AOC\0"[..] {
279      off +=4;
280    }
281
282    // Pentax can also start with PENTAX and in that case uses different offsets
283    if data[0..6] == b"PENTAX"[..] {
284      off += 8;
285      let endian = if data[off..off+2] == b"II"[..] {LITTLE_ENDIAN} else {BIG_ENDIAN};
286      return TiffIFD::new(&buf[offset..], 10, base_offset, 0, depth, endian)
287    }
288
289    if data[0..7] == b"Nikon\0\x02"[..] {
290      off += 10;
291      let endian = if data[off..off+2] == b"II"[..] {LITTLE_ENDIAN} else {BIG_ENDIAN};
292      return TiffIFD::new(&buf[off+offset..], 8, base_offset, 0, depth, endian)
293    }
294
295    // Some have MM or II to indicate endianness - read that
296    if data[off..off+2] == b"II"[..] {
297      off +=2;
298      endian = LITTLE_ENDIAN;
299    } if data[off..off+2] == b"MM"[..] {
300      off +=2;
301      endian = BIG_ENDIAN;
302    }
303
304    TiffIFD::new(buf, offset+off, base_offset, 0, depth, endian)
305  }
306
307  pub fn new_fuji(buf: &'a[u8], offset: usize) -> Result<TiffIFD<'a>, String> {
308    let mut entries = HashMap::new();
309    let num = BEu32(buf, offset); // Directory entries in this IFD
310    if num > 4000 {
311      return Err(format!("too many entries in IFD ({})", num).to_string())
312    }
313    let mut off = offset+4;
314    for _ in 0..num {
315      let tag = BEu16(buf, off);
316      let len = BEu16(buf, off+2);
317      if tag == t(Tag::ImageWidth) {
318        entries.insert(t(Tag::ImageWidth), TiffEntry {
319          tag: t(Tag::ImageWidth),
320          typ: 3, // Short
321          count: 2,
322          parent_offset: 0,
323          doffset: off+4,
324          data: &buf[off+4..off+8],
325          endian: BIG_ENDIAN,
326        });
327      } else if tag == t(Tag::RafOldWB) {
328        entries.insert(t(Tag::RafOldWB), TiffEntry {
329          tag: t(Tag::RafOldWB),
330          typ: 3, // Short
331          count: 4,
332          parent_offset: 0,
333          doffset: off+4,
334          data: &buf[off+4..off+12],
335          endian: BIG_ENDIAN,
336        });
337      }
338      off += (len+4) as usize;
339    }
340
341    Ok(TiffIFD {
342      entries: entries,
343      subifds: Vec::new(),
344      nextifd: 0,
345      start_offset: 0,
346      endian: BIG_ENDIAN,
347    })
348  }
349
350  pub fn find_entry(&self, tag: Tag) -> Option<&TiffEntry> {
351    if self.entries.contains_key(&t(tag)) {
352      self.entries.get(&t(tag))
353    } else {
354      for ifd in &self.subifds {
355        match ifd.find_entry(tag) {
356          Some(x) => return Some(x),
357          None => {},
358        }
359      }
360      None
361    }
362  }
363
364  pub fn has_entry(&self, tag: Tag) -> bool {
365    self.find_entry(tag).is_some()
366  }
367
368  pub fn find_ifds_with_tag(&self, tag: Tag) -> Vec<&TiffIFD> {
369    let mut ifds = Vec::new();
370    if self.entries.contains_key(&t(tag)) {
371      ifds.push(self);
372    }
373    for ifd in &self.subifds {
374      if ifd.entries.contains_key(&t(tag)) {
375        ifds.push(ifd);
376      }
377      ifds.extend(ifd.find_ifds_with_tag(tag));
378    }
379    ifds
380  }
381
382  pub fn find_first_ifd(&self, tag: Tag) -> Option<&TiffIFD> {
383    let ifds = self.find_ifds_with_tag(tag);
384    if ifds.len() == 0 {
385      None
386    } else {
387      Some(ifds[0])
388    }
389  }
390
391  pub fn get_endian(&self) -> Endian { self.endian }
392  pub fn little_endian(&self) -> bool { self.endian.little() }
393  pub fn start_offset(&self) -> usize { self.start_offset }
394}
395
396impl<'a> TiffEntry<'a> {
397  pub fn new(buf: &'a[u8], offset: usize, base_offset: usize, parent_offset: usize, e: Endian) -> TiffEntry<'a> {
398    let tag = e.ru16(buf, offset);
399    let mut typ = e.ru16(buf, offset+2);
400    let count = e.ru32(buf, offset+4) as usize;
401
402    // If we don't know the type assume byte data
403    if typ == 0 || typ > 13 {
404      typ = 1;
405    }
406
407    let bytesize: usize = count << DATASHIFTS[typ as usize];
408    let doffset: usize = if bytesize <= 4 {
409      offset + 8
410    } else {
411      (e.ru32(buf, offset+8) as usize) - base_offset
412    };
413
414    TiffEntry {
415      tag: tag,
416      typ: typ,
417      count: count,
418      parent_offset: parent_offset,
419      doffset: doffset,
420      data: &buf[doffset .. doffset+bytesize],
421      endian: e,
422    }
423  }
424
425  pub fn copy_with_new_data(&self, data: &'a[u8]) -> TiffEntry<'a> {
426    let mut copy = self.clone();
427    copy.data = data;
428    copy
429  }
430
431  pub fn copy_offset_from_parent(&self, buffer: &'a[u8]) -> TiffEntry<'a> {
432    self.copy_with_new_data(&buffer[self.parent_offset+self.doffset..])
433  }
434
435  pub fn doffset(&self) -> usize { self.doffset }
436  pub fn parent_offset(&self) -> usize { self.parent_offset }
437  pub fn count(&self) -> usize { self.count }
438  //pub fn typ(&self) -> u16 { self.typ }
439
440  pub fn get_u16(&self, idx: usize) -> u16 {
441    match self.typ {
442      1                  => self.data[idx] as u16,
443      3 | 8              => self.get_force_u16(idx),
444      _ => panic!("Trying to read typ {} for a u32", self.typ),
445    }
446  }
447
448  pub fn get_u32(&self, idx: usize) -> u32 {
449    match self.typ {
450      1 | 3 | 8          => self.get_u16(idx) as u32,
451      4 | 7 | 9 | 13     => self.get_force_u32(idx),
452      _ => panic!("Trying to read typ {} for a u32", self.typ),
453    }
454  }
455
456  pub fn get_usize(&self, idx: usize) -> usize { self.get_u32(idx) as usize }
457
458  pub fn get_force_u32(&self, idx: usize) -> u32 {
459    self.endian.ru32(self.data, idx*4)
460  }
461
462  pub fn get_force_u16(&self, idx: usize) -> u16 {
463    self.endian.ru16(self.data, idx*2)
464  }
465
466  pub fn get_f32(&self, idx: usize) -> f32 {
467    if self.typ == 5 { // Rational
468      let a = self.endian.ru32(self.data, idx*8) as f32;
469      let b = self.endian.ru32(self.data, idx*8+4) as f32;
470      a / b
471    } else if self.typ == 10 { // Signed Rational
472      let a = self.endian.ri32(self.data, idx*8) as f32;
473      let b = self.endian.ri32(self.data, idx*8+4) as f32;
474      a / b
475    } else {
476      self.get_u32(idx) as f32
477    }
478  }
479
480  pub fn get_str(&self) -> &str {
481    // Truncate the string when there are \0 bytes
482    let len = match self.data.iter().position(|&x| x == 0) {
483      Some(p) => p,
484      None => self.data.len(),
485    };
486    match str::from_utf8(&self.data[0..len]) {
487      Ok(val) => val.trim(),
488      Err(err) => std::panic::panic_any(err),
489    }
490  }
491
492  pub fn get_data(&self) -> &[u8] {
493    self.data
494  }
495}