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