color-q/color-module/src/lib.rs

149 lines
4.4 KiB
Rust

use std::str::FromStr;
use palette::{
cam16::{Cam16Jch, Parameters},
color_difference::Wcag21RelativeContrast,
convert::FromColorUnclamped,
FromColor, Hsl, IntoColor, IsWithinBounds, Lab, Oklch, Srgb,
};
use wasm_bindgen::prelude::*;
mod analysis;
mod color_card;
mod color_differ;
mod color_shifting;
mod convert;
mod errors;
mod palettes;
mod reversing;
mod schemes;
mod series;
mod theory;
#[wasm_bindgen]
pub fn represent_rgb(color: &str) -> Result<Box<[u8]>, errors::ColorError> {
let srgb = Srgb::from_str(color)
.map_err(|_| errors::ColorError::UnrecogniazedRGB(color.to_string()))?
.into_format::<u8>();
Ok(Box::new([srgb.red, srgb.green, srgb.blue]))
}
#[wasm_bindgen]
pub fn rgb_to_hex(r: u8, g: u8, b: u8) -> Result<String, errors::ColorError> {
let srgb = Srgb::new(r, g, b);
Ok(format!("{:x}", srgb))
}
#[wasm_bindgen]
pub fn represent_hsl(color: &str) -> Result<Box<[f32]>, errors::ColorError> {
let origin_color = Srgb::from_str(color)
.map_err(|_| errors::ColorError::UnrecogniazedRGB(color.to_string()))?
.into_format::<f32>();
let hsl = Hsl::from_color(origin_color);
Ok(Box::new([
hsl.hue.into_positive_degrees(),
hsl.saturation,
hsl.lightness,
]))
}
#[wasm_bindgen]
pub fn hsl_to_hex(h: f32, s: f32, l: f32) -> Result<String, errors::ColorError> {
let hsl = Hsl::new(h, s, l);
let srgb = Srgb::from_color_unclamped(hsl);
if !srgb.is_within_bounds() {
return Err(errors::ColorError::ComponentOutOfBounds);
}
Ok(format!("{:x}", srgb.into_format::<u8>()))
}
#[wasm_bindgen]
pub fn represent_lab(color: &str) -> Result<Box<[f32]>, errors::ColorError> {
let origin_color = Srgb::from_str(color)
.map_err(|_| errors::ColorError::UnrecogniazedRGB(color.to_string()))?
.into_format::<f32>();
let lab = Lab::from_color(origin_color);
Ok(Box::new([lab.l, lab.a, lab.b]))
}
#[wasm_bindgen]
pub fn lab_to_hex(l: f32, a: f32, b: f32) -> Result<String, errors::ColorError> {
let lab = Lab::new(l, a, b);
let srgb = Srgb::from_color_unclamped(lab);
if !srgb.is_within_bounds() {
return Err(errors::ColorError::ComponentOutOfBounds);
}
Ok(format!("{:x}", srgb.into_format::<u8>()))
}
#[wasm_bindgen]
pub fn represent_oklch(color: &str) -> Result<Box<[f32]>, errors::ColorError> {
let origin_color = Srgb::from_str(color)
.map_err(|_| errors::ColorError::UnrecogniazedRGB(color.to_string()))?
.into_format::<f32>();
let lch = Oklch::from_color(origin_color);
Ok(Box::new([
lch.l,
lch.chroma,
lch.hue.into_positive_degrees(),
]))
}
#[wasm_bindgen]
pub fn oklch_to_hex(l: f32, c: f32, h: f32) -> Result<String, errors::ColorError> {
let lch = Oklch::new(l, c, h);
let srgb = Srgb::from_color_unclamped(lch);
if !srgb.is_within_bounds() {
return Err(errors::ColorError::ComponentOutOfBounds);
}
Ok(format!("{:x}", srgb.into_format::<u8>()))
}
#[wasm_bindgen]
pub fn represent_hct(color: &str) -> Result<Box<[f32]>, errors::ColorError> {
let origin_color = Srgb::from_str(color)
.map_err(|_| errors::ColorError::UnrecogniazedRGB(color.to_string()))?
.into_format::<f32>();
let hct = Cam16Jch::from_xyz(
origin_color.into_color(),
Parameters::default_static_wp(40.0),
);
Ok(Box::new([
hct.hue.into_positive_degrees(),
hct.chroma,
hct.lightness,
]))
}
#[wasm_bindgen]
pub fn hct_to_hex(hue: f32, chroma: f32, tone: f32) -> Result<String, errors::ColorError> {
let hct = Cam16Jch::new(tone, chroma, hue);
let srgb = Srgb::from_color_unclamped(hct.into_xyz(Parameters::default_static_wp(40.0)));
if !srgb.is_within_bounds() {
return Err(errors::ColorError::ComponentOutOfBounds);
}
Ok(format!("{:x}", srgb.into_format::<u8>()))
}
#[wasm_bindgen]
pub fn wacg_relative_contrast(fg_color: &str, bg_color: &str) -> Result<f32, errors::ColorError> {
let fg_srgb = Srgb::from_str(fg_color)
.map_err(|_| errors::ColorError::UnrecogniazedRGB(fg_color.to_string()))?
.into_format::<f32>();
let bg_srgb = Srgb::from_str(bg_color)
.map_err(|_| errors::ColorError::UnrecogniazedRGB(bg_color.to_string()))?
.into_format::<f32>();
Ok(fg_srgb.relative_contrast(bg_srgb))
}
#[macro_export]
macro_rules! cond {
($s: expr, $a: expr, $b: expr) => {
if $s {
$a
} else {
$b
}
};
}