1#![allow(dead_code)]
2
3use std::{
4 fmt::Display,
5 ops::{Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub, SubAssign},
6};
7
8use super::{RGBAf, RGB, RGB24, RGBA, RGBA32};
9
10fn convert_f32_to_u8(v: f32) -> u8 {
11 let v = (v * 255.0 + 0.5) as i32;
12 v.max(0).min(255) as u8
13}
14
15#[derive(Clone, Copy, PartialEq, Debug)]
16pub struct RGBf {
17 r: f32,
18 g: f32,
19 b: f32,
20}
21
22impl Display for RGBf {
23 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
24 write!(f, "RGBf(r: {}, g: {}, b: {})", self.r, self.g, self.b)
25 }
26}
27
28impl Default for RGBf {
29 fn default() -> Self {
30 Self {
31 r: 0.0,
32 g: 0.0,
33 b: 0.0,
34 }
35 }
36}
37
38impl Add<RGBf> for RGBf {
39 type Output = RGBf;
40
41 fn add(self, rhs: RGBf) -> Self::Output {
42 RGBf::new(self.r + rhs.r, self.g + rhs.g, self.b + rhs.b)
43 }
44}
45
46impl Add<f32> for RGBf {
47 type Output = RGBf;
48
49 fn add(self, rhs: f32) -> Self::Output {
50 RGBf::new(self.r + rhs, self.g + rhs, self.b + rhs)
51 }
52}
53
54impl Add<RGBf> for f32 {
55 type Output = RGBf;
56
57 fn add(self, rhs: RGBf) -> Self::Output {
58 RGBf::new(self + rhs.r, self + rhs.g, self + rhs.b)
59 }
60}
61
62impl AddAssign<RGBf> for RGBf {
63 fn add_assign(&mut self, rhs: RGBf) {
64 *self = *self + rhs;
65 }
66}
67
68impl AddAssign<f32> for RGBf {
69 fn add_assign(&mut self, rhs: f32) {
70 *self = *self + rhs;
71 }
72}
73
74impl Sub<RGBf> for RGBf {
75 type Output = RGBf;
76
77 fn sub(self, rhs: RGBf) -> Self::Output {
78 RGBf::new(self.r - rhs.r, self.g - rhs.g, self.b - rhs.b)
79 }
80}
81
82impl Sub<f32> for RGBf {
83 type Output = RGBf;
84
85 fn sub(self, rhs: f32) -> Self::Output {
86 RGBf::new(self.r - rhs, self.g - rhs, self.b - rhs)
87 }
88}
89
90impl Sub<RGBf> for f32 {
91 type Output = RGBf;
92
93 fn sub(self, rhs: RGBf) -> Self::Output {
94 RGBf::new(self - rhs.r, self - rhs.g, self - rhs.b)
95 }
96}
97
98impl SubAssign<RGBf> for RGBf {
99 fn sub_assign(&mut self, rhs: RGBf) {
100 *self = *self - rhs;
101 }
102}
103
104impl SubAssign<f32> for RGBf {
105 fn sub_assign(&mut self, rhs: f32) {
106 *self = *self - rhs;
107 }
108}
109
110impl Mul<RGBf> for RGBf {
111 type Output = RGBf;
112
113 fn mul(self, rhs: RGBf) -> Self::Output {
114 RGBf::new(self.r * rhs.r, self.g * rhs.g, self.b * rhs.b)
115 }
116}
117
118impl Mul<f32> for RGBf {
119 type Output = RGBf;
120
121 fn mul(self, rhs: f32) -> Self::Output {
122 RGBf::new(self.r * rhs, self.g * rhs, self.b * rhs)
123 }
124}
125
126impl Mul<RGBf> for f32 {
127 type Output = RGBf;
128
129 fn mul(self, rhs: RGBf) -> Self::Output {
130 RGBf::new(self * rhs.r, self * rhs.g, self * rhs.b)
131 }
132}
133
134impl MulAssign<RGBf> for RGBf {
135 fn mul_assign(&mut self, rhs: RGBf) {
136 *self = *self * rhs;
137 }
138}
139
140impl MulAssign<f32> for RGBf {
141 fn mul_assign(&mut self, rhs: f32) {
142 *self = *self * rhs;
143 }
144}
145
146impl Div<RGBf> for RGBf {
147 type Output = RGBf;
148
149 fn div(self, rhs: RGBf) -> Self::Output {
150 RGBf::new(self.r / rhs.r, self.g / rhs.g, self.b / rhs.b)
151 }
152}
153
154impl Div<f32> for RGBf {
155 type Output = RGBf;
156
157 fn div(self, rhs: f32) -> Self::Output {
158 RGBf::new(self.r / rhs, self.g / rhs, self.b / rhs)
159 }
160}
161
162impl Div<RGBf> for f32 {
163 type Output = RGBf;
164
165 fn div(self, rhs: RGBf) -> Self::Output {
166 RGBf::new(self / rhs.r, self / rhs.g, self / rhs.b)
167 }
168}
169
170impl DivAssign<RGBf> for RGBf {
171 fn div_assign(&mut self, rhs: RGBf) {
172 *self = *self / rhs;
173 }
174}
175
176impl DivAssign<f32> for RGBf {
177 fn div_assign(&mut self, rhs: f32) {
178 *self = *self / rhs;
179 }
180}
181
182impl Neg for RGBf {
183 type Output = RGBf;
184
185 fn neg(self) -> Self::Output {
186 RGBf::new(-self.r, -self.g, -self.b)
187 }
188}
189
190impl Index<usize> for RGBf {
191 type Output = f32;
192
193 fn index(&self, index: usize) -> &Self::Output {
194 match index {
195 0 => &self.r,
196 1 => &self.g,
197 2 => &self.b,
198 _ => panic!("`rmath::color::RGBf::index`: index out of bounds."),
199 }
200 }
201}
202
203impl IndexMut<usize> for RGBf {
204 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
205 match index {
206 0 => &mut self.r,
207 1 => &mut self.g,
208 2 => &mut self.b,
209 _ => panic!("`rmath::color::RGBf::index_mut`: index out of bounds."),
210 }
211 }
212}
213
214impl From<f32> for RGBf {
215 fn from(rgbf: f32) -> Self {
216 Self::new(rgbf, rgbf, rgbf)
217 }
218}
219
220impl From<(f32, f32, f32)> for RGBf {
221 fn from(rgbf: (f32, f32, f32)) -> Self {
222 Self::new(rgbf.0, rgbf.1, rgbf.2)
223 }
224}
225
226impl From<[f32; 3]> for RGBf {
227 fn from(rgbf: [f32; 3]) -> Self {
228 Self::new(rgbf[0], rgbf[1], rgbf[2])
229 }
230}
231
232impl From<u32> for RGBf {
233 fn from(rgb_: u32) -> Self {
234 let r = ((rgb_ >> 16) & 0xff) as f32 / 255.0;
235 let g = ((rgb_ >> 8) & 0xff) as f32 / 255.0;
236 let b = (rgb_ & 0xff) as f32 / 255.0;
237 Self::new(r, g, b)
238 }
239}
240
241impl From<u8> for RGBf {
242 fn from(rgb: u8) -> Self {
243 let rgb = rgb as f32 / 255.0;
244 Self::new(rgb, rgb, rgb)
245 }
246}
247
248impl From<(u8, u8, u8)> for RGBf {
249 fn from(rgb: (u8, u8, u8)) -> Self {
250 let (r, g, b) = rgb;
251 let r = r as f32 / 255.0;
252 let g = g as f32 / 255.0;
253 let b = b as f32 / 255.0;
254 Self::new(r, g, b)
255 }
256}
257
258impl From<[u8; 3]> for RGBf {
259 fn from(rgb: [u8; 3]) -> Self {
260 let r = rgb[0] as f32 / 255.0;
261 let g = rgb[1] as f32 / 255.0;
262 let b = rgb[2] as f32 / 255.0;
263 Self::new(r, g, b)
264 }
265}
266
267impl From<RGB> for RGBf {
268 fn from(color: RGB) -> Self {
269 color.to_rgbf()
270 }
271}
272
273impl From<RGBA> for RGBf {
274 fn from(color: RGBA) -> Self {
275 color.to_rgbf()
276 }
277}
278
279impl From<RGBAf> for RGBf {
280 fn from(color: RGBAf) -> Self {
281 color.to_rgbf()
282 }
283}
284
285impl From<RGB24> for RGBf {
286 fn from(color: RGB24) -> Self {
287 color.to_rgbf()
288 }
289}
290
291impl From<RGBA32> for RGBf {
292 fn from(color: RGBA32) -> Self {
293 color.to_rgbf()
294 }
295}
296
297impl RGBf {
298 pub fn new(r: f32, g: f32, b: f32) -> Self {
299 Self { r, g, b }
300 }
301
302 pub fn black() -> Self {
303 Self::new(0.0, 0.0, 0.0)
304 }
305
306 pub fn white() -> Self {
307 Self::new(1.0, 1.0, 1.0)
308 }
309
310 pub fn red() -> Self {
311 Self::new(1.0, 0.0, 0.0)
312 }
313
314 pub fn green() -> Self {
315 Self::new(0.0, 1.0, 0.0)
316 }
317
318 pub fn blue() -> Self {
319 Self::new(0.0, 0.0, 1.0)
320 }
321
322 pub fn r(self) -> f32 {
323 self.r
324 }
325
326 pub fn g(self) -> f32 {
327 self.g
328 }
329
330 pub fn b(self) -> f32 {
331 self.b
332 }
333}
334
335impl RGBf {
336 pub fn sum(self) -> f32 {
337 self.r + self.g + self.b
338 }
339
340 pub fn gray(self) -> f32 {
341 self.sum() / 3.0
342 }
343
344 pub fn luma1(self) -> f32 {
345 0.299 * self.r + 0.587 * self.g + 0.144 * self.b
346 }
347
348 pub fn luma2(self) -> f32 {
349 0.2126 * self.r + 0.7152 * self.g + 0.0722 * self.b
350 }
351
352 pub fn min_element(self) -> f32 {
353 self.r.min(self.g).min(self.b)
354 }
355
356 pub fn max_element(self) -> f32 {
357 self.r.max(self.g).max(self.b)
358 }
359
360 pub fn is_finite(self) -> bool {
361 self.r.is_finite() && self.g.is_finite() && self.b.is_finite()
362 }
363
364 pub fn is_nan(self) -> bool {
365 self.r.is_nan() || self.g.is_nan() || self.b.is_nan()
366 }
367
368 pub fn is_infinite(self) -> bool {
369 self.r.is_infinite() || self.g.is_infinite() || self.b.is_infinite()
370 }
371
372 pub fn clamp(self, min: Self, max: Self) -> Self {
373 ruby_assert!(min.r <= max.r);
374 ruby_assert!(min.g <= max.g);
375 ruby_assert!(min.b <= max.b);
376
377 self.min(max).max(min)
378 }
379
380 pub fn min(self, rhs: Self) -> Self {
381 Self::new(self.r.min(rhs.r), self.g.min(rhs.g), self.b.min(rhs.b))
382 }
383
384 pub fn max(self, rhs: Self) -> Self {
385 Self::new(self.r.max(rhs.r), self.g.max(rhs.g), self.b.max(rhs.b))
386 }
387
388 pub fn abs(self) -> Self {
389 Self::new(self.r.abs(), self.g.abs(), self.b.abs())
390 }
391
392 pub fn round(self) -> Self {
393 Self::new(self.r.round(), self.g.round(), self.b.round())
394 }
395
396 pub fn floor(self) -> Self {
397 Self::new(self.r.floor(), self.g.floor(), self.b.floor())
398 }
399
400 pub fn ceil(self) -> Self {
401 Self::new(self.r.ceil(), self.g.ceil(), self.b.ceil())
402 }
403
404 pub fn trunc(self) -> Self {
405 Self::new(self.r.trunc(), self.g.trunc(), self.b.trunc())
406 }
407
408 pub fn fract(self) -> Self {
409 Self::new(self.r.fract(), self.g.fract(), self.b.fract())
410 }
411
412 pub fn sqrt(self) -> Self {
413 Self::new(self.r.sqrt(), self.g.sqrt(), self.b.sqrt())
414 }
415
416 pub fn exp(self) -> Self {
417 Self::new(self.r.exp(), self.g.exp(), self.b.exp())
418 }
419
420 pub fn exp2(self) -> Self {
421 Self::new(self.r.exp2(), self.g.exp2(), self.b.exp2())
422 }
423
424 pub fn ln(self) -> Self {
425 Self::new(self.r.ln(), self.g.ln(), self.b.ln())
426 }
427
428 pub fn log(self, base: f32) -> Self {
429 Self::new(self.r.log(base), self.g.log(base), self.b.log(base))
430 }
431
432 pub fn log2(self) -> Self {
433 Self::new(self.r.log2(), self.g.log2(), self.b.log2())
434 }
435
436 pub fn log10(self) -> Self {
437 Self::new(self.r.log10(), self.g.log10(), self.b.log10())
438 }
439
440 pub fn cbrt(self) -> Self {
441 Self::new(self.r.cbrt(), self.g.cbrt(), self.b.cbrt())
442 }
443
444 pub fn powf(self, n: f32) -> Self {
445 Self::new(self.r.powf(n), self.g.powf(n), self.b.powf(n))
446 }
447
448 pub fn sin(self) -> Self {
449 Self::new(self.r.sin(), self.g.sin(), self.b.sin())
450 }
451
452 pub fn cos(self) -> Self {
453 Self::new(self.r.cos(), self.g.cos(), self.b.cos())
454 }
455
456 pub fn tan(self) -> Self {
457 Self::new(self.r.tan(), self.g.tan(), self.b.tan())
458 }
459
460 pub fn sin_cos(self) -> (Self, Self) {
461 (self.sin(), self.cos())
462 }
463
464 pub fn recip(self) -> Self {
465 Self::new(self.r.recip(), self.g.recip(), self.b.recip())
466 }
467
468 pub fn saturate(self) -> Self {
469 self.clamp(Self::black(), Self::white())
470 }
471
472 pub fn lerp(self, rhs: Self, s: f32) -> Self {
473 (rhs - self) * s + self
474 }
475
476 pub fn gamma_correct(self) -> Self {
477 self.powf(1.0 / 2.2)
478 }
479}
480
481impl RGBf {
482 pub fn to_array(self) -> [f32; 3] {
483 [self.r, self.g, self.b]
484 }
485
486 pub fn to_tuple(self) -> (f32, f32, f32) {
487 (self.r, self.g, self.b)
488 }
489
490 pub fn to_rgb(self) -> RGB {
491 RGB::new(self.r as f64, self.g as f64, self.b as f64)
492 }
493
494 pub fn to_rgba(self) -> RGBA {
495 RGBA::new(self.r as f64, self.g as f64, self.b as f64, 1.0)
496 }
497
498 pub fn to_rgba_alpha(self, alpha: f64) -> RGBA {
499 RGBA::new(self.r as f64, self.g as f64, self.b as f64, alpha)
500 }
501
502 pub fn to_rgbaf(self) -> RGBAf {
503 RGBAf::new(self.r, self.g, self.b, 1.0)
504 }
505
506 pub fn to_rgbaf_alpha(self, alpha: f32) -> RGBAf {
507 RGBAf::new(self.r, self.g, self.b, alpha)
508 }
509
510 pub fn to_rgb24(self) -> RGB24 {
511 RGB24::new(
512 convert_f32_to_u8(self.r),
513 convert_f32_to_u8(self.g),
514 convert_f32_to_u8(self.b),
515 )
516 }
517
518 pub fn to_rgba32(self) -> RGBA32 {
519 RGBA32::new(
520 convert_f32_to_u8(self.r),
521 convert_f32_to_u8(self.g),
522 convert_f32_to_u8(self.b),
523 255,
524 )
525 }
526
527 pub fn to_rgba32_alpha(self, alpha: u8) -> RGBA32 {
528 RGBA32::new(
529 convert_f32_to_u8(self.r),
530 convert_f32_to_u8(self.g),
531 convert_f32_to_u8(self.b),
532 alpha,
533 )
534 }
535}