ruby_math/color/
rgbaf.rs

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::{RGBf, 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 RGBAf {
17    r: f32,
18    g: f32,
19    b: f32,
20    a: f32,
21}
22
23impl Display for RGBAf {
24    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
25        write!(
26            f,
27            "RGBAf(r: {}, g: {}, b: {}, a: {})",
28            self.r, self.g, self.b, self.a
29        )
30    }
31}
32
33impl Default for RGBAf {
34    fn default() -> Self {
35        Self {
36            r: 0.0,
37            g: 0.0,
38            b: 0.0,
39            a: 0.0,
40        }
41    }
42}
43
44impl Add<RGBAf> for RGBAf {
45    type Output = RGBAf;
46
47    fn add(self, rhs: RGBAf) -> Self::Output {
48        RGBAf::new(
49            self.r + rhs.r,
50            self.g + rhs.g,
51            self.b + rhs.b,
52            self.a + rhs.a,
53        )
54    }
55}
56
57impl Add<f32> for RGBAf {
58    type Output = RGBAf;
59
60    fn add(self, rhs: f32) -> Self::Output {
61        RGBAf::new(self.r + rhs, self.g + rhs, self.b + rhs, self.a + rhs)
62    }
63}
64
65impl Add<RGBAf> for f32 {
66    type Output = RGBAf;
67
68    fn add(self, rhs: RGBAf) -> Self::Output {
69        RGBAf::new(self + rhs.r, self + rhs.g, self + rhs.b, self + rhs.a)
70    }
71}
72
73impl AddAssign<RGBAf> for RGBAf {
74    fn add_assign(&mut self, rhs: RGBAf) {
75        *self = *self + rhs;
76    }
77}
78
79impl AddAssign<f32> for RGBAf {
80    fn add_assign(&mut self, rhs: f32) {
81        *self = *self + rhs;
82    }
83}
84
85impl Sub<RGBAf> for RGBAf {
86    type Output = RGBAf;
87
88    fn sub(self, rhs: RGBAf) -> Self::Output {
89        RGBAf::new(
90            self.r - rhs.r,
91            self.g - rhs.g,
92            self.b - rhs.b,
93            self.a - rhs.a,
94        )
95    }
96}
97
98impl Sub<f32> for RGBAf {
99    type Output = RGBAf;
100
101    fn sub(self, rhs: f32) -> Self::Output {
102        RGBAf::new(self.r - rhs, self.g - rhs, self.b - rhs, self.a - rhs)
103    }
104}
105
106impl Sub<RGBAf> for f32 {
107    type Output = RGBAf;
108
109    fn sub(self, rhs: RGBAf) -> Self::Output {
110        RGBAf::new(self - rhs.r, self - rhs.g, self - rhs.b, self - rhs.a)
111    }
112}
113
114impl SubAssign<RGBAf> for RGBAf {
115    fn sub_assign(&mut self, rhs: RGBAf) {
116        *self = *self - rhs;
117    }
118}
119
120impl SubAssign<f32> for RGBAf {
121    fn sub_assign(&mut self, rhs: f32) {
122        *self = *self - rhs;
123    }
124}
125
126impl Mul<RGBAf> for RGBAf {
127    type Output = RGBAf;
128
129    fn mul(self, rhs: RGBAf) -> Self::Output {
130        RGBAf::new(
131            self.r * rhs.r,
132            self.g * rhs.g,
133            self.b * rhs.b,
134            self.a * rhs.a,
135        )
136    }
137}
138
139impl Mul<f32> for RGBAf {
140    type Output = RGBAf;
141
142    fn mul(self, rhs: f32) -> Self::Output {
143        RGBAf::new(self.r * rhs, self.g * rhs, self.b * rhs, self.a * rhs)
144    }
145}
146
147impl Mul<RGBAf> for f32 {
148    type Output = RGBAf;
149
150    fn mul(self, rhs: RGBAf) -> Self::Output {
151        RGBAf::new(self * rhs.r, self * rhs.g, self * rhs.b, self * rhs.a)
152    }
153}
154
155impl MulAssign<RGBAf> for RGBAf {
156    fn mul_assign(&mut self, rhs: RGBAf) {
157        *self = *self * rhs;
158    }
159}
160
161impl MulAssign<f32> for RGBAf {
162    fn mul_assign(&mut self, rhs: f32) {
163        *self = *self * rhs;
164    }
165}
166
167impl Div<RGBAf> for RGBAf {
168    type Output = RGBAf;
169
170    fn div(self, rhs: RGBAf) -> Self::Output {
171        RGBAf::new(
172            self.r / rhs.r,
173            self.g / rhs.g,
174            self.b / rhs.b,
175            self.a / rhs.a,
176        )
177    }
178}
179
180impl Div<f32> for RGBAf {
181    type Output = RGBAf;
182
183    fn div(self, rhs: f32) -> Self::Output {
184        RGBAf::new(self.r / rhs, self.g / rhs, self.b / rhs, self.a / rhs)
185    }
186}
187
188impl Div<RGBAf> for f32 {
189    type Output = RGBAf;
190
191    fn div(self, rhs: RGBAf) -> Self::Output {
192        RGBAf::new(self / rhs.r, self / rhs.g, self / rhs.b, self / rhs.a)
193    }
194}
195
196impl DivAssign<RGBAf> for RGBAf {
197    fn div_assign(&mut self, rhs: RGBAf) {
198        *self = *self / rhs;
199    }
200}
201
202impl DivAssign<f32> for RGBAf {
203    fn div_assign(&mut self, rhs: f32) {
204        *self = *self / rhs;
205    }
206}
207
208impl Neg for RGBAf {
209    type Output = RGBAf;
210
211    fn neg(self) -> Self::Output {
212        RGBAf::new(-self.r, -self.g, -self.b, -self.a)
213    }
214}
215
216impl Index<usize> for RGBAf {
217    type Output = f32;
218
219    fn index(&self, index: usize) -> &Self::Output {
220        match index {
221            0 => &self.r,
222            1 => &self.g,
223            2 => &self.b,
224            3 => &self.a,
225            _ => panic!("`rmath::color::RGBAf::index`: index out of bounds."),
226        }
227    }
228}
229
230impl IndexMut<usize> for RGBAf {
231    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
232        match index {
233            0 => &mut self.r,
234            1 => &mut self.g,
235            2 => &mut self.b,
236            3 => &mut self.a,
237            _ => panic!("`rmath::color::RGBAf::index_mut`: index out of bounds."),
238        }
239    }
240}
241
242impl From<f32> for RGBAf {
243    fn from(rgb: f32) -> Self {
244        Self::new(rgb, rgb, rgb, 1.0)
245    }
246}
247
248impl From<(f32, f32, f32)> for RGBAf {
249    fn from(rgb: (f32, f32, f32)) -> Self {
250        Self::new(rgb.0, rgb.1, rgb.2, 1.0)
251    }
252}
253
254impl From<(f32, f32, f32, f32)> for RGBAf {
255    fn from(rgbaf: (f32, f32, f32, f32)) -> Self {
256        Self::new(rgbaf.0, rgbaf.1, rgbaf.2, rgbaf.3)
257    }
258}
259
260impl From<[f32; 3]> for RGBAf {
261    fn from(rgb: [f32; 3]) -> Self {
262        Self::new(rgb[0], rgb[1], rgb[2], 1.0)
263    }
264}
265
266impl From<[f32; 4]> for RGBAf {
267    fn from(rgbaf: [f32; 4]) -> Self {
268        Self::new(rgbaf[0], rgbaf[1], rgbaf[2], rgbaf[3])
269    }
270}
271
272impl From<u32> for RGBAf {
273    fn from(rgba: u32) -> Self {
274        let r = ((rgba >> 24) & 0xff) as f32 / 255.0;
275        let g = ((rgba >> 16) & 0xff) as f32 / 255.0;
276        let b = ((rgba >> 8) & 0xff) as f32 / 255.0;
277        let a = (rgba & 0xff) as f32 / 255.0;
278        Self::new(r, g, b, a)
279    }
280}
281
282impl From<u8> for RGBAf {
283    fn from(rgba: u8) -> Self {
284        let rgba = rgba as f32 / 255.0;
285        Self::new(rgba, rgba, rgba, rgba)
286    }
287}
288
289impl From<(u8, u8, u8)> for RGBAf {
290    fn from(rgb: (u8, u8, u8)) -> Self {
291        let (r, g, b) = rgb;
292        let r = r as f32 / 255.0;
293        let g = g as f32 / 255.0;
294        let b = b as f32 / 255.0;
295        Self::new(r, g, b, 1.0)
296    }
297}
298
299impl From<(u8, u8, u8, u8)> for RGBAf {
300    fn from(rgba: (u8, u8, u8, u8)) -> Self {
301        let (r, g, b, a) = rgba;
302        let r = r as f32 / 255.0;
303        let g = g as f32 / 255.0;
304        let b = b as f32 / 255.0;
305        let a = a as f32 / 255.0;
306        Self::new(r, g, b, a)
307    }
308}
309
310impl From<[u8; 3]> for RGBAf {
311    fn from(rgb: [u8; 3]) -> Self {
312        let r = rgb[0] as f32 / 255.0;
313        let g = rgb[1] as f32 / 255.0;
314        let b = rgb[2] as f32 / 255.0;
315        Self::new(r, g, b, 1.0)
316    }
317}
318
319impl From<[u8; 4]> for RGBAf {
320    fn from(rgba: [u8; 4]) -> Self {
321        let r = rgba[0] as f32 / 255.0;
322        let g = rgba[1] as f32 / 255.0;
323        let b = rgba[2] as f32 / 255.0;
324        let a = rgba[3] as f32 / 255.0;
325        Self::new(r, g, b, a)
326    }
327}
328
329impl From<RGB> for RGBAf {
330    fn from(color: RGB) -> Self {
331        color.to_rgbaf()
332    }
333}
334
335impl From<(RGB, f32)> for RGBAf {
336    fn from(color: (RGB, f32)) -> Self {
337        color.0.to_rgbaf_alpha(color.1)
338    }
339}
340
341impl From<RGBf> for RGBAf {
342    fn from(color: RGBf) -> Self {
343        color.to_rgbaf()
344    }
345}
346
347impl From<(RGBf, f32)> for RGBAf {
348    fn from(color: (RGBf, f32)) -> Self {
349        color.0.to_rgbaf_alpha(color.1)
350    }
351}
352
353impl From<RGBA> for RGBAf {
354    fn from(color: RGBA) -> Self {
355        color.to_rgbaf()
356    }
357}
358
359impl From<RGB24> for RGBAf {
360    fn from(color: RGB24) -> Self {
361        color.to_rgbaf()
362    }
363}
364
365impl From<(RGB24, f32)> for RGBAf {
366    fn from(color: (RGB24, f32)) -> Self {
367        color.0.to_rgbaf_alpha(color.1)
368    }
369}
370
371impl From<RGBA32> for RGBAf {
372    fn from(color: RGBA32) -> Self {
373        color.to_rgbaf()
374    }
375}
376
377impl RGBAf {
378    pub fn new(r: f32, g: f32, b: f32, a: f32) -> Self {
379        Self { r, g, b, a }
380    }
381
382    pub fn black() -> Self {
383        Self::new(0.0, 0.0, 0.0, 1.0)
384    }
385
386    pub fn white() -> Self {
387        Self::new(1.0, 1.0, 1.0, 1.0)
388    }
389
390    pub fn red() -> Self {
391        Self::new(1.0, 0.0, 0.0, 1.0)
392    }
393
394    pub fn green() -> Self {
395        Self::new(0.0, 1.0, 0.0, 1.0)
396    }
397
398    pub fn blue() -> Self {
399        Self::new(0.0, 0.0, 1.0, 1.0)
400    }
401
402    pub fn black_alpha(alpha: f32) -> Self {
403        Self::new(0.0, 0.0, 0.0, alpha)
404    }
405
406    pub fn white_alpha(alpha: f32) -> Self {
407        Self::new(1.0, 1.0, 1.0, alpha)
408    }
409
410    pub fn red_alpha(alpha: f32) -> Self {
411        Self::new(1.0, 0.0, 0.0, alpha)
412    }
413
414    pub fn green_alpha(alpha: f32) -> Self {
415        Self::new(0.0, 1.0, 0.0, alpha)
416    }
417
418    pub fn blue_alpha(alpha: f32) -> Self {
419        Self::new(0.0, 0.0, 1.0, alpha)
420    }
421
422    pub fn r(self) -> f32 {
423        self.r
424    }
425
426    pub fn g(self) -> f32 {
427        self.g
428    }
429
430    pub fn b(self) -> f32 {
431        self.b
432    }
433
434    pub fn a(self) -> f32 {
435        self.a
436    }
437}
438
439impl RGBAf {
440    pub fn sum(self) -> f32 {
441        self.r + self.g + self.b
442    }
443
444    pub fn gray(self) -> f32 {
445        self.sum() / 3.0
446    }
447
448    pub fn luma1(self) -> f32 {
449        0.299 * self.r + 0.587 * self.g + 0.144 * self.b
450    }
451
452    pub fn luma2(self) -> f32 {
453        0.2126 * self.r + 0.7152 * self.g + 0.0722 * self.b
454    }
455
456    pub fn min_element(self) -> f32 {
457        self.r.min(self.g).min(self.b).min(self.a)
458    }
459
460    pub fn max_element(self) -> f32 {
461        self.r.max(self.g).max(self.b).max(self.a)
462    }
463
464    pub fn is_finite(self) -> bool {
465        self.r.is_finite() && self.g.is_finite() && self.b.is_finite() && self.a.is_finite()
466    }
467
468    pub fn is_nan(self) -> bool {
469        self.r.is_nan() || self.g.is_nan() || self.b.is_nan() || self.a.is_nan()
470    }
471
472    pub fn is_infinite(self) -> bool {
473        self.r.is_infinite() || self.g.is_infinite() || self.b.is_infinite() || self.a.is_infinite()
474    }
475
476    pub fn clamp(self, min: Self, max: Self) -> Self {
477        ruby_assert!(min.r <= max.r);
478        ruby_assert!(min.g <= max.g);
479        ruby_assert!(min.b <= max.b);
480        ruby_assert!(min.a <= max.a);
481
482        self.min(max).max(min)
483    }
484
485    pub fn min(self, rhs: Self) -> Self {
486        Self::new(
487            self.r.min(rhs.r),
488            self.g.min(rhs.g),
489            self.b.min(rhs.b),
490            self.a.min(rhs.a),
491        )
492    }
493
494    pub fn max(self, rhs: Self) -> Self {
495        Self::new(
496            self.r.max(rhs.r),
497            self.g.max(rhs.g),
498            self.b.max(rhs.b),
499            self.a.max(rhs.a),
500        )
501    }
502
503    pub fn abs(self) -> Self {
504        Self::new(self.r.abs(), self.g.abs(), self.b.abs(), self.a.abs())
505    }
506
507    pub fn round(self) -> Self {
508        Self::new(
509            self.r.round(),
510            self.g.round(),
511            self.b.round(),
512            self.a.round(),
513        )
514    }
515
516    pub fn floor(self) -> Self {
517        Self::new(
518            self.r.floor(),
519            self.g.floor(),
520            self.b.floor(),
521            self.a.floor(),
522        )
523    }
524
525    pub fn ceil(self) -> Self {
526        Self::new(self.r.ceil(), self.g.ceil(), self.b.ceil(), self.a.ceil())
527    }
528
529    pub fn trunc(self) -> Self {
530        Self::new(
531            self.r.trunc(),
532            self.g.trunc(),
533            self.b.trunc(),
534            self.a.trunc(),
535        )
536    }
537
538    pub fn fract(self) -> Self {
539        Self::new(
540            self.r.fract(),
541            self.g.fract(),
542            self.b.fract(),
543            self.a.fract(),
544        )
545    }
546
547    pub fn sqrt(self) -> Self {
548        Self::new(self.r.sqrt(), self.g.sqrt(), self.b.sqrt(), self.a.sqrt())
549    }
550
551    pub fn exp(self) -> Self {
552        Self::new(self.r.exp(), self.g.exp(), self.b.exp(), self.a.exp())
553    }
554
555    pub fn exp2(self) -> Self {
556        Self::new(self.r.exp2(), self.g.exp2(), self.b.exp2(), self.a.exp2())
557    }
558
559    pub fn ln(self) -> Self {
560        Self::new(self.r.ln(), self.g.ln(), self.b.ln(), self.a.ln())
561    }
562
563    pub fn log(self, base: f32) -> Self {
564        Self::new(
565            self.r.log(base),
566            self.g.log(base),
567            self.b.log(base),
568            self.a.log(base),
569        )
570    }
571
572    pub fn log2(self) -> Self {
573        Self::new(self.r.log2(), self.g.log2(), self.b.log2(), self.a.log2())
574    }
575
576    pub fn log10(self) -> Self {
577        Self::new(
578            self.r.log10(),
579            self.g.log10(),
580            self.b.log10(),
581            self.a.log10(),
582        )
583    }
584
585    pub fn cbrt(self) -> Self {
586        Self::new(self.r.cbrt(), self.g.cbrt(), self.b.cbrt(), self.a.cbrt())
587    }
588
589    pub fn powf(self, n: f32) -> Self {
590        Self::new(
591            self.r.powf(n),
592            self.g.powf(n),
593            self.b.powf(n),
594            self.a.powf(n),
595        )
596    }
597
598    pub fn sin(self) -> Self {
599        Self::new(self.r.sin(), self.g.sin(), self.b.sin(), self.a.sin())
600    }
601
602    pub fn cos(self) -> Self {
603        Self::new(self.r.cos(), self.g.cos(), self.b.cos(), self.a.cos())
604    }
605
606    pub fn tan(self) -> Self {
607        Self::new(self.r.tan(), self.g.tan(), self.b.tan(), self.a.tan())
608    }
609
610    pub fn sin_cos(self) -> (Self, Self) {
611        (self.sin(), self.cos())
612    }
613
614    pub fn recip(self) -> Self {
615        Self::new(
616            self.r.recip(),
617            self.g.recip(),
618            self.b.recip(),
619            self.a.recip(),
620        )
621    }
622
623    pub fn saturate(self) -> Self {
624        self.clamp(Self::black_alpha(0.0), Self::white_alpha(1.0))
625    }
626
627    pub fn lerp(self, rhs: Self, s: f32) -> Self {
628        (rhs - self) * s + self
629    }
630
631    pub fn gamma_correct(self) -> Self {
632        let inv = 1.0 / 2.2;
633        Self::new(self.r.powf(inv), self.g.powf(inv), self.b.powf(inv), self.a)
634    }
635}
636
637impl RGBAf {
638    pub fn to_array(self) -> [f32; 4] {
639        [self.r, self.g, self.b, self.a]
640    }
641
642    pub fn to_tuple(self) -> (f32, f32, f32, f32) {
643        (self.r, self.g, self.b, self.a)
644    }
645
646    pub fn to_rgbf(self) -> RGBf {
647        RGBf::new(self.r, self.g, self.b)
648    }
649
650    pub fn to_rgb(self) -> RGB {
651        RGB::new(self.r as f64, self.g as f64, self.b as f64)
652    }
653
654    pub fn to_rgba(self) -> RGBA {
655        RGBA::new(self.r as f64, self.g as f64, self.b as f64, self.a as f64)
656    }
657
658    pub fn to_rgb24(self) -> RGB24 {
659        RGB24::new(
660            convert_f32_to_u8(self.r),
661            convert_f32_to_u8(self.g),
662            convert_f32_to_u8(self.b),
663        )
664    }
665
666    pub fn to_rgba32(self) -> RGBA32 {
667        RGBA32::new(
668            convert_f32_to_u8(self.r),
669            convert_f32_to_u8(self.g),
670            convert_f32_to_u8(self.b),
671            convert_f32_to_u8(self.a),
672        )
673    }
674}