makepad_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 Default for BitDepth {
67 fn default() -> Self {
68 Self::Unknown
69 }
70}
71
72impl BitDepth {
73 /// Get the max value supported by the bit depth
74 ///
75 /// During conversion from one bit depth to another
76 ///
77 /// larger values should be clamped to this bit depth
78 #[rustfmt::skip]
79 #[allow(clippy::zero_prefixed_literal)]
80 pub const fn max_value(self) -> u16
81 {
82 match self
83 {
84 Self::Eight => (1 << 08) - 1,
85 Self::Sixteen => u16::MAX,
86 Self::Float32 => 1,
87 Self::Unknown => 0,
88 }
89 }
90
91 /// Return the minimum number of bits that can be used to represent
92 /// each pixel in the image
93 ///
94 /// All bit depths below 8 return a bit type of `BitType::U8`.
95 /// and all those above 8 and below 16 return a bit type of `BitType::SixTeen`
96 ///
97 /// # Returns
98 /// An enum whose variants represent the minimum size for an unsigned integer
99 /// which can store the image pixels without overflow
100 ///
101 /// # Example
102 ///
103 /// ```
104 /// use zune_core::bit_depth::{BitDepth, BitType};
105 /// assert_eq!(BitDepth::Eight.bit_type(),BitType::U8);
106 ///
107 /// assert_eq!(BitDepth::Sixteen.bit_type(),BitType::U16);
108 /// ```
109 ///
110 /// See also [size_of](BitDepth::size_of)
111 pub const fn bit_type(self) -> BitType {
112 match self {
113 Self::Eight => BitType::U8,
114 Self::Sixteen => BitType::U16,
115 Self::Float32 => BitType::F32,
116 Self::Unknown => panic!("Unknown bit type")
117 }
118 }
119 /// Get the number of bytes needed to store a specific bit depth
120 ///
121 ///
122 /// # Example
123 /// For images less than or equal to 8 bits(1 byte), we can use a [`u8`] to store
124 /// the pixels, and a size_of [`u8`] is 1
125 ///
126 /// For images greater than 8 bits and less than 16 bits(2 bytes), we can use a [`u16`] to
127 /// store the pixels, a size_of [`u16`] is 2.
128 /// ```
129 /// use zune_core::bit_depth::BitDepth;
130 /// let depth = BitDepth::Sixteen;
131 /// // greater 12 bits is greater than 8 and less than 16
132 /// assert_eq!(depth.size_of(),2);
133 /// ```
134 pub const fn size_of(self) -> usize {
135 match self {
136 Self::Eight => core::mem::size_of::<u8>(),
137 Self::Sixteen => core::mem::size_of::<u16>(),
138 Self::Float32 => core::mem::size_of::<f32>(),
139 Self::Unknown => panic!("Unknown bit type")
140 }
141 }
142 pub const fn bit_size(&self) -> usize {
143 self.size_of() * 8
144 }
145}
146/// Byte endianness of returned samples
147/// this is useful when the decoder returns samples which span more
148/// than one byte yet the type returned is `&[u8]`
149///
150/// This helps you interpret how those bytes should be reconstructed
151/// to a higher order type
152#[derive(Copy, Clone, Debug, Eq, PartialEq)]
153pub enum ByteEndian {
154 /// Little Endian byte-order
155 LE,
156 /// Big Endian byte-order
157 BE
158}