Skip to content

Commit

Permalink
Merge pull request #424 from Ogeon/more_hex
Browse files Browse the repository at this point in the history
Add `Rgb::from_hex` and implement parsing for `u16`, `u32`, `f32`, `f64`
  • Loading branch information
Ogeon authored Nov 17, 2024
2 parents 8e22189 + d626898 commit 234309c
Show file tree
Hide file tree
Showing 9 changed files with 462 additions and 74 deletions.
8 changes: 4 additions & 4 deletions palette/src/color_difference.rs
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ pub trait EuclideanDistance: Sized {
///
/// // the rustdoc "DARK" theme background and text colors
/// let background: Srgb<f32> = Srgb::from(0x353535).into_format();
/// let foreground = Srgb::from_str("#ddd")?.into_format();
/// let foreground = Srgb::from_str("#ddd")?;
///
/// assert!(background.has_enhanced_contrast_text(foreground));
/// # Ok(())
Expand Down Expand Up @@ -515,7 +515,7 @@ mod test {
black.relative_contrast(white)
);

let c1 = Srgb::from_str("#600").unwrap().into_format();
let c1 = Srgb::from_str("#600").unwrap();

assert_relative_eq!(c1.relative_contrast(white), 13.41, epsilon = 0.01);
assert_relative_eq!(c1.relative_contrast(black), 1.56, epsilon = 0.01);
Expand All @@ -532,12 +532,12 @@ mod test {
assert!(!c1.has_enhanced_contrast_large_text(black));
assert!(!c1.has_min_contrast_graphics(black));

let c1 = Srgb::from_str("#066").unwrap().into_format();
let c1 = Srgb::from_str("#066").unwrap();

assert_relative_eq!(c1.relative_contrast(white), 6.79, epsilon = 0.01);
assert_relative_eq!(c1.relative_contrast(black), 3.09, epsilon = 0.01);

let c1 = Srgb::from_str("#9f9").unwrap().into_format();
let c1 = Srgb::from_str("#9f9").unwrap();

assert_relative_eq!(c1.relative_contrast(white), 1.22, epsilon = 0.01);
assert_relative_eq!(c1.relative_contrast(black), 17.11, epsilon = 0.01);
Expand Down
2 changes: 1 addition & 1 deletion palette/src/okhsl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ mod tests {
#[test]
fn test_srgb_to_okhsl() {
let red_hex = "#834941";
let rgb: Srgb<f64> = Srgb::from_str(red_hex).unwrap().into_format();
let rgb: Srgb<f64> = Srgb::from_str(red_hex).unwrap();
let lin_rgb = LinSrgb::<f64>::from_color_unclamped(rgb);
let oklab = Oklab::from_color_unclamped(lin_rgb);
println!(
Expand Down
6 changes: 1 addition & 5 deletions palette/src/okhsv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -292,8 +292,6 @@ mod tests {

#[cfg(feature = "approx")]
mod conversion {
use core::str::FromStr;

use crate::{
convert::FromColorUnclamped, encoding, rgb::Rgb, visual::VisuallyEqual, LinSrgb, Okhsv,
Oklab, OklabHue, Srgb,
Expand Down Expand Up @@ -403,9 +401,7 @@ mod tests {
#[test]
fn test_srgb_to_okhsv() {
let red_hex = "#ff0004";
let rgb: Srgb = Rgb::<encoding::Srgb, _>::from_str(red_hex)
.unwrap()
.into_format();
let rgb: Srgb = red_hex.parse().unwrap();
let okhsv = Okhsv::from_color_unclamped(rgb);
assert_relative_eq!(okhsv.saturation, 1.0, epsilon = 1e-3);
assert_relative_eq!(okhsv.value, 1.0, epsilon = 1e-3);
Expand Down
4 changes: 2 additions & 2 deletions palette/src/oklab.rs
Original file line number Diff line number Diff line change
Expand Up @@ -545,7 +545,7 @@ mod test {
/// Asserts that, for any color space, the lightness of pure white is converted to `l == 1.0`
#[test]
fn lightness_of_white_is_one() {
let rgb: Srgb<f64> = Rgb::from_str("#ffffff").unwrap().into_format();
let rgb: Srgb<f64> = Rgb::from_str("#ffffff").unwrap();
let lin_rgb = LinSrgb::from_color_unclamped(rgb);
let oklab = Oklab::from_color_unclamped(lin_rgb);
println!("white {rgb:?} == {oklab:?}");
Expand All @@ -565,7 +565,7 @@ mod test {
#[test]
fn blue_srgb() {
// use f64 to be comparable to javascript
let rgb: Srgb<f64> = Rgb::from_str("#0000ff").unwrap().into_format();
let rgb: Srgb<f64> = Rgb::from_str("#0000ff").unwrap();
let lin_rgb = LinSrgb::from_color_unclamped(rgb);
let oklab = Oklab::from_color_unclamped(lin_rgb);

Expand Down
8 changes: 4 additions & 4 deletions palette/src/relative_contrast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use crate::{
///
/// // the rustdoc "DARK" theme background and text colors
/// let background: Srgb<f32> = Srgb::from(0x353535).into_format();
/// let foreground = Srgb::from_str("#ddd")?.into_format();
/// let foreground = Srgb::from_str("#ddd")?;
///
/// assert!(background.has_enhanced_contrast_text(foreground));
/// # Ok(())
Expand Down Expand Up @@ -145,7 +145,7 @@ mod test {
black.get_contrast_ratio(white)
);

let c1 = Srgb::from_str("#600").unwrap().into_format();
let c1 = Srgb::from_str("#600").unwrap();

assert_relative_eq!(c1.get_contrast_ratio(white), 13.41, epsilon = 0.01);
assert_relative_eq!(c1.get_contrast_ratio(black), 1.56, epsilon = 0.01);
Expand All @@ -162,12 +162,12 @@ mod test {
assert!(!c1.has_enhanced_contrast_large_text(black));
assert!(!c1.has_min_contrast_graphics(black));

let c1 = Srgb::from_str("#066").unwrap().into_format();
let c1 = Srgb::from_str("#066").unwrap();

assert_relative_eq!(c1.get_contrast_ratio(white), 6.79, epsilon = 0.01);
assert_relative_eq!(c1.get_contrast_ratio(black), 3.09, epsilon = 0.01);

let c1 = Srgb::from_str("#9f9").unwrap().into_format();
let c1 = Srgb::from_str("#9f9").unwrap();

assert_relative_eq!(c1.get_contrast_ratio(white), 1.22, epsilon = 0.01);
assert_relative_eq!(c1.get_contrast_ratio(black), 17.11, epsilon = 0.01);
Expand Down
1 change: 1 addition & 0 deletions palette/src/rgb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ use crate::{
pub use self::rgb::{FromHexError, Iter, Rgb, Rgba};

pub mod channels;
mod hex;
#[allow(clippy::module_inception)]
mod rgb;

Expand Down
69 changes: 69 additions & 0 deletions palette/src/rgb/hex.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
use core::num::ParseIntError;

#[inline]
pub(crate) fn rgb_from_hex_4bit(hex: &str) -> Result<(u8, u8, u8), ParseIntError> {
let red = u8::from_str_radix(&hex[..1], 16)?;
let green = u8::from_str_radix(&hex[1..2], 16)?;
let blue = u8::from_str_radix(&hex[2..3], 16)?;

Ok((red * 17, green * 17, blue * 17))
}

#[inline]
pub(crate) fn rgba_from_hex_4bit(hex: &str) -> Result<(u8, u8, u8, u8), ParseIntError> {
let (red, green, blue) = rgb_from_hex_4bit(hex)?;
let alpha = u8::from_str_radix(&hex[3..4], 16)?;

Ok((red, green, blue, alpha * 17))
}

#[inline]
pub(crate) fn rgb_from_hex_8bit(hex: &str) -> Result<(u8, u8, u8), ParseIntError> {
let red = u8::from_str_radix(&hex[..2], 16)?;
let green = u8::from_str_radix(&hex[2..4], 16)?;
let blue = u8::from_str_radix(&hex[4..6], 16)?;

Ok((red, green, blue))
}

#[inline]
pub(crate) fn rgba_from_hex_8bit(hex: &str) -> Result<(u8, u8, u8, u8), ParseIntError> {
let (red, green, blue) = rgb_from_hex_8bit(hex)?;
let alpha = u8::from_str_radix(&hex[6..8], 16)?;

Ok((red, green, blue, alpha))
}

#[inline]
pub(crate) fn rgb_from_hex_16bit(hex: &str) -> Result<(u16, u16, u16), ParseIntError> {
let red = u16::from_str_radix(&hex[..4], 16)?;
let green = u16::from_str_radix(&hex[4..8], 16)?;
let blue = u16::from_str_radix(&hex[8..12], 16)?;

Ok((red, green, blue))
}

#[inline]
pub(crate) fn rgba_from_hex_16bit(hex: &str) -> Result<(u16, u16, u16, u16), ParseIntError> {
let (red, green, blue) = rgb_from_hex_16bit(hex)?;
let alpha = u16::from_str_radix(&hex[12..16], 16)?;

Ok((red, green, blue, alpha))
}

#[inline]
pub(crate) fn rgb_from_hex_32bit(hex: &str) -> Result<(u32, u32, u32), ParseIntError> {
let red = u32::from_str_radix(&hex[..8], 16)?;
let green = u32::from_str_radix(&hex[8..16], 16)?;
let blue = u32::from_str_radix(&hex[16..24], 16)?;

Ok((red, green, blue))
}

#[inline]
pub(crate) fn rgba_from_hex_32bit(hex: &str) -> Result<(u32, u32, u32, u32), ParseIntError> {
let (red, green, blue) = rgb_from_hex_32bit(hex)?;
let alpha = u32::from_str_radix(&hex[24..32], 16)?;

Ok((red, green, blue, alpha))
}
Loading

0 comments on commit 234309c

Please sign in to comment.