Skip to main content

zune_core/
bit_depth.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 bit depth, information and manipulations
10
11use core::cmp::Ordering;
12
13/// The image bit depth.
14///
15/// The library successfully supports depths up to
16/// 16 bits, as the underlying storage is usually a `u16`.
17///
18/// This allows us to comfortably support a wide variety of images
19/// e.g 10 bit av1, 16 bit png and ppm.
20#[derive(Copy, Clone, Debug, Eq, PartialEq,Default)]
21#[non_exhaustive]
22pub enum BitDepth {
23    /// U8 bit depth.
24    ///
25    /// Images with such bit depth use [`u8`] to store
26    /// pixels and use the whole range from 0-255.
27    ///
28    /// It is currently the smallest supported bit depth
29    /// by the library.
30    ///
31    /// For images with bit depths lower than this, they will be scaled
32    /// to this bit depth
33    Eight,
34    /// U16 bit depth
35    ///
36    /// Images with such bit depths use [`u16`] to store values and use the whole range
37    /// i.e 0-65535
38    ///
39    /// Data is stored and processed in native endian.
40    Sixteen,
41    /// Floating point 32 bit data, range is 0.0 to 1.0
42    ///
43    /// Uses f32 to store data
44    Float32,
45    /// Bit depth information is unknown
46    #[default]
47    Unknown,
48}
49
50/// The underlying bit representation of the image
51///
52/// This represents the minimum rust type that
53/// can be used to represent image data, required
54/// by `Channel` struct in zune-image
55#[derive(Copy, Clone, Debug, Eq, PartialEq)]
56#[non_exhaustive]
57pub enum BitType {
58    /// Images represented using a [`u8`] as their
59    /// underlying pixel storage
60    U8,
61    /// Images represented using a [`u16`] as their
62    /// underlying pixel storage.
63    U16,
64    /// Images represented using a [`f32`] as their
65    /// underlying pixel storage
66    F32,
67}
68
69impl BitType {
70    /// Return the equivalent of the image bit type's depth
71    pub fn to_depth(self) -> BitDepth {
72        match self {
73            BitType::U8 => BitDepth::Eight,
74            BitType::U16 => BitDepth::Sixteen,
75            BitType::F32 => BitDepth::Float32,
76        }
77    }
78}
79
80
81impl core::cmp::PartialOrd for BitType {
82    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
83        Some(self.cmp(other))
84    }
85}
86impl core::cmp::Ord for BitType {
87    fn cmp(&self, other: &Self) -> Ordering {
88        if self == other {
89            core::cmp::Ordering::Equal
90        } else if *self == BitType::U8 {
91            // this did not match with the other bit
92            // type so it must be the smaller one
93            // eg Depth u8, depth u16
94            core::cmp::Ordering::Less
95        } else if *self == BitType::U16 && *other == BitType::F32 {
96            core::cmp::Ordering::Less
97        } else if *self == BitType::F32 {
98            core::cmp::Ordering::Greater
99        } else {
100            unreachable!()
101        }
102    }
103}
104impl BitDepth {
105    /// Get the max value supported by the bit depth
106    ///
107    /// During conversion from one bit depth to another
108    ///
109    /// larger values should be clamped to this bit depth
110    #[rustfmt::skip]
111    #[allow(clippy::zero_prefixed_literal)]
112    pub const fn max_value(self) -> u16
113    {
114        match self
115        {
116            Self::Eight => (1 << 08) - 1,
117            Self::Sixteen => u16::MAX,
118            Self::Float32 => 1,
119            Self::Unknown => 0,
120        }
121    }
122
123    /// Return the minimum number of bits that can be used to represent
124    /// each pixel in the image
125    ///
126    /// All bit depths below 8 return a bit type of `BitType::U8`.
127    ///  and all those above 8 and below 16 return a bit type of `BitType::SixTeen`
128    ///
129    /// # Returns
130    /// An enum whose variants represent the minimum size for an unsigned integer
131    /// which can store the image pixels without overflow
132    ///
133    /// # Example
134    ///
135    /// ```
136    /// use zune_core::bit_depth::{BitDepth, BitType};
137    /// assert_eq!(BitDepth::Eight.bit_type(),BitType::U8);
138    ///
139    /// assert_eq!(BitDepth::Sixteen.bit_type(),BitType::U16);
140    /// ```
141    ///
142    /// See also [size_of](BitDepth::size_of)
143    pub const fn bit_type(self) -> BitType {
144        match self {
145            Self::Eight => BitType::U8,
146            Self::Sixteen => BitType::U16,
147            Self::Float32 => BitType::F32,
148            Self::Unknown => panic!("Unknown bit type"),
149        }
150    }
151    /// Get the number of bytes needed to store a specific bit depth
152    ///
153    ///  
154    /// # Example
155    /// For images less than or equal to 8 bits(1 byte), we can use a [`u8`] to store
156    /// the pixels, and a size_of [`u8`] is 1
157    ///
158    /// For images greater than 8  bits and less than 16 bits(2 bytes), we can use a [`u16`] to
159    /// store the pixels, a size_of [`u16`] is 2.
160    /// ```
161    /// use zune_core::bit_depth::BitDepth;
162    /// let depth = BitDepth::Sixteen;
163    /// // greater 12 bits is greater than 8 and less than 16
164    /// assert_eq!(depth.size_of(),2);
165    /// ```
166    pub const fn size_of(self) -> usize {
167        match self {
168            Self::Eight => core::mem::size_of::<u8>(),
169            Self::Sixteen => core::mem::size_of::<u16>(),
170            Self::Float32 => core::mem::size_of::<f32>(),
171            Self::Unknown => panic!("Unknown bit type"),
172        }
173    }
174    pub const fn bit_size(&self) -> usize {
175        self.size_of() * 8
176    }
177}
178
179/// Byte endianness of returned samples
180/// this is useful when the decoder returns samples which span more
181/// than one byte yet the type returned is `&[u8]`
182///
183/// This helps you interpret how those bytes should be reconstructed
184/// to a higher order type
185#[derive(Copy, Clone, Debug, Eq, PartialEq)]
186pub enum ByteEndian {
187    /// Little Endian byte-order
188    LE,
189    /// Big Endian byte-order
190    BE,
191}