devela/media/color/rgb/impls/
u16alpha.rs

1// devela::media::color::rgb::impls::u16alpha
2
3use super::*;
4use crate::{Norm, Rgb16, Rgba16};
5
6#[cfg(feature = "_float_f32")]
7use crate::{RgbF32, RgbaF32};
8#[cfg(feature = "_float_f64")]
9use crate::{RgbF64, RgbaF64};
10
11#[allow(missing_docs)]
12#[rustfmt::skip]
13impl Rgba16 {
14    /// New `Rgba<u16>`.
15    pub const fn new(r: u16, g: u16, b: u16, a: u16) -> Rgba16 { Self { c: [r, g, b, a] } }
16    /// The red component.
17    pub const fn red(self) -> u16 { self.c[0] }
18    pub const fn r(self) -> u16 { self.c[0] }
19    /// The green component.
20    pub const fn green(self) -> u16 { self.c[1] }
21    pub const fn g(self) -> u16 { self.c[1] }
22    /// The blue component.
23    pub const fn blue(self) -> u16 { self.c[2] }
24    pub const fn b(self) -> u16 { self.c[2] }
25    /// The alpha component.
26    pub const fn alpha(self) -> u16 { self.c[3] }
27    pub const fn a(self) -> u16 { self.c[3] }
28}
29
30/// # General conversions
31impl Rgba16 {
32    /// Create from an array.
33    pub const fn from_array(c: [u16; 4]) -> Rgba16 {
34        Rgba16 { c }
35    }
36    /// Convert to an array.
37    pub const fn as_array(self) -> [u16; 4] {
38        self.c
39    }
40
41    /// Create from a tuple.
42    pub const fn from_tuple(c: (u16, u16, u16, u16)) -> Rgba16 {
43        Rgba16::new(c.0, c.1, c.2, c.3)
44    }
45    /// Convert to a tuple.
46    pub const fn to_tuple(self) -> (u16, u16, u16, u16) {
47        (self.r(), self.g(), self.b(), self.a())
48    }
49
50    /* Rgb16 */
51
52    /// Create from [`Rgb<u16>`].
53    ///
54    /// Adds the given `alpha` channel.
55    pub const fn from_rgb16(c: Rgb16, alpha: u16) -> Rgba16 {
56        Rgba16::new(c.r(), c.g(), c.b(), alpha)
57    }
58    /// Convert to [`Rgb<u16>`].
59    ///
60    /// Loses the alpha channel.
61    pub const fn to_rgb16(self) -> Rgb16 {
62        Rgb16::new(self.r(), self.g(), self.b())
63    }
64
65    /* packed u64 */
66
67    /// Create from a packed `u64` in `0xRRRRGGGGBBBBAAAA` format, with the given `alpha`.
68    ///
69    /// Any bits above `0x0000_FFFF_FFFF` are ignored.
70    pub const fn from_rgb16_packed(packed: u64, alpha: u16) -> Rgba16 {
71        Rgba16::new(
72            ((packed >> 32) & 0xFFFF) as u16,
73            ((packed >> 16) & 0xFFFF) as u16,
74            (packed & 0xFFFF) as u16,
75            alpha,
76        )
77    }
78    /// Convert to a packed `u64` in `0xRRRRGGGGBBBB` format, discarding alpha.
79    pub const fn to_rgb16_packed(self) -> u64 {
80        ((self.r() as u64) << 32) | ((self.g() as u64) << 16) | (self.b() as u64)
81    }
82
83    /// Create from a packed `u64` in `0xRRRRGGGGBBBBAAAA` format (big-endian).
84    pub const fn from_rgba16_packed(packed: u64) -> Rgba16 {
85        Rgba16::new(
86            ((packed >> 48) & 0xFFFF) as u16,
87            ((packed >> 32) & 0xFFFF) as u16,
88            ((packed >> 16) & 0xFFFF) as u16,
89            (packed & 0xFFFF) as u16,
90        )
91    }
92    /// Convert to a packed `u64` in `0xRRRRGGGGBBBBAAAA` format (big-endian).
93    pub const fn to_rgba16_packed(self) -> u64 {
94        ((self.r() as u64) << 48)
95            | ((self.g() as u64) << 32)
96            | ((self.b() as u64) << 16)
97            | (self.a() as u64)
98    }
99}
100#[rustfmt::skip]
101impl From<Rgb16> for Rgba16 {
102    fn from(from: Rgb16) -> Rgba16 { Rgba16::from_rgb16(from, u16::MAX) } }
103
104/// # `f32` conversions
105#[cfg(feature = "_float_f32")]
106#[cfg_attr(nightly_doc, doc(cfg(feature = "_float_f32")))]
107impl Rgba16 {
108    /// Create from [`Rgb<f32>`].
109    ///
110    /// Adds the given `alpha` channel.
111    pub const fn from_rgb_f32(c: RgbF32, alpha: f32) -> Rgba16 {
112        Rgba16::new(
113            Norm::f32_to_u16(c.r()),
114            Norm::f32_to_u16(c.g()),
115            Norm::f32_to_u16(c.b()),
116            Norm::f32_to_u16(alpha),
117        )
118    }
119    /// Convert to [`Rgb<f32>`].
120    ///
121    /// Loses the alpha channel.
122    pub const fn to_rgb_f32(self) -> RgbF32 {
123        RgbF32::new(
124            Norm::u16_to_f32(self.r()),
125            Norm::u16_to_f32(self.g()),
126            Norm::u16_to_f32(self.b()),
127        )
128    }
129
130    /// Create from [`Rgba<f32>`].
131    pub const fn from_rgba_f32(c: RgbaF32) -> Rgba16 {
132        Rgba16::new(
133            Norm::f32_to_u16(c.r()),
134            Norm::f32_to_u16(c.g()),
135            Norm::f32_to_u16(c.b()),
136            Norm::f32_to_u16(c.a()),
137        )
138    }
139    /// Convert to [`Rgba<f32>`].
140    pub const fn to_rgba_f32(self) -> RgbaF32 {
141        RgbaF32::new(
142            Norm::u16_to_f32(self.r()),
143            Norm::u16_to_f32(self.g()),
144            Norm::u16_to_f32(self.b()),
145            Norm::u16_to_f32(self.a()),
146        )
147    }
148}
149
150/// # `f64` conversions
151#[cfg(feature = "_float_f64")]
152#[cfg_attr(nightly_doc, doc(cfg(feature = "_float_f64")))]
153impl Rgba16 {
154    /// Create from [`Rgb<f64>`].
155    ///
156    /// Adds the given `alpha` channel.
157    pub const fn from_rgb_f64(c: RgbF64, alpha: f64) -> Rgba16 {
158        Rgba16::new(
159            Norm::f64_to_u16(c.r()),
160            Norm::f64_to_u16(c.g()),
161            Norm::f64_to_u16(c.b()),
162            Norm::f64_to_u16(alpha),
163        )
164    }
165    /// Convert to [`Rgb<f64>`].
166    ///
167    /// Loses the alpha channel.
168    pub const fn to_rgb_f64(self) -> RgbF64 {
169        RgbF64::new(
170            Norm::u16_to_f64(self.r()),
171            Norm::u16_to_f64(self.g()),
172            Norm::u16_to_f64(self.b()),
173        )
174    }
175
176    /// Create from [`Rgba<f64>`].
177    pub const fn from_rgba_f64(c: RgbaF64) -> Rgba16 {
178        Rgba16::new(
179            Norm::f64_to_u16(c.r()),
180            Norm::f64_to_u16(c.g()),
181            Norm::f64_to_u16(c.b()),
182            Norm::f64_to_u16(c.a()),
183        )
184    }
185    /// Convert to [`Rgba<f64>`].
186    pub const fn to_rgba_f64(self) -> RgbaF64 {
187        RgbaF64::new(
188            Norm::u16_to_f64(self.r()),
189            Norm::u16_to_f64(self.g()),
190            Norm::u16_to_f64(self.b()),
191            Norm::u16_to_f64(self.a()),
192        )
193    }
194}
195
196#[cfg(test)]
197mod tests {
198    use super::*;
199
200    const C16: Rgb16 = Rgb16::new(2570, 5140, 7710);
201    const CA16: Rgba16 = Rgba16::new(2570, 5140, 7710, 10280);
202    const H16: u64 = 0x_0A0A_1414_1E1E;
203    const HA16: u64 = 0x_0A0A_1414_1E1E_2828;
204
205    #[test]
206    fn general_conversions() {
207        // array/tuple
208        assert_eq![Rgba16::from_array([2570, 5140, 7710, 10280]), CA16];
209        assert_eq![CA16.as_array(), [2570, 5140, 7710, 10280]];
210        assert_eq![Rgba16::from_tuple((2570, 5140, 7710, 10280)), CA16];
211        assert_eq![CA16.to_tuple(), (2570, 5140, 7710, 10280)];
212        // rgb
213        assert_eq![Rgba16::from_rgb16(C16, 10280), CA16];
214        assert_eq![CA16.to_rgb16(), C16];
215        // packed rgba
216        assert_eq![Rgba16::from_rgba16_packed(HA16), CA16];
217        assert_eq![CA16.to_rgba16_packed(), HA16];
218        // packed rgb
219        assert_eq![Rgba16::from_rgb16_packed(H16, 10280), CA16];
220        assert_eq![CA16.to_rgb16_packed(), H16];
221    }
222
223    #[test]
224    #[cfg(feature = "_float_f32")]
225    fn f32_conversions() {
226        let f = RgbF32::new(0.039215688, 0.078431375, 0.11764706);
227        let fa = RgbaF32::new(0.039215688, 0.078431375, 0.11764706, 0.15686275);
228        assert_eq![Rgba16::from_rgb_f32(f, 0.15686), CA16];
229        assert_eq![CA16.to_rgb_f32(), f];
230        assert_eq![Rgba16::from_rgba_f32(fa), CA16];
231        assert_eq![CA16.to_rgba_f32(), fa];
232    }
233
234    #[test]
235    #[cfg(feature = "_float_f64")]
236    fn f64_conversions() {
237        let f = RgbF64::new(0.0392156862745098, 0.0784313725490196, 0.11764705882352941);
238        let fa = RgbaF64::new(
239            0.0392156862745098,
240            0.0784313725490196,
241            0.11764705882352941,
242            0.1568627450980392,
243        );
244        assert_eq![Rgba16::from_rgb_f64(f, 0.15686), CA16];
245        assert_eq![CA16.to_rgb_f64(), f];
246        assert_eq![Rgba16::from_rgba_f64(fa), CA16];
247        assert_eq![CA16.to_rgba_f64(), fa];
248    }
249}