gufo_common/
exif.rs

1#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
2pub struct TagIfd {
3    pub tag: Tag,
4    pub ifd: Ifd,
5}
6
7impl TagIfd {
8    pub fn new(tag: Tag, ifd: Ifd) -> Self {
9        Self { tag, ifd }
10    }
11}
12
13impl<T: Field> From<T> for TagIfd {
14    fn from(_value: T) -> Self {
15        TagIfd {
16            tag: T::TAG,
17            ifd: T::IFD,
18        }
19    }
20}
21
22pub trait Field {
23    const NAME: &'static str;
24    const TAG: Tag;
25    const IFD: Ifd;
26    const IFD_ENTRY: Option<Ifd> = None;
27}
28
29pub fn lookup_tag_name(tagifd: TagIfd) -> Option<&'static str> {
30    crate::field::TAG_NAMES
31        .get(&(tagifd.tag.0, tagifd.ifd))
32        .copied()
33}
34
35#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy, PartialOrd, Ord)]
36pub struct Tag(pub u16);
37
38impl Tag {
39    pub const MAKER_NOTE: Self = Self(0x927C);
40
41    pub const EXIF_IFD_POINTER: Self = Self(0x8769);
42    pub const GPS_INFO_IFD_POINTER: Self = Self(0x8825);
43    pub const INTEROPERABILITY_IFD_POINTER: Self = Self(0xA005);
44
45    /// Returns the IFD if the tag stores the location of that IFD
46    ///
47    /// See 4.6.3 in v3.0 standard
48    pub fn exif_specific_ifd(&self) -> Option<Ifd> {
49        match *self {
50            Self::EXIF_IFD_POINTER => Some(Ifd::Exif),
51            Self::GPS_INFO_IFD_POINTER => Some(Ifd::Gps),
52            Self::INTEROPERABILITY_IFD_POINTER => Some(Ifd::Interoperability),
53            _ => None,
54        }
55    }
56
57    pub fn is_exif_specific_ifd(&self) -> bool {
58        self.exif_specific_ifd().is_some()
59    }
60}
61
62/// Image file directory
63#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
64pub enum Ifd {
65    Primary,
66    Thumbnail,
67    Exif,
68    Gps,
69    Interoperability,
70    MakerNote,
71}