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