ruby_math/color/
rgba32.rs

1#![allow(dead_code)]
2
3use std::{
4    fmt::Display,
5    ops::{Index, IndexMut},
6};
7
8use super::{RGBAf, RGBf, RGB, RGB24, RGBA};
9
10fn convert_f64_to_u8(v: f64) -> 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 RGBA32 {
17    r: u8,
18    g: u8,
19    b: u8,
20    a: u8,
21}
22
23impl Display for RGBA32 {
24    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
25        write!(
26            f,
27            "RGBA32(r: {}, g: {}, b: {}, a: {})",
28            self.r, self.g, self.b, self.a
29        )
30    }
31}
32
33impl Default for RGBA32 {
34    fn default() -> Self {
35        Self {
36            r: 0,
37            g: 0,
38            b: 0,
39            a: 0,
40        }
41    }
42}
43
44impl Index<usize> for RGBA32 {
45    type Output = u8;
46
47    fn index(&self, index: usize) -> &Self::Output {
48        match index {
49            0 => &self.r,
50            1 => &self.g,
51            2 => &self.b,
52            3 => &self.a,
53            _ => panic!("`rmath::color::RGBA32::index`: index out of bounds."),
54        }
55    }
56}
57
58impl IndexMut<usize> for RGBA32 {
59    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
60        match index {
61            0 => &mut self.r,
62            1 => &mut self.g,
63            2 => &mut self.b,
64            3 => &mut self.a,
65            _ => panic!("`rmath::color::RGBA32::index_mut`: index out of bounds."),
66        }
67    }
68}
69
70impl From<f64> for RGBA32 {
71    fn from(rgb: f64) -> Self {
72        let rgb = convert_f64_to_u8(rgb);
73        Self::new(rgb, rgb, rgb, rgb)
74    }
75}
76
77impl From<(f64, f64, f64)> for RGBA32 {
78    fn from(rgb: (f64, f64, f64)) -> Self {
79        let (r, g, b) = rgb;
80        let r = convert_f64_to_u8(r);
81        let g = convert_f64_to_u8(g);
82        let b = convert_f64_to_u8(b);
83        Self::new(r, g, b, 255)
84    }
85}
86
87impl From<(f64, f64, f64, f64)> for RGBA32 {
88    fn from(rgba: (f64, f64, f64, f64)) -> Self {
89        let (r, g, b, a) = rgba;
90        let r = convert_f64_to_u8(r);
91        let g = convert_f64_to_u8(g);
92        let b = convert_f64_to_u8(b);
93        let a = convert_f64_to_u8(a);
94        Self::new(r, g, b, a)
95    }
96}
97
98impl From<[f64; 3]> for RGBA32 {
99    fn from(rgb: [f64; 3]) -> Self {
100        let r = convert_f64_to_u8(rgb[0]);
101        let g = convert_f64_to_u8(rgb[1]);
102        let b = convert_f64_to_u8(rgb[2]);
103        Self::new(r, g, b, 255)
104    }
105}
106
107impl From<[f64; 4]> for RGBA32 {
108    fn from(rgba: [f64; 4]) -> Self {
109        let r = convert_f64_to_u8(rgba[0]);
110        let g = convert_f64_to_u8(rgba[1]);
111        let b = convert_f64_to_u8(rgba[2]);
112        let a = convert_f64_to_u8(rgba[3]);
113        Self::new(r, g, b, a)
114    }
115}
116
117impl From<u32> for RGBA32 {
118    fn from(rgba: u32) -> Self {
119        let r = ((rgba >> 24) & 0xff) as u8;
120        let g = ((rgba >> 16) & 0xff) as u8;
121        let b = ((rgba >> 8) & 0xff) as u8;
122        let a = (rgba & 0xff) as u8;
123        Self::new(r, g, b, a)
124    }
125}
126
127impl From<u8> for RGBA32 {
128    fn from(rgb: u8) -> Self {
129        Self::new(rgb, rgb, rgb, 255)
130    }
131}
132
133impl From<(u8, u8, u8)> for RGBA32 {
134    fn from(rgb: (u8, u8, u8)) -> Self {
135        let (r, g, b) = rgb;
136        Self::new(r, g, b, 255)
137    }
138}
139
140impl From<(u8, u8, u8, u8)> for RGBA32 {
141    fn from(rgba: (u8, u8, u8, u8)) -> Self {
142        let (r, g, b, a) = rgba;
143        Self::new(r, g, b, a)
144    }
145}
146
147impl From<[u8; 3]> for RGBA32 {
148    fn from(rgb: [u8; 3]) -> Self {
149        Self::new(rgb[0], rgb[1], rgb[2], 255)
150    }
151}
152
153impl From<[u8; 4]> for RGBA32 {
154    fn from(rgba: [u8; 4]) -> Self {
155        Self::new(rgba[0], rgba[1], rgba[2], rgba[3])
156    }
157}
158
159impl From<RGB> for RGBA32 {
160    fn from(color: RGB) -> Self {
161        color.to_rgba32()
162    }
163}
164
165impl From<(RGB, u8)> for RGBA32 {
166    fn from(color: (RGB, u8)) -> Self {
167        color.0.to_rgba32_alpha(color.1)
168    }
169}
170
171impl From<RGBf> for RGBA32 {
172    fn from(color: RGBf) -> Self {
173        color.to_rgba32()
174    }
175}
176
177impl From<(RGBf, u8)> for RGBA32 {
178    fn from(color: (RGBf, u8)) -> Self {
179        color.0.to_rgba32_alpha(color.1)
180    }
181}
182
183impl From<RGBA> for RGBA32 {
184    fn from(color: RGBA) -> Self {
185        color.to_rgba32()
186    }
187}
188
189impl From<RGBAf> for RGBA32 {
190    fn from(color: RGBAf) -> Self {
191        color.to_rgba32()
192    }
193}
194
195impl From<RGB24> for RGBA32 {
196    fn from(color: RGB24) -> Self {
197        color.to_rgba32()
198    }
199}
200
201impl From<(RGB24, u8)> for RGBA32 {
202    fn from(color: (RGB24, u8)) -> Self {
203        color.0.to_rgba32_alpha(color.1)
204    }
205}
206
207impl RGBA32 {
208    pub fn new(r: u8, g: u8, b: u8, a: u8) -> Self {
209        Self { r, g, b, a }
210    }
211
212    pub fn black() -> Self {
213        Self::new(0, 0, 0, 255)
214    }
215
216    pub fn white() -> Self {
217        Self::new(255, 255, 255, 255)
218    }
219
220    pub fn red() -> Self {
221        Self::new(255, 0, 0, 255)
222    }
223
224    pub fn green() -> Self {
225        Self::new(0, 1, 0, 255)
226    }
227
228    pub fn blue() -> Self {
229        Self::new(0, 0, 255, 255)
230    }
231
232    pub fn black_alpha(alpha: u8) -> Self {
233        Self::new(0, 0, 0, alpha)
234    }
235
236    pub fn white_alpha(alpha: u8) -> Self {
237        Self::new(255, 255, 255, alpha)
238    }
239
240    pub fn red_alpha(alpha: u8) -> Self {
241        Self::new(255, 0, 0, alpha)
242    }
243
244    pub fn green_alpha(alpha: u8) -> Self {
245        Self::new(0, 1, 0, alpha)
246    }
247
248    pub fn blue_alpha(alpha: u8) -> Self {
249        Self::new(0, 0, 255, alpha)
250    }
251
252    pub fn r(self) -> u8 {
253        self.r
254    }
255
256    pub fn g(self) -> u8 {
257        self.g
258    }
259
260    pub fn b(self) -> u8 {
261        self.b
262    }
263
264    pub fn a(self) -> u8 {
265        self.a
266    }
267}
268
269impl RGBA32 {
270    pub fn sum(self) -> i32 {
271        self.r as i32 + self.g as i32 + self.b as i32
272    }
273
274    pub fn gray(self) -> u8 {
275        (self.sum() / 3) as u8
276    }
277
278    pub fn min_element(self) -> u8 {
279        self.r.min(self.g).min(self.b).min(self.a)
280    }
281
282    pub fn max_element(self) -> u8 {
283        self.r.max(self.g).max(self.b).max(self.a)
284    }
285
286    pub fn clamp(self, min: Self, max: Self) -> Self {
287        ruby_assert!(min.r <= max.r);
288        ruby_assert!(min.g <= max.g);
289        ruby_assert!(min.b <= max.b);
290        ruby_assert!(min.a <= max.a);
291
292        self.min(max).max(min)
293    }
294
295    pub fn min(self, rhs: Self) -> Self {
296        Self::new(
297            self.r.min(rhs.r),
298            self.g.min(rhs.g),
299            self.b.min(rhs.b),
300            self.a.min(rhs.a),
301        )
302    }
303
304    pub fn max(self, rhs: Self) -> Self {
305        Self::new(
306            self.r.max(rhs.r),
307            self.g.max(rhs.g),
308            self.b.max(rhs.b),
309            self.a.max(rhs.a),
310        )
311    }
312
313    pub fn saturate(self) -> Self {
314        self.clamp(Self::black_alpha(0), Self::white_alpha(255))
315    }
316}
317
318impl RGBA32 {
319    pub fn to_array(self) -> [u8; 4] {
320        [self.r, self.g, self.b, self.a]
321    }
322
323    pub fn to_tuple(self) -> (u8, u8, u8, u8) {
324        (self.r, self.g, self.b, self.a)
325    }
326
327    pub fn to_rgb(self) -> RGB {
328        RGB::new(
329            self.r as f64 / 255.0,
330            self.g as f64 / 255.0,
331            self.b as f64 / 255.0,
332        )
333    }
334
335    pub fn to_rgbf(self) -> RGBf {
336        RGBf::new(
337            self.r as f32 / 255.0,
338            self.g as f32 / 255.0,
339            self.b as f32 / 255.0,
340        )
341    }
342
343    pub fn to_rgba(self) -> RGBA {
344        RGBA::new(
345            self.r as f64 / 255.0,
346            self.g as f64 / 255.0,
347            self.b as f64 / 255.0,
348            self.a as f64 / 255.0,
349        )
350    }
351
352    pub fn to_rgbaf(self) -> RGBAf {
353        RGBAf::new(
354            self.r as f32 / 255.0,
355            self.g as f32 / 255.0,
356            self.b as f32 / 255.0,
357            self.a as f32 / 255.0,
358        )
359    }
360
361    pub fn to_rgb24(self) -> RGB24 {
362        RGB24::new(self.r, self.g, self.b)
363    }
364}