tiff_encoder/ifd/
types.rs

1//! Representations of TIFF field data types.
2//!
3//! Each type comes with convenience functions in order
4//! to facilitate its use.
5//!
6//! Every TIFF data type has to implement [`TiffType`] in order to be
7//! usable in the crate.
8//!
9//! [`TiffType`]: trait.TiffType.html
10
11use std::convert::AsRef;
12use std::io;
13
14use crate::ifd::values::TiffTypeValues;
15use crate::write::EndianFile;
16
17/// A type of data for TIFF fields.
18///
19/// Other types that might come to exist can be easily implemented by
20/// implementing this trait.
21pub trait TiffType {
22    /// The TIFF 16-bit code that identifies the type.
23    fn id() -> u16;
24
25    /// The number of bytes occupied by a single value of this type.
26    fn size() -> u32;
27
28    /// The function that writes this type to a given [`EndianFile`].
29    ///
30    /// # Panics
31    ///
32    /// Will `panic` if the number of bytes written to the file is
33    /// different than the number of bytes specified in [`size()`].
34    ///
35    /// [`EndianFile`]: ../../struct.EndianFile.html
36    /// [`size()`]: #tymethod.size
37    fn write_to(self, file: &mut EndianFile) -> io::Result<()>;
38}
39
40/// 8-bit unsigned integer.
41#[derive(Debug, PartialEq)]
42pub struct BYTE(pub u8);
43impl BYTE {
44    /// Constructs a [`TiffTypeValues`] of `BYTE`s from a vector of
45    /// bytes.
46    ///
47    /// [`TiffTypeValues`]: ../values/struct.TiffTypeValues.html
48    pub fn values<T: AsRef<[u8]>>(values: T) -> TiffTypeValues<BYTE> {
49        TiffTypeValues::new(values.as_ref().iter().map(|&value| BYTE(value)).collect())
50    }
51    /// Constructs a [`TiffTypeValues`] consisting of a single `BYTE`.
52    ///
53    /// In other words, marks this `BYTE` as the single value of its
54    /// field.
55    ///
56    /// [`TiffTypeValues`]: ../values/struct.TiffTypeValues.html
57    pub fn single(value: u8) -> TiffTypeValues<BYTE> {
58        TiffTypeValues::new(vec![BYTE(value)])
59    }
60}
61impl TiffType for BYTE {
62    fn id() -> u16 {
63        1
64    }
65    fn size() -> u32 {
66        1
67    }
68    fn write_to(self, file: &mut EndianFile) -> io::Result<()> {
69        file.write_u8(self.0)
70    }
71}
72/// Convenient macro to declare an IFD entry of [`BYTE`] values.
73///
74/// [`BYTE`]: ifd/types/struct.BYTE.html
75#[macro_export]
76macro_rules! BYTE {
77    ($($values: expr),+) => {
78        $crate::ifd::values::TiffTypeValues::new(vec![$($crate::ifd::types::BYTE($values)),+])
79    };
80}
81
82/// 8-bit byte that contains a 7-bit ASCII code.
83///
84/// According the TIFF specification, the last byte
85/// of a field of `ASCII`s must be `NUL` (binary zero, '\0').
86#[derive(Debug, PartialEq)]
87pub struct ASCII(u8);
88impl ASCII {
89    /// Constructs a [`TiffTypeValues`] of `ASCII`s from a `&str`.
90    ///
91    /// If the string doesn't already end with a `NUL` value, it will
92    /// be added automatically.
93    ///
94    /// [`TiffTypeValues`]: ../values/struct.TiffTypeValues.html
95    pub fn from_str(s: &str) -> TiffTypeValues<ASCII> {
96        let mut values = Vec::with_capacity(s.chars().count());
97        for c in s.chars() {
98            if c >= (128 as char) {
99                panic!("String contains non-ASCII character {}.", c)
100            }
101            values.push(c as u8);
102        }
103        Self::values(values)
104    }
105    /// Constructs a [`TiffTypeValues`] of `ASCII`s from a vector of
106    /// bytes.
107    ///
108    /// If last value isn't already a `NUL` value, a `NUL` value will
109    /// be added automatically after the last value.
110    ///
111    /// [`TiffTypeValues`]: ../values/struct.TiffTypeValues.html
112    pub fn values<T: AsRef<[u8]>>(values: T) -> TiffTypeValues<ASCII> {
113        let values = values.as_ref();
114        if values.len() == 0 {
115            panic!("Cannot create an empty instance of TiffTypeValues.")
116        }
117
118        // TIFF ASCIIs must end with a NUL character.
119        // If the user doesn't add it, add it automatically.
120        let add_nul = *values.last().unwrap() != 0;
121        let mut values: Vec<_> = values.iter().map(|&value| ASCII::new(value)).collect();
122        if add_nul {
123            values.push(ASCII::new(0))
124        }
125        TiffTypeValues::new(values)
126    }
127    /// Creates an `ASCII`s value from a byte.
128    ///
129    /// # Panics
130    ///
131    /// An ASCII value only uses 7 bytes. Trying to create an
132    /// `ASCII` from values bigger than 127 will `panic`.
133    pub fn new(value: u8) -> ASCII {
134        if value >= 128 {
135            panic!("Tried to create an ASCII encoded by the value {}.\n An ASCII value can only range from 0 to 127.", value);
136        }
137        ASCII(value)
138    }
139}
140impl TiffType for ASCII {
141    fn id() -> u16 {
142        2
143    }
144    fn size() -> u32 {
145        1
146    }
147    fn write_to(self, file: &mut EndianFile) -> io::Result<()> {
148        file.write_u8(self.0)
149    }
150}
151/// Convenient macro to declare an IFD entry of [`ASCII`] values.
152///
153/// [`ASCII`]: ifd/types/struct.ASCII.html
154#[macro_export]
155macro_rules! ASCII {
156    ($string: expr) => {
157        $crate::ifd::types::ASCII::from_str($string)
158    };
159}
160
161/// 16-bit (2-byte) unsigned integer.
162#[derive(Debug, PartialEq)]
163pub struct SHORT(pub u16);
164impl SHORT {
165    /// Constructs a [`TiffTypeValues`] of `SHORTS`s from a vector of
166    /// `u16`.
167    ///
168    /// [`TiffTypeValues`]: ../values/struct.TiffTypeValues.html
169    pub fn values<T: AsRef<[u16]>>(values: T) -> TiffTypeValues<SHORT> {
170        TiffTypeValues::new(values.as_ref().iter().map(|&value| SHORT(value)).collect())
171    }
172
173    /// Constructs a [`TiffTypeValues`] consisting of a single `SHORT`.
174    ///
175    /// In other words, marks this `SHORT` as the single value of its
176    /// field.
177    ///
178    /// [`TiffTypeValues`]: ../values/struct.TiffTypeValues.html
179    pub fn single(value: u16) -> TiffTypeValues<SHORT> {
180        TiffTypeValues::new(vec![SHORT(value)])
181    }
182}
183impl TiffType for SHORT {
184    fn id() -> u16 {
185        3
186    }
187    fn size() -> u32 {
188        2
189    }
190    fn write_to(self, file: &mut EndianFile) -> io::Result<()> {
191        file.write_u16(self.0)
192    }
193}
194/// Convenient macro to declare an IFD entry of [`SHORT`] values.
195///
196/// [`SHORT`]: ifd/types/struct.SHORT.html
197#[macro_export]
198macro_rules! SHORT {
199    ($($values: expr),+) => {
200        $crate::ifd::values::TiffTypeValues::new(vec![$($crate::ifd::types::SHORT($values)),+])
201    };
202}
203
204/// 32-bit (4-byte) unsigned integer.
205#[derive(Debug, PartialEq)]
206pub struct LONG(pub u32);
207impl LONG {
208    /// Constructs a [`TiffTypeValues`] of `LONG`s from a vector of
209    /// `u32`.
210    ///
211    /// [`TiffTypeValues`]: ../values/struct.TiffTypeValues.html
212    pub fn values<T: AsRef<[u32]>>(values: T) -> TiffTypeValues<LONG> {
213        TiffTypeValues::new(values.as_ref().iter().map(|&value| LONG(value)).collect())
214    }
215
216    /// Constructs a [`TiffTypeValues`] consisting of a single `LONG`.
217    ///
218    /// In other words, marks this `LONG` as the single value of its
219    /// field.
220    ///
221    /// [`TiffTypeValues`]: ../values/struct.TiffTypeValues.html
222    pub fn single(value: u32) -> TiffTypeValues<LONG> {
223        TiffTypeValues::new(vec![LONG(value)])
224    }
225}
226impl TiffType for LONG {
227    fn id() -> u16 {
228        4
229    }
230    fn size() -> u32 {
231        4
232    }
233    fn write_to(self, file: &mut EndianFile) -> io::Result<()> {
234        file.write_u32(self.0)
235    }
236}
237/// Convenient macro to declare an IFD entry of [`LONG`] values.
238///
239/// [`LONG`]: ifd/types/struct.BYTE.html
240#[macro_export]
241macro_rules! LONG {
242    ($($values: expr),+) => {
243        $crate::ifd::values::TiffTypeValues::new(vec![$($crate::ifd::types::LONG($values)),+])
244    };
245}
246
247/// Two LONGs representing, respectively, the numerator and the denominator of a fraction.
248#[derive(Debug, PartialEq)]
249pub struct RATIONAL {
250    pub numerator: u32,
251    pub denominator: u32,
252}
253impl RATIONAL {
254    /// Constructs a [`TiffTypeValues`] of `RATIONAL`s from a vector of
255    /// pairs (numerator, denominator). Both must be `u32` values.
256    ///
257    /// [`TiffTypeValues`]: ../values/struct.TiffTypeValues.html
258    pub fn values<T: AsRef<[(u32, u32)]>>(values: T) -> TiffTypeValues<RATIONAL> {
259        TiffTypeValues::new(
260            values
261                .as_ref()
262                .iter()
263                .map(|&(numerator, denominator)| RATIONAL {
264                    numerator,
265                    denominator,
266                })
267                .collect(),
268        )
269    }
270
271    /// Constructs a [`TiffTypeValues`] consisting of a single `RATIONAL`
272    /// from a pair (numerator, denominator). Both values must be `u32`.
273    ///
274    /// In other words, marks this `RATIONAL` as the single value of its
275    /// field.
276    ///
277    /// [`TiffTypeValues`]: ../values/struct.TiffTypeValues.html
278    pub fn single(numerator: u32, denominator: u32) -> TiffTypeValues<RATIONAL> {
279        TiffTypeValues::new(vec![RATIONAL {
280            numerator,
281            denominator,
282        }])
283    }
284}
285impl TiffType for RATIONAL {
286    fn id() -> u16 {
287        5
288    }
289    fn size() -> u32 {
290        8
291    }
292    fn write_to(self, file: &mut EndianFile) -> io::Result<()> {
293        file.write_u32(self.numerator)?;
294        file.write_u32(self.denominator)?;
295        Ok(())
296    }
297}
298/// Convenient macro to declare an IFD entry of [`RATIONAL`] values.
299///
300/// [`RATIONAL`]: ifd/types/struct.RATIONAL.html
301#[macro_export]
302macro_rules! RATIONAL {
303    ($(($num: expr, $den: expr)),+) => {
304        $crate::ifd::values::TiffTypeValues::new(vec![$($crate::ifd::types::RATIONAL{numerator: $num, denominator: $den}),+])
305    };
306}
307
308/// 8-bit signed (twos-complement) integer.
309#[derive(Debug, PartialEq)]
310pub struct SBYTE(pub i8);
311impl SBYTE {
312    /// Constructs a [`TiffTypeValues`] of `SBYTE`s from a vector of
313    /// `i8`.
314    ///
315    /// [`TiffTypeValues`]: ../values/struct.TiffTypeValues.html
316    pub fn values<T: AsRef<[i8]>>(values: T) -> TiffTypeValues<SBYTE> {
317        TiffTypeValues::new(values.as_ref().iter().map(|&value| SBYTE(value)).collect())
318    }
319    /// Constructs a [`TiffTypeValues`] consisting of a single `SBYTE`.
320    ///
321    /// In other words, marks this `SBYTE` as the single value of its
322    /// field.
323    ///
324    /// [`TiffTypeValues`]: ../values/struct.TiffTypeValues.html
325    pub fn single(value: i8) -> TiffTypeValues<SBYTE> {
326        TiffTypeValues::new(vec![SBYTE(value)])
327    }
328}
329impl TiffType for SBYTE {
330    fn id() -> u16 {
331        6
332    }
333    fn size() -> u32 {
334        1
335    }
336    fn write_to(self, file: &mut EndianFile) -> io::Result<()> {
337        file.write_i8(self.0)
338    }
339}
340/// Convenient macro to declare an IFD entry of [`SBYTE`] values.
341///
342/// [`SBYTE`]: ifd/types/struct.SBYTE.html
343#[macro_export]
344macro_rules! SBYTE {
345    ($($values: expr),+) => {
346        $crate::ifd::values::TiffTypeValues::new(vec![$($crate::ifd::types::SBYTE($values)),+])
347    };
348}
349
350/// 8-bit byte that may contain anything, depending on the definition of the field.
351#[derive(Debug, PartialEq)]
352pub struct UNDEFINED(pub u8);
353impl UNDEFINED {
354    /// Constructs a [`TiffTypeValues`] of `UNDEFINED`s from a vector of
355    /// bytes.
356    ///
357    /// [`TiffTypeValues`]: ../values/struct.TiffTypeValues.html
358    pub fn values<T: AsRef<[u8]>>(values: T) -> TiffTypeValues<UNDEFINED> {
359        TiffTypeValues::new(
360            values
361                .as_ref()
362                .iter()
363                .map(|&value| UNDEFINED(value))
364                .collect(),
365        )
366    }
367    /// Constructs a [`TiffTypeValues`] consisting of a single `UNDEFINED`.
368    ///
369    /// In other words, marks this `UNDEFINED` as the single value of its
370    /// field.
371    ///
372    /// [`TiffTypeValues`]: ../values/struct.TiffTypeValues.html
373    pub fn single(value: u8) -> TiffTypeValues<UNDEFINED> {
374        TiffTypeValues::new(vec![UNDEFINED(value)])
375    }
376}
377impl TiffType for UNDEFINED {
378    fn id() -> u16 {
379        7
380    }
381    fn size() -> u32 {
382        1
383    }
384    fn write_to(self, file: &mut EndianFile) -> io::Result<()> {
385        file.write_u8(self.0)
386    }
387}
388/// Convenient macro to declare an IFD entry of [`UNDEFINED`] values.
389///
390/// [`UNDEFINED`]: ifd/types/struct.UNDEFINED.html
391#[macro_export]
392macro_rules! UNDEFINED {
393    ($($values: expr),+) => {
394        $crate::ifd::values::TiffTypeValues::new(vec![$($crate::ifd::types::UNDEFINED($values)),+])
395    };
396}
397
398/// 16-bit (2-byte) signed (twos-complement) integer.
399#[derive(Debug, PartialEq)]
400pub struct SSHORT(pub i16);
401impl SSHORT {
402    /// Constructs a [`TiffTypeValues`] of `SSHORT`s from a vector of
403    /// `i16`.
404    ///
405    /// [`TiffTypeValues`]: ../values/struct.TiffTypeValues.html
406    pub fn values<T: AsRef<[i16]>>(values: T) -> TiffTypeValues<SSHORT> {
407        TiffTypeValues::new(values.as_ref().iter().map(|&value| SSHORT(value)).collect())
408    }
409
410    /// Constructs a [`TiffTypeValues`] consisting of a single `SSHORT`.
411    ///
412    /// In other words, marks this `SSHORT` as the single value of its
413    /// field.
414    ///
415    /// [`TiffTypeValues`]: ../values/struct.TiffTypeValues.html
416    pub fn single(value: i16) -> TiffTypeValues<SSHORT> {
417        TiffTypeValues::new(vec![SSHORT(value)])
418    }
419}
420impl TiffType for SSHORT {
421    fn id() -> u16 {
422        8
423    }
424    fn size() -> u32 {
425        2
426    }
427    fn write_to(self, file: &mut EndianFile) -> io::Result<()> {
428        file.write_i16(self.0)
429    }
430}
431/// Convenient macro to declare an IFD entry of [`SSHORT`] values.
432///
433/// [`SSHORT`]: ifd/types/struct.SSHORT.html
434#[macro_export]
435macro_rules! SSHORT {
436    ($($values: expr),+) => {
437        $crate::ifd::values::TiffTypeValues::new(vec![$($crate::ifd::types::SSHORT($values)),+])
438    };
439}
440
441/// 32-bit (4-byte) signed (twos-complement) integer.
442#[derive(Debug, PartialEq)]
443pub struct SLONG(pub i32);
444impl SLONG {
445    /// Constructs a [`TiffTypeValues`] of `SLONG`s from a vector of
446    /// `i32`.
447    ///
448    /// [`TiffTypeValues`]: ../values/struct.TiffTypeValues.html
449    pub fn values<T: AsRef<[i32]>>(values: T) -> TiffTypeValues<SLONG> {
450        TiffTypeValues::new(values.as_ref().iter().map(|&value| SLONG(value)).collect())
451    }
452
453    /// Constructs a [`TiffTypeValues`] consisting of a single `SLONG`.
454    ///
455    /// In other words, marks this `SLONG` as the single value of its
456    /// field.
457    ///
458    /// [`TiffTypeValues`]: ../values/struct.TiffTypeValues.html
459    pub fn single(value: i32) -> TiffTypeValues<SLONG> {
460        TiffTypeValues::new(vec![SLONG(value)])
461    }
462}
463impl TiffType for SLONG {
464    fn id() -> u16 {
465        9
466    }
467    fn size() -> u32 {
468        4
469    }
470    fn write_to(self, file: &mut EndianFile) -> io::Result<()> {
471        file.write_i32(self.0)
472    }
473}
474/// Convenient macro to declare an IFD entry of [`SLONG`] values.
475///
476/// [`SLONG`]: ifd/types/struct.SLONG.html
477#[macro_export]
478macro_rules! SLONG {
479    ($($values: expr),+) => {
480        $crate::ifd::values::TiffTypeValues::new(vec![$($crate::ifd::types::SLONG($values)),+])
481    };
482}
483
484/// Two SLONGs representing, respectively, the numerator and the denominator of a fraction.
485#[derive(Debug, PartialEq)]
486pub struct SRATIONAL {
487    pub numerator: i32,
488    pub denominator: i32,
489}
490impl SRATIONAL {
491    /// Constructs a [`TiffTypeValues`] of `SRATIONAL`s from a vector of
492    /// pairs (numerator, denominator). Both must be `i32` values.
493    ///
494    /// [`TiffTypeValues`]: ../values/struct.TiffTypeValues.html
495    pub fn values<T: AsRef<[(i32, i32)]>>(values: T) -> TiffTypeValues<SRATIONAL> {
496        TiffTypeValues::new(
497            values
498                .as_ref()
499                .iter()
500                .map(|&(numerator, denominator)| SRATIONAL {
501                    numerator,
502                    denominator,
503                })
504                .collect(),
505        )
506    }
507
508    /// Constructs a [`TiffTypeValues`] consisting of a single `SRATIONAL`
509    /// from a pair (numerator, denominator). Both values must be `i32`.
510    ///
511    /// In other words, marks this `SRATIONAL` as the single value of its
512    /// field.
513    ///
514    /// [`TiffTypeValues`]: ../values/struct.TiffTypeValues.html
515    pub fn single(numerator: i32, denominator: i32) -> TiffTypeValues<SRATIONAL> {
516        TiffTypeValues::new(vec![SRATIONAL {
517            numerator,
518            denominator,
519        }])
520    }
521}
522impl TiffType for SRATIONAL {
523    fn id() -> u16 {
524        10
525    }
526    fn size() -> u32 {
527        8
528    }
529    fn write_to(self, file: &mut EndianFile) -> io::Result<()> {
530        file.write_i32(self.numerator)?;
531        file.write_i32(self.denominator)?;
532        Ok(())
533    }
534}
535/// Convenient macro to declare an IFD entry of [`SRATIONAL`] values.
536///
537/// [`SRATIONAL`]: ifd/types/struct.SRATIONAL.html
538#[macro_export]
539macro_rules! SRATIONAL {
540    ($(($num: expr, $den: expr)),+) => {
541        $crate::ifd::values::TiffTypeValues::new(vec![$($crate::ifd::types::SRATIONAL{numerator: $num, denominator: $den}),+])
542    };
543}
544
545/// Single precision (4-byte) IEEE format.
546#[derive(Debug, PartialEq)]
547pub struct FLOAT(pub f32);
548impl FLOAT {
549    /// Constructs a [`TiffTypeValues`] of `FLOAT`s from a vector of
550    /// `f32`.
551    ///
552    /// [`TiffTypeValues`]: ../values/struct.TiffTypeValues.html
553    pub fn values<T: AsRef<[f32]>>(values: T) -> TiffTypeValues<FLOAT> {
554        TiffTypeValues::new(values.as_ref().iter().map(|&value| FLOAT(value)).collect())
555    }
556
557    /// Constructs a [`TiffTypeValues`] consisting of a single `FLOAT`.
558    ///
559    /// In other words, marks this `FLOAT` as the single value of its
560    /// field.
561    ///
562    /// [`TiffTypeValues`]: ../values/struct.TiffTypeValues.html
563    pub fn single(value: f32) -> TiffTypeValues<FLOAT> {
564        TiffTypeValues::new(vec![FLOAT(value)])
565    }
566}
567impl TiffType for FLOAT {
568    fn id() -> u16 {
569        11
570    }
571    fn size() -> u32 {
572        4
573    }
574    fn write_to(self, file: &mut EndianFile) -> io::Result<()> {
575        file.write_f32(self.0)
576    }
577}
578/// Convenient macro to declare an IFD entry of [`FLOAT`] values.
579///
580/// [`FLOAT`]: ifd/types/struct.FLOAT.html
581#[macro_export]
582macro_rules! FLOAT {
583    ($($values: expr),+) => {
584        $crate::ifd::values::TiffTypeValues::new(vec![$($crate::ifd::types::FLOAT($values)),+])
585    };
586}
587
588/// Double precision (8-byte) IEEE format.
589#[derive(Debug, PartialEq)]
590pub struct DOUBLE(pub f64);
591impl DOUBLE {
592    /// Constructs a [`TiffTypeValues`] of `DOUBLE`s from a vector of
593    /// `f64`.
594    ///
595    /// [`TiffTypeValues`]: ../values/struct.TiffTypeValues.html
596    pub fn values<T: AsRef<[f64]>>(values: T) -> TiffTypeValues<DOUBLE> {
597        TiffTypeValues::new(values.as_ref().iter().map(|&value| DOUBLE(value)).collect())
598    }
599    /// Constructs a [`TiffTypeValues`] consisting of a single `DOUBLE`.
600    ///
601    /// In other words, marks this `DOUBLE` as the single value of its
602    /// field.
603    ///
604    /// [`TiffTypeValues`]: ../values/struct.TiffTypeValues.html
605    pub fn single(value: f64) -> TiffTypeValues<DOUBLE> {
606        TiffTypeValues::new(vec![DOUBLE(value)])
607    }
608}
609impl TiffType for DOUBLE {
610    fn id() -> u16 {
611        12
612    }
613    fn size() -> u32 {
614        8
615    }
616    fn write_to(self, file: &mut EndianFile) -> io::Result<()> {
617        file.write_f64(self.0)
618    }
619}
620/// Convenient macro to declare an IFD entry of [`DOUBLE`] values.
621///
622/// [`DOUBLE`]: ifd/types/struct.DOUBLE.html
623#[macro_export]
624macro_rules! DOUBLE {
625    ($($values: expr),+) => {
626        $crate::ifd::values::TiffTypeValues::new(vec![$($crate::ifd::types::DOUBLE($values)),+])
627    };
628}
629
630/// 32-bit (4-byte) unsigned integer used exclusively to point to IFDs.
631///
632/// This type is not supposed to be used directly. See [`OffsetsToIfds`].
633///
634/// [`OffsetsToIfds`]: ../values/struct.OffsetsToIfds.html
635#[derive(Debug, PartialEq)]
636pub struct IFD(pub(crate) u32);
637impl TiffType for IFD {
638    fn id() -> u16 {
639        13
640    }
641    fn size() -> u32 {
642        4
643    }
644    fn write_to(self, file: &mut EndianFile) -> io::Result<()> {
645        file.write_u32(self.0)
646    }
647}