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 const 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, 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 { 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); 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 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 { 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);}, }
220 }
221 }
222 } else if entry.tag == t(Tag::Makernote) {
223 if depth < 10 { 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);}, }
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 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 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 if data[0..5] == b"EPSON"[..] {
274 off += 8;
275 }
276
277 if data[0..4] == b"AOC\0"[..] {
279 off +=4;
280 }
281
282 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 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); 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, 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, 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 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 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 { 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 { 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 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}