feat(design): 配色来源纯数学层(Monet 式量化取色 + 色卡 + 三级回落 + 对比度收敛)
D40 分层:design 保持零第三方依赖,只吃已解码的 RGBA 像素。 - palette/quantize:5bit 直方图 + CIELAB k-means(QuantizerCelebi/Score 的形状) - palette/score:官方 Score 口径(CUTOFF_CHROMA 5 / TARGET 48 / 权重 0.7+0.3) - palette/seed:seed_from_rgba + D40 彩度门槛 8,灰白图回落而非凭空上色 - palette/card:8 张内置色卡,key 为持久化键 - palette/wcag:26 对文字对比度门禁 + 沿 tone 轴收敛并记录修正 - palette/resolve:纯函数三级来源编排 + Provenance(原因码/提示键)
This commit is contained in:
1 parent
c1fc5b8086
commit
18327fb038
11 files changed
+2098
-2
No files matched your search
@@ -114,7 +114,8 @@ pub mod tonal;
|
||||
mod cam16;
|
||||
mod critical_planes;
|
||||
mod hct_solver;
|
||||
mod space;
|
||||
// `pub(crate)`:取色量化(`crate::palette::quantize`)要在 CIELAB 里算簇距离,复用同一套换算。
|
||||
pub(crate) mod space;
|
||||
mod viewing_conditions;
|
||||
|
||||
pub use hct::Hct;
|
||||
|
||||
@@ -212,6 +212,18 @@ impl Scheme {
|
||||
Self { flavor, colors }
|
||||
}
|
||||
|
||||
/// 从 49 个已解析色值直接构造(**底层入口**,下标必须等于 `Role as usize`)。
|
||||
///
|
||||
/// 只给两类调用方用:
|
||||
/// 1. `palette::wcag` 的对比度收敛——它按角色替换个别色值后要重新组装成一套方案;
|
||||
/// 2. 测试——要能构造「故意不达标」的方案,比较度校验器才有反证。
|
||||
///
|
||||
/// 常规路径一律走 [`Scheme::from_palettes`]:那样色值才是 tone 表的推导结果,
|
||||
/// 而不是随手塞进来的数。
|
||||
pub fn from_colors(flavor: SchemeFlavor, colors: [Color; 49]) -> Self {
|
||||
Self { flavor, colors }
|
||||
}
|
||||
|
||||
/// 该角色在指定模式下的 tone 值(M3 语义;文档表格、调试与测试用)。
|
||||
pub fn tone_of(role: Role, flavor: SchemeFlavor) -> f64 {
|
||||
let entry = &TONE_TABLE[role as usize];
|
||||
|
||||
@@ -109,6 +109,20 @@ pub(crate) fn lstar_from_color(color: Color) -> f64 {
|
||||
lstar_from_y(xyz_from_color(color)[1])
|
||||
}
|
||||
|
||||
/// 色值 → CIELAB(`[L*, a*, b*]`)。
|
||||
///
|
||||
/// `L*` 与 [`lstar_from_color`] 逐值相同(同一个 `lab_f`);`a*`/`b*` 走 D65 白点归一。
|
||||
/// 取色量化(`crate::palette::quantize`)用它在感知空间里算簇间距离——sRGB 欧氏距离会把
|
||||
/// 暗部差异放大、亮部差异压扁,分出来的簇不符合「看起来是一族颜色」。
|
||||
pub(crate) fn lab_from_color(color: Color) -> [f64; 3] {
|
||||
let xyz = xyz_from_color(color);
|
||||
let f = |component: f64, white: f64| lab_f(component / white);
|
||||
let fx = f(xyz[0], WHITE_POINT_D65[0]);
|
||||
let fy = f(xyz[1], WHITE_POINT_D65[1]);
|
||||
let fz = f(xyz[2], WHITE_POINT_D65[2]);
|
||||
[116.0 * fy - 16.0, 500.0 * (fx - fy), 200.0 * (fy - fz)]
|
||||
}
|
||||
|
||||
/// `L*` → 中性灰色值(`L*` 与彩度无关,纯灰)。
|
||||
pub(crate) fn color_from_lstar(lstar: f64) -> Color {
|
||||
let component = delinearized(y_from_lstar(lstar));
|
||||
|
||||
Reference in new issue
Block a user