re_components/
color.rs

1/// An RGBA color tuple with unmultiplied/separate alpha,
2/// in sRGB gamma space with linear alpha.
3///
4/// ```
5/// use re_components::ColorRGBA;
6/// use arrow2_convert::field::ArrowField;
7/// use arrow2::datatypes::{DataType, Field};
8///
9/// assert_eq!(ColorRGBA::data_type(), DataType::UInt32);
10/// ```
11#[derive(
12    Clone,
13    Copy,
14    Debug,
15    PartialEq,
16    Eq,
17    bytemuck::Pod,
18    bytemuck::Zeroable,
19    arrow2_convert::ArrowField,
20    arrow2_convert::ArrowSerialize,
21    arrow2_convert::ArrowDeserialize,
22)]
23#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
24#[arrow_field(transparent)]
25#[repr(transparent)]
26pub struct ColorRGBA(pub u32);
27
28impl ColorRGBA {
29    #[inline]
30    pub fn from_rgb(r: u8, g: u8, b: u8) -> Self {
31        Self::from([r, g, b, 255])
32    }
33
34    #[inline]
35    pub fn from_unmultiplied_rgba(r: u8, g: u8, b: u8, a: u8) -> Self {
36        Self::from([r, g, b, a])
37    }
38
39    #[inline]
40    pub fn to_array(self) -> [u8; 4] {
41        [
42            (self.0 >> 24) as u8,
43            (self.0 >> 16) as u8,
44            (self.0 >> 8) as u8,
45            self.0 as u8,
46        ]
47    }
48}
49
50impl From<[u8; 4]> for ColorRGBA {
51    #[inline]
52    fn from(bytes: [u8; 4]) -> Self {
53        Self(
54            (bytes[0] as u32) << 24
55                | (bytes[1] as u32) << 16
56                | (bytes[2] as u32) << 8
57                | (bytes[3] as u32),
58        )
59    }
60}
61
62impl re_log_types::LegacyComponent for ColorRGBA {
63    #[inline]
64    fn legacy_name() -> re_log_types::ComponentName {
65        "rerun.colorrgba".into()
66    }
67}
68
69#[cfg(feature = "ecolor")]
70impl From<ColorRGBA> for ecolor::Color32 {
71    fn from(color: ColorRGBA) -> Self {
72        let [r, g, b, a] = color.to_array();
73        Self::from_rgba_premultiplied(r, g, b, a)
74    }
75}
76
77re_log_types::component_legacy_shim!(ColorRGBA);
78
79#[test]
80fn test_colorrgba_roundtrip() {
81    use arrow2::array::Array;
82    use arrow2_convert::{deserialize::TryIntoCollection, serialize::TryIntoArrow};
83
84    let colors_in = vec![ColorRGBA(0u32), ColorRGBA(255u32)];
85    let array: Box<dyn Array> = colors_in.try_into_arrow().unwrap();
86    let colors_out: Vec<ColorRGBA> = TryIntoCollection::try_into_collection(array).unwrap();
87    assert_eq!(colors_in, colors_out);
88}