增加指定对比两个颜色的功能。

This commit is contained in:
徐涛 2025-01-13 15:11:03 +08:00
parent 0f343c606e
commit a012f28c47
6 changed files with 246 additions and 0 deletions

View File

@ -0,0 +1,38 @@
use palette::cam16::Cam16Jch;
use serde::Serialize;
use wasm_bindgen::prelude::wasm_bindgen;
use super::{ColorDifference, Differ};
#[derive(Debug, Clone, Copy, Serialize)]
#[wasm_bindgen]
pub struct HctDiffference {
pub hue: Differ,
pub chroma: Differ,
pub lightness: Differ,
}
impl ColorDifference for Cam16Jch<f32> {
type Difference = HctDiffference;
fn difference(&self, other: &Self) -> Self::Difference {
let hue = self.hue.into_positive_degrees() - other.hue.into_positive_degrees();
let chroma = self.chroma - other.chroma;
let lightness = self.lightness - other.lightness;
HctDiffference {
hue: Differ {
delta: hue,
percent: hue / self.hue.into_positive_degrees(),
},
chroma: Differ {
delta: chroma,
percent: chroma / self.chroma,
},
lightness: Differ {
delta: lightness,
percent: lightness / self.lightness,
},
}
}
}

View File

@ -0,0 +1,38 @@
use palette::Hsl;
use serde::Serialize;
use wasm_bindgen::prelude::wasm_bindgen;
use super::{ColorDifference, Differ};
#[derive(Debug, Clone, Copy, Serialize)]
#[wasm_bindgen]
pub struct HSLDifference {
pub hue: Differ,
pub saturation: Differ,
pub lightness: Differ,
}
impl ColorDifference for Hsl {
type Difference = HSLDifference;
fn difference(&self, other: &Self) -> Self::Difference {
let hue = self.hue.into_positive_degrees() - other.hue.into_positive_degrees();
let saturation = self.saturation - other.saturation;
let lightness = self.lightness - other.lightness;
HSLDifference {
hue: Differ {
delta: hue,
percent: hue / self.hue.into_positive_degrees(),
},
saturation: Differ {
delta: saturation,
percent: saturation / self.saturation,
},
lightness: Differ {
delta: lightness,
percent: lightness / self.lightness,
},
}
}
}

View File

@ -0,0 +1,20 @@
use serde::Serialize;
use wasm_bindgen::prelude::wasm_bindgen;
pub mod cam16jch;
pub mod hsl;
pub mod oklch;
pub mod rgb;
#[derive(Debug, Clone, Copy, Serialize)]
#[wasm_bindgen]
pub struct Differ {
pub delta: f32,
pub percent: f32,
}
pub trait ColorDifference {
type Difference;
fn difference(&self, other: &Self) -> Self::Difference;
}

View File

@ -0,0 +1,38 @@
use palette::Oklch;
use serde::Serialize;
use wasm_bindgen::prelude::wasm_bindgen;
use super::{ColorDifference, Differ};
#[derive(Debug, Clone, Copy, Serialize)]
#[wasm_bindgen]
pub struct OklchDifference {
pub hue: Differ,
pub chroma: Differ,
pub lightness: Differ,
}
impl ColorDifference for Oklch {
type Difference = OklchDifference;
fn difference(&self, other: &Self) -> Self::Difference {
let hue = self.hue.into_positive_degrees() - other.hue.into_positive_degrees();
let chroma = self.chroma - other.chroma;
let lightness = self.l - other.l;
OklchDifference {
hue: Differ {
delta: hue,
percent: hue / self.hue.into_positive_degrees(),
},
chroma: Differ {
delta: chroma,
percent: chroma / self.chroma,
},
lightness: Differ {
delta: lightness,
percent: lightness / self.l,
},
}
}
}

View File

@ -0,0 +1,38 @@
use palette::Srgb;
use serde::Serialize;
use wasm_bindgen::prelude::wasm_bindgen;
use super::{ColorDifference, Differ};
#[derive(Debug, Clone, Copy, Serialize)]
#[wasm_bindgen]
pub struct RGBDifference {
pub r: Differ,
pub g: Differ,
pub b: Differ,
}
impl ColorDifference for Srgb {
type Difference = RGBDifference;
fn difference(&self, other: &Self) -> Self::Difference {
let r = self.red - other.red;
let g = self.green - other.green;
let b = self.blue - other.blue;
RGBDifference {
r: Differ {
delta: r,
percent: r / self.red,
},
g: Differ {
delta: g,
percent: g / self.green,
},
b: Differ {
delta: b,
percent: b / self.blue,
},
}
}
}

View File

@ -1,6 +1,7 @@
use std::{str::FromStr, sync::Arc};
use color_card::Category;
use color_differ::ColorDifference;
use palette::{
cam16::{Cam16Jch, Parameters},
color_difference::Wcag21RelativeContrast,
@ -12,6 +13,7 @@ use strum::IntoEnumIterator;
use wasm_bindgen::prelude::*;
mod color_card;
mod color_differ;
mod errors;
#[wasm_bindgen]
@ -422,3 +424,75 @@ pub fn search_color_cards(tag: String, category: Option<String>) -> Result<JsVal
serde_wasm_bindgen::to_value(&cards).map_err(|e| e.to_string())
}
#[wasm_bindgen]
pub fn differ_in_rgb(
color: &str,
other: &str,
) -> Result<color_differ::rgb::RGBDifference, errors::ColorError> {
let srgb = Srgb::from_str(color)
.map_err(|_| errors::ColorError::UnrecogniazedRGB(color.to_string()))?
.into_format::<f32>();
let other_srgb = Srgb::from_str(other)
.map_err(|_| errors::ColorError::UnrecogniazedRGB(other.to_string()))?
.into_format::<f32>();
Ok(srgb.difference(&other_srgb))
}
#[wasm_bindgen]
pub fn differ_in_hsl(
color: &str,
other: &str,
) -> Result<color_differ::hsl::HSLDifference, errors::ColorError> {
let hsl = Hsl::from_color(
Srgb::from_str(color)
.map_err(|_| errors::ColorError::UnrecogniazedRGB(color.to_string()))?
.into_format::<f32>(),
);
let other_hsl = Hsl::from_color(
Srgb::from_str(other)
.map_err(|_| errors::ColorError::UnrecogniazedRGB(other.to_string()))?
.into_format::<f32>(),
);
Ok(hsl.difference(&other_hsl))
}
#[wasm_bindgen]
pub fn differ_in_hct(
color: &str,
other: &str,
) -> Result<color_differ::cam16jch::HctDiffference, errors::ColorError> {
let hct = Cam16Jch::from_xyz(
Srgb::from_str(color)
.map_err(|_| errors::ColorError::UnrecogniazedRGB(color.to_string()))?
.into_format::<f32>()
.into_color(),
Parameters::default_static_wp(40.0),
);
let other_hct = Cam16Jch::from_xyz(
Srgb::from_str(other)
.map_err(|_| errors::ColorError::UnrecogniazedRGB(other.to_string()))?
.into_format::<f32>()
.into_color(),
Parameters::default_static_wp(40.0),
);
Ok(hct.difference(&other_hct))
}
#[wasm_bindgen]
pub fn differ_in_oklch(
color: &str,
other: &str,
) -> Result<color_differ::oklch::OklchDifference, errors::ColorError> {
let oklch = Oklch::from_color(
Srgb::from_str(color)
.map_err(|_| errors::ColorError::UnrecogniazedRGB(color.to_string()))?
.into_format::<f32>(),
);
let other_oklch = Oklch::from_color(
Srgb::from_str(other)
.map_err(|_| errors::ColorError::UnrecogniazedRGB(other.to_string()))?
.into_format::<f32>(),
);
Ok(oklch.difference(&other_oklch))
}