zune_image/
metadata.rs

1/*
2 * Copyright (c) 2023.
3 *
4 * This software is free software;
5 *
6 * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license
7 */
8
9//! Image metadata
10//!
11//! This module provides the ability to store image metadata and transfer it
12//! from one image to another
13
14use zune_core::bit_depth::BitDepth;
15use zune_core::colorspace::{ColorCharacteristics, ColorSpace};
16
17use crate::codecs::ImageFormat;
18
19mod exif;
20
21/// Contains information about whether the image
22/// is pre multiplied with it's alpha
23/// or it's not
24#[derive(Debug, Copy, Clone, Eq, PartialEq)]
25pub enum AlphaState {
26    PreMultiplied,
27    NonPreMultiplied
28}
29
30/// Image metadata
31///
32/// Each image type has this information present
33/// The decoder usually sets this up while the encoder
34/// can get these details from the user/image struct
35#[derive(Clone, Debug)]
36pub struct ImageMetadata {
37    // REMEMBER: If you add a field here add it's serialization
38    // to src/serde
39    pub(crate) color_trc:     Option<ColorCharacteristics>,
40    pub(crate) default_gamma: Option<f32>,
41    pub(crate) width:         usize,
42    pub(crate) height:        usize,
43    pub(crate) colorspace:    ColorSpace,
44    pub(crate) depth:         BitDepth,
45    pub(crate) format:        Option<ImageFormat>,
46    pub(crate) alpha:         AlphaState,
47    #[cfg(feature = "metadata")]
48    pub(crate) exif:          Option<Vec<::exif::Field>>,
49    pub(crate) icc_chunk:     Option<Vec<u8>>,
50    // whether or not the image is in linear colorspace or
51    // rgb
52    pub(crate) is_linear:     bool
53}
54
55impl Default for ImageMetadata {
56    fn default() -> Self {
57        ImageMetadata {
58            color_trc: None,
59            default_gamma: None,
60            width: 0,
61            height: 0,
62            colorspace: ColorSpace::Unknown,
63            depth: BitDepth::default(),
64            format: None,
65            alpha: AlphaState::NonPreMultiplied,
66            #[cfg(feature = "metadata")]
67            exif: None,
68
69            icc_chunk: None,
70            is_linear: false
71        }
72    }
73}
74
75impl ImageMetadata {
76    /// Return the exif metadata of an image or none if it
77    /// doesn't exist
78    ///
79    ///
80    #[cfg(feature = "metadata")]
81    #[cfg_attr(feature = "docs", doc(cfg(feature = "metadata")))]
82    pub const fn exif(&self) -> Option<&Vec<::exif::Field>> {
83        return self.exif.as_ref();
84    }
85
86    /// Return a mutable reference to the exif metadata of an image or none if it
87    /// doesn't exist
88    ///
89    #[cfg(feature = "metadata")]
90    #[cfg_attr(feature = "docs", doc(cfg(feature = "metadata")))]
91
92    pub fn exif_mut(&mut self) -> Option<&mut Vec<::exif::Field>> {
93        return self.exif.as_mut();
94    }
95    /// Get image dimensions as a tuple of width and height
96    ///  
97    /// # Example
98    ///
99    /// ```rust
100    ///use zune_image::metadata::ImageMetadata;
101    /// let meta = ImageMetadata::default();
102    /// // default dimensions are usually zero
103    /// assert_eq!(meta.dimensions(),(0,0));
104    /// ```
105    pub const fn dimensions(&self) -> (usize, usize) {
106        (self.width, self.height)
107    }
108    /// Set image dimensions
109    ///
110    /// # Example
111    /// ```
112    /// use zune_image::metadata::ImageMetadata;
113    /// let mut meta = ImageMetadata::default();
114    /// // set image dimensions
115    /// meta.set_dimensions(23,24);
116    /// // get image dimensions
117    /// assert_eq!(meta.dimensions(),(23,24));
118    /// ```
119    pub fn set_dimensions(&mut self, width: usize, height: usize) {
120        self.width = width;
121        self.height = height;
122    }
123    /// Get an image's colorspace
124    ///
125    /// The default colorspace is usually [`ColorSpace::Unknown`]
126    /// which represents an uninitialized image
127    pub const fn colorspace(&self) -> ColorSpace {
128        self.colorspace
129    }
130    /// Set the image's colorspace
131    pub fn set_colorspace(&mut self, colorspace: ColorSpace) {
132        self.colorspace = colorspace;
133    }
134    /// Get color transfer characteristics
135    ///
136    /// Color transfer characteristics tell us more about how
137    /// the colorspace values are represented
138    /// whether they are linear or gamma encoded
139    pub const fn color_trc(&self) -> Option<ColorCharacteristics> {
140        self.color_trc
141    }
142    /// Set color transfer characteristics for this image
143    pub fn set_color_trc(&mut self, trc: ColorCharacteristics) {
144        self.color_trc = Some(trc);
145    }
146    /// Get the image bit depth
147    ///
148    /// Default value is [`BitDepth::Unknown`]
149    /// which indicates that the bit-depth is currently unknown for a
150    /// particular image
151    pub const fn depth(&self) -> BitDepth {
152        self.depth
153    }
154    /// Set the image bit depth
155    pub fn set_depth(&mut self, depth: BitDepth) {
156        self.depth = depth;
157    }
158    /// Set the default gamma for this image
159    ///
160    /// This is gamma that will be used to convert this image
161    /// from gamma colorspace to linear colorspace and back.
162    ///
163    /// Do not set this in between operations, and do not set
164    /// this if you do not know what you are doing.
165    ///
166    /// The library will set this automatically for supported decoders
167    /// (those which specify gamma during transfer)
168    ///
169    /// # Arguments
170    /// - gamma : The new gamma value
171    pub fn set_default_gamma(&mut self, gamma: f32) {
172        self.default_gamma = Some(gamma);
173    }
174
175    /// Get the image for which this metadata was fetched from
176    ///
177    /// May be None if the caller didn't set a format
178    pub const fn image_format(&self) -> Option<ImageFormat> {
179        self.format
180    }
181
182    pub const fn alpha(&self) -> AlphaState {
183        self.alpha
184    }
185    pub fn is_premultiplied_alpha(&self) -> bool {
186        self.alpha.eq(&AlphaState::PreMultiplied)
187    }
188
189    pub fn set_alpha(&mut self, alpha_state: AlphaState) {
190        self.alpha = alpha_state;
191    }
192
193    pub fn set_icc_chunk(&mut self, icc_chunk: Vec<u8>) {
194        self.icc_chunk = Some(icc_chunk);
195    }
196    /// Return the icc chunk of the image
197    pub fn icc_chunk(&self) -> Option<&Vec<u8>> {
198        self.icc_chunk.as_ref()
199    }
200
201    /// Return whether the image is in linear colorspace or not
202    ///
203    /// if `true` -> Image in linear colorspace
204    /// if `false` -> Image in gamma colorspace
205    pub fn is_linear(&self) -> bool {
206        self.is_linear
207    }
208
209    /// Set whether the image is in linear colorspace or not
210    ///
211    /// if `true` -> Image in linear colorspace
212    /// if `false` -> Image in gamma colorspace
213    pub fn set_linear(&mut self, linear: bool) {
214        self.is_linear = linear;
215    }
216}