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}