/rust/registry/src/index.crates.io-1949cf8c6b5b557f/moxcms-0.8.1/src/rgb.rs
Line | Count | Source |
1 | | /* |
2 | | * // Copyright 2024 (c) the Radzivon Bartoshyk. All rights reserved. |
3 | | * // |
4 | | * // Use of this source code is governed by a BSD-style |
5 | | * // license that can be found in the LICENSE file. |
6 | | */ |
7 | | use crate::math::{FusedMultiplyAdd, m_clamp, m_max, m_min}; |
8 | | use crate::mlaf::mlaf; |
9 | | use crate::{Matrix3f, Vector3, Xyz}; |
10 | | use num_traits::{AsPrimitive, Bounded, Float, Num, Pow, Signed}; |
11 | | use pxfm::{ |
12 | | f_exp, f_exp2, f_exp2f, f_exp10, f_exp10f, f_expf, f_log, f_log2, f_log2f, f_log10, f_log10f, |
13 | | f_logf, f_pow, f_powf, |
14 | | }; |
15 | | use std::cmp::Ordering; |
16 | | use std::ops::{Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub}; |
17 | | |
18 | | #[repr(C)] |
19 | | #[derive(Debug, PartialOrd, PartialEq, Clone, Copy, Default)] |
20 | | /// Represents any RGB values |
21 | | pub struct Rgb<T> { |
22 | | /// Red component |
23 | | pub r: T, |
24 | | /// Green component |
25 | | pub g: T, |
26 | | /// Blue component |
27 | | pub b: T, |
28 | | } |
29 | | |
30 | | impl<T> Rgb<T> { |
31 | 0 | pub fn new(r: T, g: T, b: T) -> Rgb<T> { |
32 | 0 | Rgb { r, g, b } |
33 | 0 | } Unexecuted instantiation: <moxcms::rgb::Rgb<f64>>::new Unexecuted instantiation: <moxcms::rgb::Rgb<f32>>::new |
34 | | } |
35 | | |
36 | | impl<T> Rgb<T> |
37 | | where |
38 | | T: Copy, |
39 | | { |
40 | 0 | pub fn dup(v: T) -> Rgb<T> { |
41 | 0 | Rgb { r: v, g: v, b: v } |
42 | 0 | } |
43 | | |
44 | | #[inline] |
45 | 0 | pub const fn to_vector(self) -> Vector3<T> { |
46 | 0 | Vector3 { |
47 | 0 | v: [self.r, self.g, self.b], |
48 | 0 | } |
49 | 0 | } |
50 | | } |
51 | | |
52 | | impl Rgb<f32> { |
53 | | #[inline(always)] |
54 | 0 | pub fn apply(&self, matrix: Matrix3f) -> Rgb<f32> { |
55 | 0 | let new_r = mlaf( |
56 | 0 | mlaf(self.r * matrix.v[0][0], self.g, matrix.v[0][1]), |
57 | 0 | self.b, |
58 | 0 | matrix.v[0][2], |
59 | | ); |
60 | | |
61 | 0 | let new_g = mlaf( |
62 | 0 | mlaf(self.r * matrix.v[1][0], self.g, matrix.v[1][1]), |
63 | 0 | self.b, |
64 | 0 | matrix.v[1][2], |
65 | | ); |
66 | | |
67 | 0 | let new_b = mlaf( |
68 | 0 | mlaf(self.r * matrix.v[2][0], self.g, matrix.v[2][1]), |
69 | 0 | self.b, |
70 | 0 | matrix.v[2][2], |
71 | | ); |
72 | | |
73 | 0 | Rgb { |
74 | 0 | r: new_r, |
75 | 0 | g: new_g, |
76 | 0 | b: new_b, |
77 | 0 | } |
78 | 0 | } |
79 | | |
80 | | #[inline(always)] |
81 | 0 | pub fn to_xyz(&self, matrix: Matrix3f) -> Xyz { |
82 | 0 | let new_self = self.apply(matrix); |
83 | 0 | Xyz { |
84 | 0 | x: new_self.r, |
85 | 0 | y: new_self.g, |
86 | 0 | z: new_self.b, |
87 | 0 | } |
88 | 0 | } |
89 | | |
90 | | #[inline(always)] |
91 | 0 | pub fn is_out_of_gamut(&self) -> bool { |
92 | 0 | !(0.0..=1.0).contains(&self.r) |
93 | 0 | || !(0.0..=1.0).contains(&self.g) |
94 | 0 | || !(0.0..=1.0).contains(&self.b) |
95 | 0 | } |
96 | | } |
97 | | |
98 | | impl<T> Index<usize> for Rgb<T> { |
99 | | type Output = T; |
100 | | |
101 | 0 | fn index(&self, index: usize) -> &T { |
102 | 0 | match index { |
103 | 0 | 0 => &self.r, |
104 | 0 | 1 => &self.g, |
105 | 0 | 2 => &self.b, |
106 | 0 | _ => panic!("Index out of bounds for Rgb"), |
107 | | } |
108 | 0 | } |
109 | | } |
110 | | |
111 | | impl<T> IndexMut<usize> for Rgb<T> { |
112 | 0 | fn index_mut(&mut self, index: usize) -> &mut T { |
113 | 0 | match index { |
114 | 0 | 0 => &mut self.r, |
115 | 0 | 1 => &mut self.g, |
116 | 0 | 2 => &mut self.b, |
117 | 0 | _ => panic!("Index out of bounds for RGB"), |
118 | | } |
119 | 0 | } |
120 | | } |
121 | | |
122 | | macro_rules! generated_float_definition_rgb { |
123 | | ($T: ty) => { |
124 | | impl Rgb<$T> { |
125 | | #[inline] |
126 | 0 | pub fn zeroed() -> Rgb<$T> { |
127 | 0 | Rgb::<$T>::new(0., 0., 0.) |
128 | 0 | } Unexecuted instantiation: <moxcms::rgb::Rgb<f32>>::zeroed Unexecuted instantiation: <moxcms::rgb::Rgb<f64>>::zeroed |
129 | | |
130 | | #[inline] |
131 | 0 | pub fn ones() -> Rgb<$T> { |
132 | 0 | Rgb::<$T>::new(1., 1., 1.) |
133 | 0 | } Unexecuted instantiation: <moxcms::rgb::Rgb<f32>>::ones Unexecuted instantiation: <moxcms::rgb::Rgb<f64>>::ones |
134 | | |
135 | | #[inline] |
136 | 0 | pub fn white() -> Rgb<$T> { |
137 | 0 | Rgb::<$T>::ones() |
138 | 0 | } Unexecuted instantiation: <moxcms::rgb::Rgb<f32>>::white Unexecuted instantiation: <moxcms::rgb::Rgb<f64>>::white |
139 | | |
140 | | #[inline] |
141 | 0 | pub fn black() -> Rgb<$T> { |
142 | 0 | Rgb::<$T>::zeroed() |
143 | 0 | } Unexecuted instantiation: <moxcms::rgb::Rgb<f32>>::black Unexecuted instantiation: <moxcms::rgb::Rgb<f64>>::black |
144 | | } |
145 | | }; |
146 | | } |
147 | | |
148 | | generated_float_definition_rgb!(f32); |
149 | | generated_float_definition_rgb!(f64); |
150 | | |
151 | | macro_rules! generated_integral_definition_rgb { |
152 | | ($T: ty) => { |
153 | | impl Rgb<$T> { |
154 | | #[inline] |
155 | 0 | pub fn zeroed() -> Rgb<$T> { |
156 | 0 | Rgb::<$T>::new(0, 0, 0) |
157 | 0 | } Unexecuted instantiation: <moxcms::rgb::Rgb<u8>>::zeroed Unexecuted instantiation: <moxcms::rgb::Rgb<u16>>::zeroed Unexecuted instantiation: <moxcms::rgb::Rgb<i8>>::zeroed Unexecuted instantiation: <moxcms::rgb::Rgb<i16>>::zeroed Unexecuted instantiation: <moxcms::rgb::Rgb<i32>>::zeroed Unexecuted instantiation: <moxcms::rgb::Rgb<u32>>::zeroed |
158 | | |
159 | | #[inline] |
160 | 0 | pub fn capped() -> Rgb<$T> { |
161 | 0 | Rgb::<$T>::new(<$T>::MAX, <$T>::MAX, <$T>::MAX) |
162 | 0 | } Unexecuted instantiation: <moxcms::rgb::Rgb<u8>>::capped Unexecuted instantiation: <moxcms::rgb::Rgb<u16>>::capped Unexecuted instantiation: <moxcms::rgb::Rgb<i8>>::capped Unexecuted instantiation: <moxcms::rgb::Rgb<i16>>::capped Unexecuted instantiation: <moxcms::rgb::Rgb<i32>>::capped Unexecuted instantiation: <moxcms::rgb::Rgb<u32>>::capped |
163 | | |
164 | | #[inline] |
165 | 0 | pub fn white() -> Rgb<$T> { |
166 | 0 | Rgb::<$T>::capped() |
167 | 0 | } Unexecuted instantiation: <moxcms::rgb::Rgb<u8>>::white Unexecuted instantiation: <moxcms::rgb::Rgb<u16>>::white Unexecuted instantiation: <moxcms::rgb::Rgb<i8>>::white Unexecuted instantiation: <moxcms::rgb::Rgb<i16>>::white Unexecuted instantiation: <moxcms::rgb::Rgb<i32>>::white Unexecuted instantiation: <moxcms::rgb::Rgb<u32>>::white |
168 | | |
169 | | #[inline] |
170 | 0 | pub fn black() -> Rgb<$T> { |
171 | 0 | Rgb::<$T>::new(0, 0, 0) |
172 | 0 | } Unexecuted instantiation: <moxcms::rgb::Rgb<u8>>::black Unexecuted instantiation: <moxcms::rgb::Rgb<u16>>::black Unexecuted instantiation: <moxcms::rgb::Rgb<i8>>::black Unexecuted instantiation: <moxcms::rgb::Rgb<i16>>::black Unexecuted instantiation: <moxcms::rgb::Rgb<i32>>::black Unexecuted instantiation: <moxcms::rgb::Rgb<u32>>::black |
173 | | } |
174 | | }; |
175 | | } |
176 | | |
177 | | generated_integral_definition_rgb!(u8); |
178 | | generated_integral_definition_rgb!(u16); |
179 | | generated_integral_definition_rgb!(i8); |
180 | | generated_integral_definition_rgb!(i16); |
181 | | generated_integral_definition_rgb!(i32); |
182 | | generated_integral_definition_rgb!(u32); |
183 | | |
184 | | pub trait FusedPow<T> { |
185 | | fn f_pow(&self, power: T) -> Self; |
186 | | } |
187 | | |
188 | | pub trait FusedLog2<T> { |
189 | | fn f_log2(&self) -> Self; |
190 | | } |
191 | | |
192 | | pub trait FusedLog10<T> { |
193 | | fn f_log10(&self) -> Self; |
194 | | } |
195 | | |
196 | | pub trait FusedLog<T> { |
197 | | fn f_log(&self) -> Self; |
198 | | } |
199 | | |
200 | | pub trait FusedExp<T> { |
201 | | fn f_exp(&self) -> Self; |
202 | | } |
203 | | |
204 | | pub trait FusedExp2<T> { |
205 | | fn f_exp2(&self) -> Self; |
206 | | } |
207 | | |
208 | | pub trait FusedExp10<T> { |
209 | | fn f_exp10(&self) -> Self; |
210 | | } |
211 | | |
212 | | impl FusedPow<Rgb<f32>> for Rgb<f32> { |
213 | 0 | fn f_pow(&self, power: Rgb<f32>) -> Rgb<f32> { |
214 | 0 | Rgb::new( |
215 | 0 | f_powf(self.r, power.r), |
216 | 0 | f_powf(self.g, power.g), |
217 | 0 | f_powf(self.b, power.b), |
218 | | ) |
219 | 0 | } |
220 | | } |
221 | | |
222 | | impl FusedPow<Rgb<f64>> for Rgb<f64> { |
223 | 0 | fn f_pow(&self, power: Rgb<f64>) -> Rgb<f64> { |
224 | 0 | Rgb::new( |
225 | 0 | f_pow(self.r, power.r), |
226 | 0 | f_pow(self.g, power.g), |
227 | 0 | f_pow(self.b, power.b), |
228 | | ) |
229 | 0 | } |
230 | | } |
231 | | |
232 | | impl FusedLog2<Rgb<f32>> for Rgb<f32> { |
233 | | #[inline] |
234 | 0 | fn f_log2(&self) -> Rgb<f32> { |
235 | 0 | Rgb::new(f_log2f(self.r), f_log2f(self.g), f_log2f(self.b)) |
236 | 0 | } |
237 | | } |
238 | | |
239 | | impl FusedLog2<Rgb<f64>> for Rgb<f64> { |
240 | | #[inline] |
241 | 0 | fn f_log2(&self) -> Rgb<f64> { |
242 | 0 | Rgb::new(f_log2(self.r), f_log2(self.g), f_log2(self.b)) |
243 | 0 | } |
244 | | } |
245 | | |
246 | | impl FusedLog<Rgb<f32>> for Rgb<f32> { |
247 | | #[inline] |
248 | 0 | fn f_log(&self) -> Rgb<f32> { |
249 | 0 | Rgb::new(f_logf(self.r), f_logf(self.g), f_logf(self.b)) |
250 | 0 | } |
251 | | } |
252 | | |
253 | | impl FusedLog<Rgb<f64>> for Rgb<f64> { |
254 | | #[inline] |
255 | 0 | fn f_log(&self) -> Rgb<f64> { |
256 | 0 | Rgb::new(f_log(self.r), f_log(self.g), f_log(self.b)) |
257 | 0 | } |
258 | | } |
259 | | |
260 | | impl FusedLog10<Rgb<f32>> for Rgb<f32> { |
261 | | #[inline] |
262 | 0 | fn f_log10(&self) -> Rgb<f32> { |
263 | 0 | Rgb::new(f_log10f(self.r), f_log10f(self.g), f_log10f(self.b)) |
264 | 0 | } |
265 | | } |
266 | | |
267 | | impl FusedLog10<Rgb<f64>> for Rgb<f64> { |
268 | | #[inline] |
269 | 0 | fn f_log10(&self) -> Rgb<f64> { |
270 | 0 | Rgb::new(f_log10(self.r), f_log10(self.g), f_log10(self.b)) |
271 | 0 | } |
272 | | } |
273 | | |
274 | | impl FusedExp<Rgb<f32>> for Rgb<f32> { |
275 | | #[inline] |
276 | 0 | fn f_exp(&self) -> Rgb<f32> { |
277 | 0 | Rgb::new(f_expf(self.r), f_expf(self.g), f_expf(self.b)) |
278 | 0 | } |
279 | | } |
280 | | |
281 | | impl FusedExp<Rgb<f64>> for Rgb<f64> { |
282 | | #[inline] |
283 | 0 | fn f_exp(&self) -> Rgb<f64> { |
284 | 0 | Rgb::new(f_exp(self.r), f_exp(self.g), f_exp(self.b)) |
285 | 0 | } |
286 | | } |
287 | | |
288 | | impl FusedExp2<Rgb<f32>> for Rgb<f32> { |
289 | | #[inline] |
290 | 0 | fn f_exp2(&self) -> Rgb<f32> { |
291 | 0 | Rgb::new(f_exp2f(self.r), f_exp2f(self.g), f_exp2f(self.b)) |
292 | 0 | } |
293 | | } |
294 | | |
295 | | impl FusedExp2<Rgb<f64>> for Rgb<f64> { |
296 | | #[inline] |
297 | 0 | fn f_exp2(&self) -> Rgb<f64> { |
298 | 0 | Rgb::new(f_exp2(self.r), f_exp2(self.g), f_exp2(self.b)) |
299 | 0 | } |
300 | | } |
301 | | |
302 | | impl FusedExp10<Rgb<f32>> for Rgb<f32> { |
303 | | #[inline] |
304 | 0 | fn f_exp10(&self) -> Rgb<f32> { |
305 | 0 | Rgb::new(f_exp10f(self.r), f_exp10f(self.g), f_exp10f(self.b)) |
306 | 0 | } |
307 | | } |
308 | | |
309 | | impl FusedExp10<Rgb<f64>> for Rgb<f64> { |
310 | | #[inline] |
311 | 0 | fn f_exp10(&self) -> Rgb<f64> { |
312 | 0 | Rgb::new(f_exp10(self.r), f_exp10(self.g), f_exp10(self.b)) |
313 | 0 | } |
314 | | } |
315 | | |
316 | | impl<T> Rgb<T> |
317 | | where |
318 | | T: Copy + AsPrimitive<f32>, |
319 | | { |
320 | 0 | pub fn euclidean_distance(&self, other: Rgb<T>) -> f32 { |
321 | 0 | let dr = self.r.as_() - other.r.as_(); |
322 | 0 | let dg = self.g.as_() - other.g.as_(); |
323 | 0 | let db = self.b.as_() - other.b.as_(); |
324 | 0 | (dr * dr + dg * dg + db * db).sqrt() |
325 | 0 | } |
326 | | } |
327 | | |
328 | | impl<T> Rgb<T> |
329 | | where |
330 | | T: Copy + AsPrimitive<f32>, |
331 | | { |
332 | 0 | pub fn taxicab_distance(&self, other: Self) -> f32 { |
333 | 0 | let dr = self.r.as_() - other.r.as_(); |
334 | 0 | let dg = self.g.as_() - other.g.as_(); |
335 | 0 | let db = self.b.as_() - other.b.as_(); |
336 | 0 | dr.abs() + dg.abs() + db.abs() |
337 | 0 | } |
338 | | } |
339 | | |
340 | | impl<T> Add for Rgb<T> |
341 | | where |
342 | | T: Add<Output = T>, |
343 | | { |
344 | | type Output = Rgb<T>; |
345 | | |
346 | | #[inline] |
347 | 0 | fn add(self, rhs: Self) -> Self::Output { |
348 | 0 | Rgb::new(self.r + rhs.r, self.g + rhs.g, self.b + rhs.b) |
349 | 0 | } |
350 | | } |
351 | | |
352 | | impl<T> Sub for Rgb<T> |
353 | | where |
354 | | T: Sub<Output = T>, |
355 | | { |
356 | | type Output = Rgb<T>; |
357 | | |
358 | | #[inline] |
359 | 0 | fn sub(self, rhs: Self) -> Self::Output { |
360 | 0 | Rgb::new(self.r - rhs.r, self.g - rhs.g, self.b - rhs.b) |
361 | 0 | } |
362 | | } |
363 | | |
364 | | impl<T: Copy + Clone> Sub<T> for Rgb<T> |
365 | | where |
366 | | T: Sub<Output = T>, |
367 | | { |
368 | | type Output = Rgb<T>; |
369 | | |
370 | | #[inline] |
371 | 0 | fn sub(self, rhs: T) -> Self::Output { |
372 | 0 | Rgb::new(self.r - rhs, self.g - rhs, self.b - rhs) |
373 | 0 | } |
374 | | } |
375 | | |
376 | | impl<T: Copy + Clone> Add<T> for Rgb<T> |
377 | | where |
378 | | T: Add<Output = T>, |
379 | | { |
380 | | type Output = Rgb<T>; |
381 | | |
382 | | #[inline] |
383 | 0 | fn add(self, rhs: T) -> Self::Output { |
384 | 0 | Rgb::new(self.r + rhs, self.g + rhs, self.b + rhs) |
385 | 0 | } |
386 | | } |
387 | | |
388 | | impl<T: Copy + Clone> Rgb<T> |
389 | | where |
390 | | T: Signed, |
391 | | { |
392 | | #[inline] |
393 | 0 | pub fn abs(self) -> Self { |
394 | 0 | Rgb::new(self.r.abs(), self.g.abs(), self.b.abs()) |
395 | 0 | } |
396 | | } |
397 | | |
398 | | impl<T> Div for Rgb<T> |
399 | | where |
400 | | T: Div<Output = T>, |
401 | | { |
402 | | type Output = Rgb<T>; |
403 | | |
404 | | #[inline] |
405 | 0 | fn div(self, rhs: Self) -> Self::Output { |
406 | 0 | Rgb::new(self.r / rhs.r, self.g / rhs.g, self.b / rhs.b) |
407 | 0 | } |
408 | | } |
409 | | |
410 | | impl<T: Clone + Copy> Div<T> for Rgb<T> |
411 | | where |
412 | | T: Div<Output = T>, |
413 | | { |
414 | | type Output = Rgb<T>; |
415 | | |
416 | | #[inline] |
417 | 0 | fn div(self, rhs: T) -> Self::Output { |
418 | 0 | Rgb::new(self.r / rhs, self.g / rhs, self.b / rhs) |
419 | 0 | } |
420 | | } |
421 | | |
422 | | impl<T> Mul for Rgb<T> |
423 | | where |
424 | | T: Mul<Output = T>, |
425 | | { |
426 | | type Output = Rgb<T>; |
427 | | |
428 | | #[inline] |
429 | 0 | fn mul(self, rhs: Self) -> Self::Output { |
430 | 0 | Rgb::new(self.r * rhs.r, self.g * rhs.g, self.b * rhs.b) |
431 | 0 | } |
432 | | } |
433 | | |
434 | | impl<T: Clone + Copy> Mul<T> for Rgb<T> |
435 | | where |
436 | | T: Mul<Output = T>, |
437 | | { |
438 | | type Output = Rgb<T>; |
439 | | |
440 | | #[inline] |
441 | 0 | fn mul(self, rhs: T) -> Self::Output { |
442 | 0 | Rgb::new(self.r * rhs, self.g * rhs, self.b * rhs) |
443 | 0 | } |
444 | | } |
445 | | |
446 | | impl<T> MulAssign for Rgb<T> |
447 | | where |
448 | | T: MulAssign<T>, |
449 | | { |
450 | | #[inline] |
451 | 0 | fn mul_assign(&mut self, rhs: Self) { |
452 | 0 | self.r *= rhs.r; |
453 | 0 | self.g *= rhs.g; |
454 | 0 | self.b *= rhs.b; |
455 | 0 | } |
456 | | } |
457 | | |
458 | | macro_rules! generated_mul_assign_definition_rgb { |
459 | | ($T: ty) => { |
460 | | impl<T> MulAssign<$T> for Rgb<T> |
461 | | where |
462 | | T: MulAssign<$T>, |
463 | | { |
464 | | #[inline] |
465 | 0 | fn mul_assign(&mut self, rhs: $T) { |
466 | 0 | self.r *= rhs; |
467 | 0 | self.g *= rhs; |
468 | 0 | self.b *= rhs; |
469 | 0 | } Unexecuted instantiation: <moxcms::rgb::Rgb<_> as core::ops::arith::MulAssign<i8>>::mul_assign Unexecuted instantiation: <moxcms::rgb::Rgb<_> as core::ops::arith::MulAssign<u8>>::mul_assign Unexecuted instantiation: <moxcms::rgb::Rgb<_> as core::ops::arith::MulAssign<u16>>::mul_assign Unexecuted instantiation: <moxcms::rgb::Rgb<_> as core::ops::arith::MulAssign<i16>>::mul_assign Unexecuted instantiation: <moxcms::rgb::Rgb<_> as core::ops::arith::MulAssign<u32>>::mul_assign Unexecuted instantiation: <moxcms::rgb::Rgb<_> as core::ops::arith::MulAssign<i32>>::mul_assign Unexecuted instantiation: <moxcms::rgb::Rgb<_> as core::ops::arith::MulAssign<f32>>::mul_assign Unexecuted instantiation: <moxcms::rgb::Rgb<_> as core::ops::arith::MulAssign<f64>>::mul_assign |
470 | | } |
471 | | }; |
472 | | } |
473 | | |
474 | | generated_mul_assign_definition_rgb!(i8); |
475 | | generated_mul_assign_definition_rgb!(u8); |
476 | | generated_mul_assign_definition_rgb!(u16); |
477 | | generated_mul_assign_definition_rgb!(i16); |
478 | | generated_mul_assign_definition_rgb!(u32); |
479 | | generated_mul_assign_definition_rgb!(i32); |
480 | | generated_mul_assign_definition_rgb!(f32); |
481 | | generated_mul_assign_definition_rgb!(f64); |
482 | | |
483 | | impl<T> AddAssign for Rgb<T> |
484 | | where |
485 | | T: AddAssign<T>, |
486 | | { |
487 | | #[inline] |
488 | 0 | fn add_assign(&mut self, rhs: Self) { |
489 | 0 | self.r += rhs.r; |
490 | 0 | self.g += rhs.g; |
491 | 0 | self.b += rhs.b; |
492 | 0 | } |
493 | | } |
494 | | |
495 | | macro_rules! generated_add_assign_definition_rgb { |
496 | | ($T: ty) => { |
497 | | impl<T: Copy> AddAssign<$T> for Rgb<T> |
498 | | where |
499 | | T: AddAssign<$T>, |
500 | | { |
501 | | #[inline] |
502 | 0 | fn add_assign(&mut self, rhs: $T) { |
503 | 0 | self.r += rhs; |
504 | 0 | self.g += rhs; |
505 | 0 | self.b += rhs; |
506 | 0 | } Unexecuted instantiation: <moxcms::rgb::Rgb<_> as core::ops::arith::AddAssign<i8>>::add_assign Unexecuted instantiation: <moxcms::rgb::Rgb<_> as core::ops::arith::AddAssign<u8>>::add_assign Unexecuted instantiation: <moxcms::rgb::Rgb<_> as core::ops::arith::AddAssign<u16>>::add_assign Unexecuted instantiation: <moxcms::rgb::Rgb<_> as core::ops::arith::AddAssign<i16>>::add_assign Unexecuted instantiation: <moxcms::rgb::Rgb<_> as core::ops::arith::AddAssign<u32>>::add_assign Unexecuted instantiation: <moxcms::rgb::Rgb<_> as core::ops::arith::AddAssign<i32>>::add_assign Unexecuted instantiation: <moxcms::rgb::Rgb<_> as core::ops::arith::AddAssign<f32>>::add_assign Unexecuted instantiation: <moxcms::rgb::Rgb<_> as core::ops::arith::AddAssign<f64>>::add_assign |
507 | | } |
508 | | }; |
509 | | } |
510 | | |
511 | | generated_add_assign_definition_rgb!(i8); |
512 | | generated_add_assign_definition_rgb!(u8); |
513 | | generated_add_assign_definition_rgb!(u16); |
514 | | generated_add_assign_definition_rgb!(i16); |
515 | | generated_add_assign_definition_rgb!(u32); |
516 | | generated_add_assign_definition_rgb!(i32); |
517 | | generated_add_assign_definition_rgb!(f32); |
518 | | generated_add_assign_definition_rgb!(f64); |
519 | | |
520 | | impl<T> DivAssign for Rgb<T> |
521 | | where |
522 | | T: DivAssign<T>, |
523 | | { |
524 | | #[inline] |
525 | 0 | fn div_assign(&mut self, rhs: Self) { |
526 | 0 | self.r /= rhs.r; |
527 | 0 | self.g /= rhs.g; |
528 | 0 | self.b /= rhs.b; |
529 | 0 | } |
530 | | } |
531 | | |
532 | | macro_rules! generated_div_assign_definition_rgb { |
533 | | ($T: ty) => { |
534 | | impl<T: Copy> DivAssign<$T> for Rgb<T> |
535 | | where |
536 | | T: DivAssign<$T>, |
537 | | { |
538 | | #[inline] |
539 | 0 | fn div_assign(&mut self, rhs: $T) { |
540 | 0 | self.r /= rhs; |
541 | 0 | self.g /= rhs; |
542 | 0 | self.b /= rhs; |
543 | 0 | } Unexecuted instantiation: <moxcms::rgb::Rgb<_> as core::ops::arith::DivAssign<u8>>::div_assign Unexecuted instantiation: <moxcms::rgb::Rgb<_> as core::ops::arith::DivAssign<i8>>::div_assign Unexecuted instantiation: <moxcms::rgb::Rgb<_> as core::ops::arith::DivAssign<u16>>::div_assign Unexecuted instantiation: <moxcms::rgb::Rgb<_> as core::ops::arith::DivAssign<i16>>::div_assign Unexecuted instantiation: <moxcms::rgb::Rgb<_> as core::ops::arith::DivAssign<u32>>::div_assign Unexecuted instantiation: <moxcms::rgb::Rgb<_> as core::ops::arith::DivAssign<i32>>::div_assign Unexecuted instantiation: <moxcms::rgb::Rgb<_> as core::ops::arith::DivAssign<f32>>::div_assign Unexecuted instantiation: <moxcms::rgb::Rgb<_> as core::ops::arith::DivAssign<f64>>::div_assign |
544 | | } |
545 | | }; |
546 | | } |
547 | | |
548 | | generated_div_assign_definition_rgb!(u8); |
549 | | generated_div_assign_definition_rgb!(i8); |
550 | | generated_div_assign_definition_rgb!(u16); |
551 | | generated_div_assign_definition_rgb!(i16); |
552 | | generated_div_assign_definition_rgb!(u32); |
553 | | generated_div_assign_definition_rgb!(i32); |
554 | | generated_div_assign_definition_rgb!(f32); |
555 | | generated_div_assign_definition_rgb!(f64); |
556 | | |
557 | | impl<T> Neg for Rgb<T> |
558 | | where |
559 | | T: Neg<Output = T>, |
560 | | { |
561 | | type Output = Rgb<T>; |
562 | | |
563 | | #[inline] |
564 | 0 | fn neg(self) -> Self::Output { |
565 | 0 | Rgb::new(-self.r, -self.g, -self.b) |
566 | 0 | } |
567 | | } |
568 | | |
569 | | impl<T> Rgb<T> |
570 | | where |
571 | | T: FusedMultiplyAdd<T>, |
572 | | { |
573 | 0 | pub fn mla(&self, b: Rgb<T>, c: Rgb<T>) -> Rgb<T> { |
574 | 0 | Rgb::new( |
575 | 0 | self.r.mla(b.r, c.r), |
576 | 0 | self.g.mla(b.g, c.g), |
577 | 0 | self.b.mla(b.b, c.b), |
578 | | ) |
579 | 0 | } |
580 | | } |
581 | | |
582 | | impl<T> Rgb<T> |
583 | | where |
584 | | T: Num + PartialOrd + Copy + Bounded, |
585 | | { |
586 | | /// Clamp function to clamp each channel within a given range |
587 | | #[inline] |
588 | | #[allow(clippy::manual_clamp)] |
589 | 0 | pub fn clamp(&self, min_value: T, max_value: T) -> Rgb<T> { |
590 | 0 | Rgb::new( |
591 | 0 | m_clamp(self.r, min_value, max_value), |
592 | 0 | m_clamp(self.g, min_value, max_value), |
593 | 0 | m_clamp(self.b, min_value, max_value), |
594 | | ) |
595 | 0 | } |
596 | | |
597 | | /// Min function to define min |
598 | | #[inline] |
599 | 0 | pub fn min(&self, other_min: T) -> Rgb<T> { |
600 | 0 | Rgb::new( |
601 | 0 | m_min(self.r, other_min), |
602 | 0 | m_min(self.g, other_min), |
603 | 0 | m_min(self.b, other_min), |
604 | | ) |
605 | 0 | } |
606 | | |
607 | | /// Max function to define max |
608 | | #[inline] |
609 | 0 | pub fn max(&self, other_max: T) -> Rgb<T> { |
610 | 0 | Rgb::new( |
611 | 0 | m_max(self.r, other_max), |
612 | 0 | m_max(self.g, other_max), |
613 | 0 | m_max(self.b, other_max), |
614 | | ) |
615 | 0 | } |
616 | | |
617 | | /// Clamp function to clamp each channel within a given range |
618 | | #[inline] |
619 | | #[allow(clippy::manual_clamp)] |
620 | 0 | pub fn clamp_p(&self, min_value: Rgb<T>, max_value: Rgb<T>) -> Rgb<T> { |
621 | 0 | Rgb::new( |
622 | 0 | m_clamp(self.r, max_value.r, min_value.r), |
623 | 0 | m_clamp(self.g, max_value.g, min_value.g), |
624 | 0 | m_clamp(self.b, max_value.b, min_value.b), |
625 | | ) |
626 | 0 | } |
627 | | |
628 | | /// Min function to define min |
629 | | #[inline] |
630 | 0 | pub fn min_p(&self, other_min: Rgb<T>) -> Rgb<T> { |
631 | 0 | Rgb::new( |
632 | 0 | m_min(self.r, other_min.r), |
633 | 0 | m_min(self.g, other_min.g), |
634 | 0 | m_min(self.b, other_min.b), |
635 | | ) |
636 | 0 | } |
637 | | |
638 | | /// Max function to define max |
639 | | #[inline] |
640 | 0 | pub fn max_p(&self, other_max: Rgb<T>) -> Rgb<T> { |
641 | 0 | Rgb::new( |
642 | 0 | m_max(self.r, other_max.r), |
643 | 0 | m_max(self.g, other_max.g), |
644 | 0 | m_max(self.b, other_max.b), |
645 | | ) |
646 | 0 | } |
647 | | } |
648 | | |
649 | | impl<T> Rgb<T> |
650 | | where |
651 | | T: Float + 'static, |
652 | | f32: AsPrimitive<T>, |
653 | | { |
654 | | #[inline] |
655 | 0 | pub fn sqrt(&self) -> Rgb<T> { |
656 | 0 | let zeros = 0f32.as_(); |
657 | 0 | Rgb::new( |
658 | 0 | if self.r.partial_cmp(&zeros).unwrap_or(Ordering::Less) == Ordering::Less { |
659 | 0 | 0f32.as_() |
660 | | } else { |
661 | 0 | self.r.sqrt() |
662 | | }, |
663 | 0 | if self.g.partial_cmp(&zeros).unwrap_or(Ordering::Less) == Ordering::Less { |
664 | 0 | 0f32.as_() |
665 | | } else { |
666 | 0 | self.g.sqrt() |
667 | | }, |
668 | 0 | if self.b.partial_cmp(&zeros).unwrap_or(Ordering::Less) == Ordering::Less { |
669 | 0 | 0f32.as_() |
670 | | } else { |
671 | 0 | self.b.sqrt() |
672 | | }, |
673 | | ) |
674 | 0 | } |
675 | | |
676 | | #[inline] |
677 | 0 | pub fn cbrt(&self) -> Rgb<T> { |
678 | 0 | Rgb::new(self.r.cbrt(), self.g.cbrt(), self.b.cbrt()) |
679 | 0 | } |
680 | | } |
681 | | |
682 | | impl<T> Pow<T> for Rgb<T> |
683 | | where |
684 | | T: Float, |
685 | | { |
686 | | type Output = Rgb<T>; |
687 | | |
688 | | #[inline] |
689 | 0 | fn pow(self, rhs: T) -> Self::Output { |
690 | 0 | Rgb::<T>::new(self.r.powf(rhs), self.g.powf(rhs), self.b.powf(rhs)) |
691 | 0 | } |
692 | | } |
693 | | |
694 | | impl<T> Pow<Rgb<T>> for Rgb<T> |
695 | | where |
696 | | T: Float, |
697 | | { |
698 | | type Output = Rgb<T>; |
699 | | |
700 | | #[inline] |
701 | 0 | fn pow(self, rhs: Rgb<T>) -> Self::Output { |
702 | 0 | Rgb::<T>::new(self.r.powf(rhs.r), self.g.powf(rhs.g), self.b.powf(rhs.b)) |
703 | 0 | } |
704 | | } |
705 | | |
706 | | impl<T> Rgb<T> { |
707 | 0 | pub fn cast<V>(self) -> Rgb<V> |
708 | 0 | where |
709 | 0 | T: AsPrimitive<V>, |
710 | 0 | V: Copy + 'static, |
711 | | { |
712 | 0 | Rgb::new(self.r.as_(), self.g.as_(), self.b.as_()) |
713 | 0 | } |
714 | | } |
715 | | |
716 | | impl<T> Rgb<T> |
717 | | where |
718 | | T: Float + 'static, |
719 | | { |
720 | 0 | pub fn round(self) -> Rgb<T> { |
721 | 0 | Rgb::new(self.r.round(), self.g.round(), self.b.round()) |
722 | 0 | } |
723 | | } |