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}