1#[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}