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 entryimpl Iterator.offset[0..n]
652 .iter()
653 .map(|&e: u8| 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 entryimpl Iterator.offset[0..n]
663 .iter()
664 .map(|&e: u8| Signed(i32::from(e as i8)))
665 .collect(),
666 ))
667}
668
669/// Type representing an Image File Directory
670pub type Directory = HashMap<Tag, Entry>;
671