diff --git a/CHANGELOG.md b/CHANGELOG.md index 9bc71d6..1f7b1c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ This release has an [MSRV][] of 1.82. * Support for the ACES2065-1 color space. ([#124][] by [@tomcur][]) * A documentation example implementing `ColorSpace`. ([#130][] by [@tomcur][]) +* Conversions of `[u8; 4]` and packed `u32` into `Rgba8` and `PremulRgba8` are now provided. ([#135][] by [@tomcur][]) ### Fixed @@ -119,6 +120,7 @@ This is the initial release. [#128]: https://github.com/linebender/color/pull/128 [#129]: https://github.com/linebender/color/pull/129 [#130]: https://github.com/linebender/color/pull/130 +[#135]: https://github.com/linebender/color/pull/135 [Unreleased]: https://github.com/linebender/color/compare/v0.2.2...HEAD [0.2.2]: https://github.com/linebender/color/releases/tag/v0.2.2 diff --git a/color/src/rgba8.rs b/color/src/rgba8.rs index 66af91d..d661ed2 100644 --- a/color/src/rgba8.rs +++ b/color/src/rgba8.rs @@ -41,12 +41,27 @@ impl Rgba8 { [self.r, self.g, self.b, self.a] } - /// Returns the color as a little endian packed value, with `a` as the - /// most significant byte and `r` the least. + /// Convert the `[u8; 4]` byte array into an `Rgba8` color. + /// + /// The color values must be given in the order `[r, g, b, a]`. + #[must_use] + pub const fn from_u8_array([r, g, b, a]: [u8; 4]) -> Self { + Self { r, g, b, a } + } + + /// Returns the color as a little-endian packed value, with `r` the least significant byte and + /// `a` the most significant. #[must_use] pub const fn to_u32(self) -> u32 { u32::from_ne_bytes(self.to_u8_array()) } + + /// Interpret the little-endian packed value as a color, with `r` the least significant byte + /// and `a` the most significant. + #[must_use] + pub const fn from_u32(packed_bytes: u32) -> Self { + Self::from_u8_array(u32::to_ne_bytes(packed_bytes)) + } } impl From for AlphaColor { @@ -90,12 +105,27 @@ impl PremulRgba8 { [self.r, self.g, self.b, self.a] } - /// Returns the color as a little endian packed value, with `a` as the - /// most significant byte and `r` the least. + /// Convert the `[u8; 4]` byte array into a `PremulRgba8` color. + /// + /// The color values must be given in the order `[r, g, b, a]`. + #[must_use] + pub const fn from_u8_array([r, g, b, a]: [u8; 4]) -> Self { + Self { r, g, b, a } + } + + /// Returns the color as a little-endian packed value, with `r` the least significant byte and + /// `a` the most significant. #[must_use] pub const fn to_u32(self) -> u32 { u32::from_ne_bytes(self.to_u8_array()) } + + /// Interpret the little-endian packed value as a color, with `r` the least significant byte + /// and `a` the most significant. + #[must_use] + pub const fn from_u32(packed_bytes: u32) -> Self { + Self::from_u8_array(u32::to_ne_bytes(packed_bytes)) + } } /// This is deprecated and will be removed in 0.3.0. @@ -134,6 +164,25 @@ mod tests { assert_eq!(0xffccbbaa_u32.to_le(), p.to_u32()); } + #[test] + fn from_u32() { + let c = Rgba8 { + r: 1, + g: 2, + b: 3, + a: 4, + }; + assert_eq!(Rgba8::from_u32(0x04030201_u32.to_le()), c); + + let p = PremulRgba8 { + r: 0xaa, + g: 0xbb, + b: 0xcc, + a: 0xff, + }; + assert_eq!(PremulRgba8::from_u32(0xffccbbaa_u32.to_le()), p); + } + #[test] #[cfg(feature = "bytemuck")] fn bytemuck_to_u32() { @@ -153,4 +202,14 @@ mod tests { }; assert_eq!(p.to_u32(), bytemuck::cast(p)); } + + #[test] + #[cfg(feature = "bytemuck")] + fn bytemuck_from_u32() { + let c = 0x04030201_u32.to_le(); + assert_eq!(Rgba8::from_u32(c), bytemuck::cast(c)); + + let p = 0xffccbbaa_u32.to_le(); + assert_eq!(PremulRgba8::from_u32(p), bytemuck::cast(p)); + } }