From a012f28c4793e5e855e41931496b3487e2370244 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E6=B6=9B?= Date: Mon, 13 Jan 2025 15:11:03 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=8C=87=E5=AE=9A=E5=AF=B9?= =?UTF-8?q?=E6=AF=94=E4=B8=A4=E4=B8=AA=E9=A2=9C=E8=89=B2=E7=9A=84=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- color-module/src/color_differ/cam16jch.rs | 38 ++++++++++++ color-module/src/color_differ/hsl.rs | 38 ++++++++++++ color-module/src/color_differ/mod.rs | 20 ++++++ color-module/src/color_differ/oklch.rs | 38 ++++++++++++ color-module/src/color_differ/rgb.rs | 38 ++++++++++++ color-module/src/lib.rs | 74 +++++++++++++++++++++++ 6 files changed, 246 insertions(+) create mode 100644 color-module/src/color_differ/cam16jch.rs create mode 100644 color-module/src/color_differ/hsl.rs create mode 100644 color-module/src/color_differ/mod.rs create mode 100644 color-module/src/color_differ/oklch.rs create mode 100644 color-module/src/color_differ/rgb.rs diff --git a/color-module/src/color_differ/cam16jch.rs b/color-module/src/color_differ/cam16jch.rs new file mode 100644 index 0000000..cd6f583 --- /dev/null +++ b/color-module/src/color_differ/cam16jch.rs @@ -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 { + 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, + }, + } + } +} diff --git a/color-module/src/color_differ/hsl.rs b/color-module/src/color_differ/hsl.rs new file mode 100644 index 0000000..d15571a --- /dev/null +++ b/color-module/src/color_differ/hsl.rs @@ -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, + }, + } + } +} diff --git a/color-module/src/color_differ/mod.rs b/color-module/src/color_differ/mod.rs new file mode 100644 index 0000000..0fe1083 --- /dev/null +++ b/color-module/src/color_differ/mod.rs @@ -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; +} diff --git a/color-module/src/color_differ/oklch.rs b/color-module/src/color_differ/oklch.rs new file mode 100644 index 0000000..3ed99c9 --- /dev/null +++ b/color-module/src/color_differ/oklch.rs @@ -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, + }, + } + } +} diff --git a/color-module/src/color_differ/rgb.rs b/color-module/src/color_differ/rgb.rs new file mode 100644 index 0000000..813e47b --- /dev/null +++ b/color-module/src/color_differ/rgb.rs @@ -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, + }, + } + } +} diff --git a/color-module/src/lib.rs b/color-module/src/lib.rs index 502cc4a..b2f407c 100644 --- a/color-module/src/lib.rs +++ b/color-module/src/lib.rs @@ -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) -> Result Result { + let srgb = Srgb::from_str(color) + .map_err(|_| errors::ColorError::UnrecogniazedRGB(color.to_string()))? + .into_format::(); + let other_srgb = Srgb::from_str(other) + .map_err(|_| errors::ColorError::UnrecogniazedRGB(other.to_string()))? + .into_format::(); + Ok(srgb.difference(&other_srgb)) +} + +#[wasm_bindgen] +pub fn differ_in_hsl( + color: &str, + other: &str, +) -> Result { + let hsl = Hsl::from_color( + Srgb::from_str(color) + .map_err(|_| errors::ColorError::UnrecogniazedRGB(color.to_string()))? + .into_format::(), + ); + let other_hsl = Hsl::from_color( + Srgb::from_str(other) + .map_err(|_| errors::ColorError::UnrecogniazedRGB(other.to_string()))? + .into_format::(), + ); + Ok(hsl.difference(&other_hsl)) +} + +#[wasm_bindgen] +pub fn differ_in_hct( + color: &str, + other: &str, +) -> Result { + let hct = Cam16Jch::from_xyz( + Srgb::from_str(color) + .map_err(|_| errors::ColorError::UnrecogniazedRGB(color.to_string()))? + .into_format::() + .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::() + .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 { + let oklch = Oklch::from_color( + Srgb::from_str(color) + .map_err(|_| errors::ColorError::UnrecogniazedRGB(color.to_string()))? + .into_format::(), + ); + let other_oklch = Oklch::from_color( + Srgb::from_str(other) + .map_err(|_| errors::ColorError::UnrecogniazedRGB(other.to_string()))? + .into_format::(), + ); + Ok(oklch.difference(&other_oklch)) +}