Skip to content

Commit

Permalink
Implement (Premul)Rgba8::from_u32 and from_u8_array (#135)
Browse files Browse the repository at this point in the history
Closes #73.

The conversions from the packed u32 are easy to get wrong when
implemented manually.

(On the other hand, these methods are also easy to use wrong.)
  • Loading branch information
tomcur authored Jan 18, 2025
1 parent b0b868e commit 2f4652e
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 4 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand Down
67 changes: 63 additions & 4 deletions color/src/rgba8.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Rgba8> for AlphaColor<Srgb> {
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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() {
Expand All @@ -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));
}
}

0 comments on commit 2f4652e

Please sign in to comment.