image2/
type.rs

1use crate::*;
2
3/// Type is used to represent supported image data types
4pub trait Type:
5    'static + Unpin + Default + Clone + Copy + Sync + Send + PartialEq + PartialOrd + std::fmt::Debug
6{
7    /// Min value
8    const MIN: f64;
9
10    /// Max value
11    const MAX: f64;
12
13    /// I/O base type
14    const BASE: io::BaseType;
15
16    /// Convert to f64
17    fn to_f64(&self) -> f64;
18
19    /// Convert from f64
20    fn from_f64(f: f64) -> Self;
21
22    /// Returns true when `T` is a floating point type
23    fn is_float() -> bool {
24        let x = Self::to_f64(&Self::from_f64(0.5));
25        x > 0.0 && x < 1.0
26    }
27
28    /// Get the type name
29    fn type_name() -> &'static str {
30        use io::BaseType::*;
31        match Self::BASE {
32            Unknown => "unknown",
33            None => "none",
34            UInt8 => "uint8",
35            Int8 => "int8",
36            UInt16 => "uint16",
37            Int16 => "int16",
38            UInt32 => "uint32",
39            Int32 => "int32",
40            UInt64 => "uint64",
41            Int64 => "int64",
42            Half => "half",
43            Float => "float",
44            Double => "double",
45            String => "string",
46            Ptr => "ptr",
47            Last => "",
48        }
49    }
50
51    /// Set a value from an f64 value
52    fn set_from_f64(&mut self, f: f64) {
53        *self = Self::from_f64(f);
54    }
55
56    /// Set a value from normalized float
57    fn set_from_norm(&mut self, f: f64) {
58        *self = Self::from_norm(f);
59    }
60
61    /// Convert from `T` to normalized float
62    fn to_norm(&self) -> f64 {
63        Self::normalize(self.to_f64())
64    }
65
66    /// Convert to `T` from normalized float
67    fn from_norm(f: f64) -> Self {
68        Self::from_f64(Self::denormalize(f))
69    }
70
71    #[inline]
72    /// Scale a value to fit between 0 and 1.0 based on the min/max values for `T`
73    fn normalize(f: f64) -> f64 {
74        (f - Self::MIN) / (Self::MAX - Self::MIN)
75    }
76
77    #[inline]
78    /// Scale an f64 value to fit the range supported by `T`
79    fn denormalize(f: f64) -> f64 {
80        f * Self::MAX - Self::MIN
81    }
82
83    /// Ensure the given value is less than the max allowed and greater than or equal to the
84    /// minimum value
85    #[inline]
86    fn clamp(f: f64) -> f64 {
87        f.clamp(Self::MIN, Self::MAX)
88    }
89
90    /// Convert a value from one type to another
91    #[inline]
92    fn convert<X: Type>(&self) -> X {
93        X::from_f64(X::denormalize(Self::normalize(Self::to_f64(self))))
94    }
95
96    /// Get the number of bits for a data type
97    fn bits() -> usize {
98        std::mem::size_of::<Self>() * 8
99    }
100}
101
102impl Type for u8 {
103    const MIN: f64 = 0.0;
104    const MAX: f64 = u8::MAX as f64;
105    const BASE: io::BaseType = io::BaseType::UInt8;
106
107    fn to_f64(&self) -> f64 {
108        *self as f64
109    }
110
111    fn from_f64(f: f64) -> Self {
112        f as Self
113    }
114}
115
116impl Type for i8 {
117    const MIN: f64 = i8::MIN as f64;
118    const MAX: f64 = i8::MAX as f64;
119    const BASE: io::BaseType = io::BaseType::Int8;
120
121    fn to_f64(&self) -> f64 {
122        *self as f64
123    }
124
125    fn from_f64(f: f64) -> Self {
126        f as Self
127    }
128}
129
130impl Type for u16 {
131    const MIN: f64 = 0.0;
132    const MAX: f64 = u16::MAX as f64;
133    const BASE: io::BaseType = io::BaseType::UInt16;
134
135    fn to_f64(&self) -> f64 {
136        *self as f64
137    }
138
139    fn from_f64(f: f64) -> Self {
140        f as Self
141    }
142}
143
144impl Type for i16 {
145    const MIN: f64 = i16::MIN as f64;
146    const MAX: f64 = i16::MAX as f64;
147    const BASE: io::BaseType = io::BaseType::Int16;
148
149    fn to_f64(&self) -> f64 {
150        *self as f64
151    }
152
153    fn from_f64(f: f64) -> Self {
154        f as Self
155    }
156}
157
158impl Type for u32 {
159    const MIN: f64 = 0.0;
160    const MAX: f64 = u32::MAX as f64;
161    const BASE: io::BaseType = io::BaseType::UInt32;
162
163    fn to_f64(&self) -> f64 {
164        *self as f64
165    }
166
167    fn from_f64(f: f64) -> Self {
168        f as Self
169    }
170}
171
172impl Type for i32 {
173    const MIN: f64 = i32::MIN as f64;
174    const MAX: f64 = i32::MAX as f64;
175    const BASE: io::BaseType = io::BaseType::Int32;
176
177    fn to_f64(&self) -> f64 {
178        *self as f64
179    }
180
181    fn from_f64(f: f64) -> Self {
182        f as Self
183    }
184}
185
186impl Type for u64 {
187    const MIN: f64 = 0.0;
188    const MAX: f64 = u64::MAX as f64;
189    const BASE: io::BaseType = io::BaseType::UInt64;
190
191    fn to_f64(&self) -> f64 {
192        *self as f64
193    }
194
195    fn from_f64(f: f64) -> Self {
196        f as Self
197    }
198}
199
200impl Type for i64 {
201    const MIN: f64 = i64::MIN as f64;
202    const MAX: f64 = i64::MAX as f64;
203    const BASE: io::BaseType = io::BaseType::Int64;
204
205    fn to_f64(&self) -> f64 {
206        *self as f64
207    }
208
209    fn from_f64(f: f64) -> Self {
210        f as Self
211    }
212}
213
214impl Type for f16 {
215    const MIN: f64 = 0.0;
216    const MAX: f64 = 1.0;
217    const BASE: io::BaseType = io::BaseType::Half;
218
219    fn to_f64(&self) -> f64 {
220        f16::to_f64(*self)
221    }
222
223    fn from_f64(f: f64) -> Self {
224        f16::from_f64(f)
225    }
226}
227
228impl Type for f32 {
229    const MIN: f64 = 0.0;
230    const MAX: f64 = 1.0;
231    const BASE: io::BaseType = io::BaseType::Float;
232
233    fn to_f64(&self) -> f64 {
234        *self as f64
235    }
236
237    fn from_f64(f: f64) -> Self {
238        f as Self
239    }
240}
241
242impl Type for f64 {
243    const MIN: f64 = 0.0;
244    const MAX: f64 = 1.0;
245    const BASE: io::BaseType = io::BaseType::Double;
246
247    fn to_f64(&self) -> f64 {
248        *self
249    }
250
251    fn from_f64(f: f64) -> Self {
252        f
253    }
254}