js 颜色转换分析

一、十六进制转RGB

  function hexToRgba(hex) {// 移除 # 字符hex = hex.replace('#', '');// 处理简写形式如 #fffif (hex.length === 3) {hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];}// 转换为十进制const r = parseInt(hex.substring(0, 2), 16); // 截图前两位,然后16进制转为10进制const g = parseInt(hex.substring(2, 4), 16);const b = parseInt(hex.substring(4, 6), 16);return `rgb(${r}, ${g}, ${b})`;}
  • 使用十六进制表示颜色时,每两位代表一个颜色通道(#RRGGBB:RR=红,GG=绿,BB=蓝),范围00-FF(十进制0-255)。

二、RGB转十六进制

function rgbToHex(rgbStr) {// 提取 RGB 值const match = rgbStr.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)$/i);if (!match) {throw new Error('Invalid RGB/RGBA string format');}// 解析颜色分量const r = parseInt(match[1]);const g = parseInt(match[2]);const b = parseInt(match[3]);// 转换为十六进制const toHex = (num) => {const hex = Math.min(255, Math.max(0, num)).toString(16);return hex.length === 1 ? '0' + hex : hex;};return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
}
  • 使用正则表达式匹配rgb/rgba
    /^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)$/i // (?:,\s*([\d.]+))?:可选捕获透明度部分
    
  • 数值范围处理和十六进制转换
    const toHex = (num) => {// 1. 确保颜色值在 0-255 范围内// 2. 处理可能的非法输入值// 3. 转为十六进制const hex = Math.min(255, Math.max(0, num)).toString(16);return hex.length === 1 ? '0' + hex : hex;
    };
    

三、十六进制转HSL

(一)、什么是HSL

HSL(Hue, Saturation, Lightness)是一种基于人类感知的颜色表示方法,广泛应用于计算机图形学、网页设计和图像处理等领域。它比传统的 RGB(红绿蓝)模型更直观,便于调整颜色的色调、鲜艳度和明暗。

(二)、HSL中H、S、L分别代表什么

H:色相(Hue, H)

  • 定义:颜色的基本类型(如红、绿、蓝)。
  • 范围:0°–360°(环形色轮)。
    0° = 红色
    120° = 绿色
    240° = 蓝色
    360° = 回到红色
    在这里插入图片描述

色相和色度的区别

特性色相(Hue)色度(Chroma)
定义颜色的种类(红、绿、蓝等)颜色的纯度(鲜艳程度)
几何表示色轮上的角度(0°–360°)颜色点到灰度轴的距离
物理基础光的波长颜色成分的纯度(与灰度的偏离)
调整效果改变颜色类别(如红→蓝)改变颜色的鲜艳度(如鲜红→灰红)
感知独立性与明度、饱和度无关与明度相关(明度影响最大色度)

S:饱和度(Saturation, S)

  • 定义:颜色的鲜艳程度(从灰度到纯色)。
  • 范围:0%–100%
    0% = 灰色(完全去色)
    100% = 最鲜艳的颜色
    在这里插入图片描述

L:明度(Lightness, L)

  • 定义:颜色的明暗程度(从黑到白)。
  • 范围:0%–100%
    0% = 纯黑
    50% = 标准颜色
    100% = 纯白

(三)、HSL的圆柱模型

HSL还有双六棱锥模型,这里主要说圆柱模型
HSL(色相、饱和度、明度)的圆柱模型是一种直观的几何表示方式,将颜色的三个属性映射到三维空间中。

基本结构

  • 色相(Hue, H)
    • 几何位置:围绕圆柱的圆周方向(0°–360°)。
    • 物理意义:颜色在色轮上的角度,决定颜色种类(如红、绿、蓝)。
  • 饱和度(Saturation, S)
    • 几何位置:从圆柱中心到边缘的径向距离(0%–100%)。
    • 物理意义:颜色的鲜艳程度,中心为灰色,边缘为纯色。
  • 明度(Lightness, L)
    • 几何位置:沿圆柱的垂直轴高度(0%–100%)。
    • 物理意义:颜色的明暗程度,底部为纯黑,顶部为纯白,中间为纯色。

关键几何特征

  • 灰度轴(中心轴)
    • 位置:圆柱的中心垂直线(S=0%)。
  • 颜色特性:
    • 所有点均为灰色,色相(H)无意义。
    • 明度(L)决定灰度深浅:
      • L=0% → 纯黑
      • L=100% → 纯白
      • L=50% → 中性灰
  • 中间平面(L=50%)
    • 位置:圆柱的中间水平截面(高度为 50%)。
    • 颜色特性:
      • 所有颜色处于最鲜艳状态(饱和度 S=100%)。
      • 色相(H)在此平面上形成完整的 色相环(红→黄→绿→青→蓝→品红→红)。
  • 顶部与底部
    • 顶部(L=100%):
      • 所有颜色均为纯白(无论色相和饱和度如何)。
    • 底部(L=0%):
      • 所有颜色均为纯黑(无论色相和饱和度如何)。
        在这里插入图片描述

(四)、什么是RGB

RGB(Red, Green, Blue)是一种基于光学的颜色表示方法,通过红、绿、蓝三原色的不同比例混合来定义颜色。它是数字设备(如显示器、摄像头)最基础的颜色模型。

(五)、RGB中R、G、B分别代表什么

R:(Red,红色)

  • 定义:红色光的强度,是光的三原色之一。
  • 作用:红色分量主导颜色中的红色成分。
  • 示例:纯红色的 RGB 值为 (255, 0, 0)。

G(Green,绿色)

  • 定义:绿色光的强度,是光的三原色之一。
  • 作用:绿色分量主导颜色中的绿色成分。
  • 示例:纯绿色的 RGB 值为 (0, 255, 0)。

B(Blue,蓝色)

  • 定义:蓝色光的强度,是光的三原色之一。
  • 作用:蓝色分量主导颜色中的蓝色成分。
  • 示例:纯蓝色的 RGB 值为 (0, 0, 255)。

(六)RGB的立方体模型

RGB 立方体模型是描述 RGB 颜色空间最直观的几何表示方式。它通过三维坐标系将红(R)、绿(G)、蓝(B)三个颜色分量的组合关系可视化,帮助理解颜色的混合规律和分布特性。

基本结构
RGB 立方体是一个三维直角坐标系:

  • 三个坐标轴:

    • R 轴(红色):从左(0)到右(255 或 1.0)
    • G 轴(绿色):从前(0)到后(255 或 1.0)
    • B 轴(蓝色):从下(0)到上(255 或 1.0)
  • 顶点:立方体的 8 个顶点对应极端颜色值,例如:

    • (0,0,0) → 纯黑色
    • (255,255,255) → 纯白色
    • (255,0,0) → 纯红色
    • (0,255,0) → 纯绿色
    • (0,0,255) → 纯蓝色

关键几何特征

  • 灰度对角线

    • 定义:从黑色 (0,0,0) 到白色 (255,255,255) 的对角线。
    • 颜色特性:线上所有点满足 R=G=B,即 灰度色。
      • 例如:(128,128,128) → 中灰色。
  • 纯色顶点

    • 6 个非黑白顶点:对应红、绿、蓝及其两两混合的纯色:

      顶点坐标颜色名称
      (255,0,0)纯红
      (0,255,0)纯绿
      (0,0,255)纯蓝
      (255,255,0)黄(红+绿)
      (255,0,255)品红(红+蓝)
      (0,255,255)青(绿+蓝)
  • 颜色平面

    • 单通道为 0 的平面:
      • R=0 平面 → 蓝绿混合色(如青、蓝、绿)。
      • G=0 平面 → 红蓝混合色(如品红、红、蓝)。
      • B=0 平面 → 红绿混合色(如黄、红、绿)。
        在这里插入图片描述
        归一化如下图
        归一化

(七)、十六进制转HSL

function hexToHsl(hex) {// 1. 去除#号并解析R,G,Blet r = parseInt(hex.slice(1, 3), 16) / 255;let g = parseInt(hex.slice(3, 5), 16) / 255;let b = parseInt(hex.slice(5, 7), 16) / 255;// 2. 计算最大值、最小值和色度(Chroma)let max = Math.max(r, g, b);let min = Math.min(r, g, b);let chroma = max - min;// 3. 计算明度(Lightness)let l = (max + min) / 2;// 4. 计算色相(Hue)和饱和度(Saturation)let h = 0, s = 0;if (chroma !== 0) {// 饱和度计算s = chroma / (1 - Math.abs(2 * l - 1));// 色相计算switch (max) {case r: h = ((g - b) / chroma) % 6; break;case g: h = (b - r) / chroma + 2; break;case b: h = (r - g) / chroma + 4; break;}h = h * 60;if (h < 0) h += 360; // 确保色相在0-360度之间}// 5. 返回HSL对象(色相四舍五入,饱和度和明度转为百分比)return {h: Math.round(h),s: Math.round(s * 100),l: Math.round(l * 100)};
}

使用max - min计算色度的几何意义

  let max = Math.max(r, g, b);let min = Math.min(r, g, b);let chroma = max - min;

色度表示颜色点 P(R,G,B) 到灰度轴的垂直距离,即颜色偏离灰色的程度。:

  • 当 C=0:颜色位于灰度轴上(完全无色彩)。
  • 当 C=1:颜色为纯色(如纯红、纯绿、纯蓝)。

总结:当某个分量(如R)远大于其他分量时,max - min 的值越大,颜色越接近纯色(如纯红)。

数学推导
颜色点到灰度轴的距离(三维空间中的垂直距离)为:
在这里插入图片描述
而 C=max−min 是该距离的简化近似,避免了复杂的平方根运算, 但是忽略了部分分量差异。会导致色度越大,颜色越偏离灰色。

根号3的来源,使用到了空间向量相关知识。公式如下
在这里插入图片描述

使用(max - min)/2计算色度的几何意义

 let l = (max + min) / 2;

明度表示颜色点在灰度轴上的投影位置。具体来说,颜色点 P(R,G,B)沿垂直于灰度轴的方向投影到灰度轴上,得到的投影点坐标为 (L,L,L)其中 L 是明度值。

  • 示例:
    • 纯红色 (1,0,0):
      L=(1+0)/2=0.5,投影点为 (0.5,0.5,0.5),即中等灰色。
    • 浅蓝色 (0.2,0.8,0.8):
      L= (0.8+0.2)/2 =0.5,投影点仍为 (0.5,0.5,0.5)。

数学推导
在这里插入图片描述
简化公式为
在这里插入图片描述
和色度一样,使用(max+min)/2 计算明度只需比较和一次加法,适合实时计算(如早期图形处理),同时还可以兼容HSL中饱和度的计算。

色度和明度对比

属性几何意义物理意义计算依赖
色度颜色到灰度轴的垂直距离颜色的纯度(偏离灰色的程度)max 和 min 的差值
明度颜色在灰度轴上的投影位置颜色的整体亮度(等效灰色亮度)max 和 min 的平均值

使用chroma / (1 - Math.abs(2 * l - 1))计算饱和度的几何意义

 s = chroma / (1 - Math.abs(2 * l - 1));

在这里插入图片描述
这相当于:

  • 在RGB立方体中,从当前颜色点向灰度轴作垂线
  • 计算该点到灰度轴的距离(实际色度)
  • 计算该明度平面上可能的最大色度
  • 求两者的比值

可视化理解:

  • 想象RGB立方体:
    • 在L=0.5的中间平面,最大色度大(分母大),容易得到高饱和度
    • 在L接近0或1的平面,最大色度小(分母小),饱和度被压缩
  • 这种设计确保了:
    • 纯色总是在L=0.5时S=100%
    • 接近黑白时饱和度自动降低

计算色相的几何意义

 switch (max) {case r: h = ((g - b) / chroma) % 6; break;case g: h = (b - r) / chroma + 2; break;case b: h = (r - g) / chroma + 4; break;}

为什么计算色相时需要分三段进行判断?

色相表示颜色在色轮上的位置(0°~360°),不同主色对应不同区间:

  • 红色(R):0°(或360°)
  • 绿色(G):120°
  • 蓝色(B):240°

色相的计算需要根据最大值通道确定基础角度,再通过其他通道的相对差异调整偏移量。

当最大值是R时

case r: h = ((g - b) / chroma) % 6; break; // 这里 % 6 是为了防止差值出超过0-6之间的数值。如果差值超过0-6的范围那么%6可以回到范围
  • 基础角度:0°(红色)
  • 偏移方向:
    • 若G > B → 向黄色(60°方向)偏移。
    • 若B > G → 向品红色(300°方向)偏移。
  • 计算公式:
    • 在这里插入图片描述
    • 几何意义:计算G和B的相对比例,归一化到[-1,1],再映射到0-6的临时值。

当最大值是G时

case g: h = (b - r) / chroma + 2; break;
  • 基础角度:120°(绿色)
  • 偏移方向:
    • 若B > R → 向青色(180°方向)偏移。
    • 若R > B → 向黄色(60°方向)偏移。
  • 计算公式:
    • 在这里插入图片描述
    • 几何意义:+2 将结果偏移到绿色区域(120°)。

当最大值是B时

  • 基础角度:240°(蓝色)
  • 偏移方向:
    • 若R > G → 向品红色(300°方向)偏移。
    • 若G > R → 向青色(180°方向)偏移。
  • 计算公式:
    • 在这里插入图片描述
    • 几何意义:+4 将结果偏移到蓝色区域(240°)

为什么计算色相时当最大值为r时公式里面是g-b为不是b-g?

色轮以 逆时针方向 定义颜色过渡:
红色(0°) → 黄色(60°) → 绿色(120°) → 青色(180°) → 蓝色(240°) → 品红(300°) → 红色(360°)。
当 R为最大值 时:
若 G > B,颜色偏向 黄色(60°方向),此时 (G - B) 为正,色相应 增加。
若 B > G,颜色偏向 品红色(300°方向),此时 (G - B) 为负,色相应 减少。
使用 (G - B) 而非 (B - G) 能直接反映这一方向性。(同样道理适用于最大值为g或b)

四、HSL转十六进制

function hslToHex(h, s, l) {// 规范化输入值h = h % 360;s = Math.max(0, Math.min(100, s)) / 100;l = Math.max(0, Math.min(100, l)) / 100;// 处理灰度色if (s === 0) {const gray = Math.round(l * 255);return `#${gray.toString(16).padStart(2, '0').repeat(3)}`;}// 计算色度、中间值和明度偏移const c = (1 - Math.abs(2 * l - 1)) * s;const x = c * (1 - Math.abs((h / 60) % 2 - 1));const m = l - c / 2;// 根据色相确定RGB初始值let r, g, b;if (h >= 0 && h < 60) {[r, g, b] = [c, x, 0];} else if (h < 120) {[r, g, b] = [x, c, 0];} else if (h < 180) {[r, g, b] = [0, c, x];} else if (h < 240) {[r, g, b] = [0, x, c];} else if (h < 300) {[r, g, b] = [x, 0, c];} else {[r, g, b] = [c, 0, x];}// 转换为十六进制const toHex = (value) => {const hex = Math.round((value + m) * 255).toString(16);return hex.padStart(2, '0');};return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
}

获取色度

const c = (1 - Math.abs(2 * l - 1)) * s;

是上面十六进制转为HSL中饱和度s=chroma / (1 - Math.abs(2 * l - 1)); 再乘以(1 - Math.abs(2 * l - 1))得到色度

计算中间颜色分量的值

const x = c * (1 - Math.abs((h / 60) % 2 - 1));

分步理解公式

  • 色相分段:h / 60
    • 将色相 H 按每 60° 分段,对应色轮上的 6 个主色区间(红、黄、绿、青、蓝、品红)。
  • 模2操作:(h / 60) % 2
    • 将分段后的色相值映射到 0~2 的范围内,用于在每段内生成对称的插值系数。
  • 归一化到 -1~1:(h / 60) % 2 - 1
    • 通过减去 1,将范围调整为 -1~1,便于后续的绝对值处理。
  • 生成插值系数:1 - Math.abs(…)
    • 取绝对值后,值域为 0~1,再用 1 减去它,得到 0→1→0 的三角形波形,用于颜色分量的平滑过渡。
  • 乘以色度 C:c * …
    • 最终结果表示中间颜色分量的强度,范围在 0~C 之间。

为什么乘以色度?

  • 色度 C 表示颜色的纯度,插值系数与 C 相乘,确保颜色强度与饱和度一致。
    • 高饱和度( 最大,颜色鲜艳)。
    • 低饱和度(颜色为灰色)。

中间颜色分量的几何意义:

色相分段与颜色过渡

  • 每 60° 对应一个颜色区间:
    • 0°~60°:红色 → 黄色
    • 60°~120°:黄色 → 绿色
    • 120°~180°:绿色 → 青色
    • 180°~240°:青色 → 蓝色
    • 240°~300°:蓝色 → 品红
    • 300°~360°:品红 → 红色
  • 中间分量的作用:
    在每个区间内,一个颜色分量保持最大值(由主色决定),另一个分量从 0 增长到最大值(或从最大值减少到 0),第三个分量保持为 0。
    • 例如:在 0°~60°(红→黄)区间:
      • 红色分量 R=C(最大)
      • 绿色分量 G=C×插值系数(从 0 到 C)
      • 蓝色分量 B=0。

插值系数的波形

  • 波形形状:
    插值系数通过 1 - Math.abs((h / 60) % 2 - 1) 生成 三角形波形,在每 60° 区间内从 0 线性增长到 1,再线性减少到 0。
    • 示例:当 H=30°(0°~60°区间):
      插值系数=1−∣(30/60)%2−1∣=1−∣0.5−1∣=0.5
      此时绿色分量 G=C×0.5,颜色为橙色。

计算明度偏移量

const m = l - c / 2;

计算明度偏移量的几何意义

平移中间分量:将中间分量(如 r′,g′,b ′)从相对范围 0∼C 平移到实际范围 L− C/2∼L+ C/2,保颜色在灰度轴上的投影亮度为 L。

计算明度偏移量的数据推导

HSL明度的定义:

  • 在HSL模型中,明度 L 是RGB分量的最大值(max)和最小值(min)的算术平均值
    • 在这里插入图片描述

色度 C 的定义:

  • 色度(Chroma) 表示颜色的纯度,即RGB分量的最大值与最小值之差:
    • 在这里插入图片描述

联立方程求解

  • 通过联立上述两个方程,可以推导出 min 和 max:
    • 在这里插入图片描述
    • max:颜色分量的最大值(例如纯红色时 R=1)
    • min:颜色分量的最小值(例如纯红色时 G=B=0)

明度偏移量 m 的引入
在HSL转RGB时,中间分量(如 r ′,g ′,b ′)是基于色相和饱和度计算出的相对值(范围0~C)。为了将这些中间分量映射到实际RGB值(范围0~1),需要加上一个偏移量 m,使得:
在这里插入图片描述
将 m=L− C/2代入,可保证:
在这里插入图片描述
从而满足HSL明度的定义。

根据色相区间确定 RGB 初始值

  let r, g, b;if (h >= 0 && h < 60) {[r, g, b] = [c, x, 0];} else if (h < 120) {[r, g, b] = [x, c, 0];} else if (h < 180) {[r, g, b] = [0, c, x];} else if (h < 240) {[r, g, b] = [0, x, c];} else if (h < 300) {[r, g, b] = [x, 0, c];} else {[r, g, b] = [c, 0, x];}
色相区间临时 RGB 值
0°-60°(C, X, 0)
60°-120°(X, C, 0)
120°-180°(0, C, X)
180°-240°(0, X, C)
240°-300°(X, 0, C)
300°-360°(C, 0, X)

调整 RGB 值并转换为十六进制

 const toHex = (value) => {const hex = Math.round((value + m) * 255).toString(16);return hex.padStart(2, '0');};
  • 将 RGB 值加上明度偏移量 m,并限制在 0-1 范围内。
  • 转换为 0-255 的整数,再转为两位十六进制。

五、十六进制转HSV

虽然HSV和HSL看着名字相似,但它们的定义和计算逻辑有本质区别。尽管在十六进制→HSL 和 十六进制→HSV(HSV → 十六进制 和 HSL → 十六进制) 的转换过程中,计算中间值(如色度 c 和辅助变量 x)或者色度等公式看起来相似,但它们的物理含义不同,最终转换结果也不同

(一)、什么是HSV

HSV(Hue, Saturation, Value)是一种基于人类颜色感知的模型,用于直观描述颜色的 色调、鲜艳度 和 亮度。它在图像处理、设计工具和数据可视化中广泛应用。

(二)、HSV中H、S、V分别代表什么

H:色相(Hue, H)

  • 定义:颜色的基本类型(如红、绿、蓝)。
  • 范围:0°–360°(环形色轮)。
    0° = 红色
    120° = 绿色
    240° = 蓝色
    360° = 回到红色

S:饱和度(Saturation, S)

  • 定义:颜色的鲜艳程度(从灰度到纯色)。
  • 范围:0%–100%
    0% = 灰色(完全去色)
    100% = 最鲜艳的颜色

V:明度(Value,V)

  • 定义:颜色的亮度。明度越高,颜色越亮;越低则越暗。
  • 范围:0%(纯黑)–100%(最亮,颜色保持纯色)。
    V=100%:亮红色(RGB的红色通道全开)。
    V=50%:暗红色(亮度减半)。
    V=0%:纯黑色(所有颜色通道关闭)。

(三)、HSV和HSL的区别

模型定义公式几何意义示例(纯红色)适用场景核心优势
HSVV=max(R,G,B)颜色的最大亮度(最亮时颜色保持纯色)V=100% → 纯红(RGB: 255,0,0)图像处理、快速调色直观调整颜色亮度
HSLL= (max+min)/2颜色的平均亮度(中等亮度时颜色最纯)L=50% → 纯红(RGB: 255,0,0)设计、数据可视化自然保持颜色鲜艳度

(四)、HSV的圆柱模型

HSV还有单六棱锥模型,这里主要说圆柱模型

基本结构

HSV 圆柱模型由三个正交维度构成,分别对应色相(H)、饱和度(S)、明度(V):

  • 色相(Hue)

    • 几何方向:沿圆柱的 圆周分布,角度范围为 0°–360°。
    • 物理意义:决定颜色的基本类型(如红、绿、蓝等)。
  • 饱和度(Saturation)

    • 几何方向:沿圆柱的 径向分布,范围 0%(中心)–100%(边缘)。
    • 物理意义:表示颜色纯度(鲜艳程度)。
  • 明度(Value)

    • 几何方向:沿圆柱的 垂直轴分布,范围 0%(底部)–100%(顶部)。
    • 物理意义:控制颜色亮度(明暗程度)。

关键几何特征

  • 色相环的连续性
    • 圆周闭合性:色相角度 0° 与 360° 重合,颜色从红→黄→绿→青→蓝→品红→红无缝过渡。
    • 几何意义:圆柱的圆周方向形成闭环,确保颜色过渡无间断。
  • 饱和度与径向距离
    • 中心轴为灰度轴:当 S=0% 时,无论 H 和 V 如何,颜色均为不同明度的灰色(如深灰、浅灰)。
    • 边缘为纯色:当 S=100% 时,颜色达到最大纯度,对应 RGB 的纯色(如红、绿、蓝)。
  • 底部为纯黑(V=0%):所有颜色在 V=0% 时均变为黑色,与 H 和 S 无关。
    • 顶部为最亮纯色(V=100%):颜色保持最大亮度,但可能因 S 不同呈现不同鲜艳度。
      • 示例:
        • V=100%、S=100% → 纯红色(RGB: 255,0,0)。
        • V=100%、S=50% → 浅红色(RGB: 255,128,128)。
  • 颜色过渡规律
    • 垂直方向(调整 V):
      • 颜色亮度线性变化,但饱和度不变。
      • 示例:V 从 50%→100%,颜色从暗红→亮红,但始终为红色(H 固定)。
    • 径向方向(调整 S):
      • 颜色从中心灰色逐渐变为边缘纯色。
      • 示例:S 从 0%→100%,颜色从灰→浅红→纯红。
    • 圆周方向(调整 H):
      • 颜色种类周期性变化,色轮角度对应不同颜色类型。
      • 示例:H 从 0°→60°,颜色从红→橙→黄。

在这里插入图片描述

(五)、十六进制转HSV

function hexToHsv(hex) {// 1. 移除#号并解析R, G, B分量(0~255)hex = hex.replace(/^#/, '');let r, g, b;if (hex.length === 3) {// 处理简写格式(如 #RGB → #RRGGBB)r = parseInt(hex[0] + hex[0], 16);g = parseInt(hex[1] + hex[1], 16);b = parseInt(hex[2] + hex[2], 16);} else {r = parseInt(hex.substring(0, 2), 16);g = parseInt(hex.substring(2, 4), 16);b = parseInt(hex.substring(4, 6), 16);}// 2. 归一化到0~1范围r /= 255, g /= 255, b /= 255;// 3. 计算最大值、最小值和色度(Chroma)const max = Math.max(r, g, b);const min = Math.min(r, g, b);const chroma = max - min;// 4. 计算明度(Value)const v = max;// 5. 计算饱和度(Saturation)let s = max === 0 ? 0 : chroma / max;// 6. 计算色相(Hue)let h = 0;if (chroma !== 0) {switch (max) {case r:h = ((g - b) / chroma) % 6;break;case g:h = (b - r) / chroma + 2;break;case b:h = (r - g) / chroma + 4;break;}h = (h * 60 + 360) % 360; // 确保角度在0~360之间}// 7. 转换为百分比并四舍五入return {h: Math.round(h),s: Math.round(s * 100),v: Math.round(v * 100)};
}

计算色度

  const chroma = max - min;

原理和HSL一样,不再赘诉

计算明度

   const v = max;

根据HSL模型定义,明度直接取最大值

计算饱和度

  let s = max === 0 ? 0 : chroma / max;

为什么在计算饱和度时HSV和HSL两个模型公式不一样?

这源于两者对颜色亮度的定义差异以及几何模型的根本区别

HSV/HSL中对S公式理解

  • HSV 的饱和度公式
    • 在这里插入图片描述
    • 物理意义:
      • 饱和度是 色度(Chroma)占当前明度(V)的比例。
      • 明度 V 是 RGB 的最大值,因此饱和度表示颜色纯度相对于最大亮度的占比。
        • 纯红色(RGB(255,0,0)):V=1,Chroma=1→S=100%。
        • 浅红色(RGB(255,128,128)):V=1,Chroma=0.5→S=50%。
  • HSL 的饱和度公式
    • 在这里插入图片描述
    • 物理意义:
      • 饱和度是 色度占当前亮度下可能的最大色度的比例。
      • 分母 1−∣2L−1∣ 表示当前亮度 L 下允许的最大色度。
        • 当 L=0.5(中等亮度)时,分母为 1,饱和度 S=Chroma
        • 当 L→0 或 L→1(接近黑/白)时,分母趋近 0,饱和度被压缩。

计算色相

 if (chroma !== 0) {switch (max) {case r:h = ((g - b) / chroma) % 6;break;case g:h = (b - r) / chroma + 2;break;case b:h = (r - g) / chroma + 4;break;}h = (h * 60 + 360) % 360; // 确保角度在0~360之间}

原理和HSL一样,不再赘诉

六、HSV转十六进制

function hsvToHex(h, s, v) {// 1. 规范化输入值h = ((h % 360) + 360) % 360; // 确保色相在0~360之间s = Math.max(0, Math.min(100, s)) / 100; // 饱和度转为0~1v = Math.max(0, Math.min(100, v)) / 100; // 明度转为0~1// 2. 处理饱和度为0的情况(灰度色)if (s === 0) {const gray = Math.round(v * 255);return `#${gray.toString(16).padStart(2, '0').repeat(3)}`;}// 3. 计算色度、中间值和明度偏移const c = v * s;const x = c * (1 - Math.abs(((h / 60) % 2) - 1));const m = v - c;// 4. 根据色相区间确定RGB初始值let r, g, b;if (h < 60) {[r, g, b] = [c, x, 0];} else if (h < 120) {[r, g, b] = [x, c, 0];} else if (h < 180) {[r, g, b] = [0, c, x];} else if (h < 240) {[r, g, b] = [0, x, c];} else if (h < 300) {[r, g, b] = [x, 0, c];} else {[r, g, b] = [c, 0, x];}// 5. 调整RGB值并转换为十六进制const toHex = (value) => {const hex = Math.round((value + m) * 255).toString(16);return hex.padStart(2, '0');};return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
}

计算色度

  const c = v * s;

在HSV中为什么计算色度公式是v * s?

色度 c 是颜色在 RGB 空间中的最大分量与最小分量的差值,表示颜色的“纯度”或“鲜艳程度”。在 HSV 模型中:

  • 当 S = 1 时,颜色为纯色,色度 c 达到最大值(c = V)。
  • 当 S = 0 时,颜色为灰色,色度 c = 0。
  • 因此,色度 c 是饱和度和明度的乘积:
    c = V * S

计算中间值

const x = c * (1 - Math.abs(((h / 60) % 2) - 1));

这里和上面HSL转十六进制时求x理解一致(这是因为在十六进制转为HSL和十六进制转为HSV转换中对色相的处理方式完全相同)

明度偏移

const m = v - c;

为什么HSL或HSV转为十六进制 m 的计算方式不同?

  • HSV

    • 在 RGB 中,max(R, G, B) = v(由 v 决定)
    • min(R, G, B) = v - c(因为 c = max - min)。
    • 所以 m 的作用是 确保 min(R, G, B) 正确,使得:
      • 当 s = 1 时,c = v,m = 0(纯色,最小值是 0)。
      • 当 s = 0 时,c = 0,m = v(灰度,所有分量等于 v)。
  • HSL

    • 在 RGB 中,(max + min) / 2 = l(由 l 决定)。
    • c = max - min(色度)。
    • 所以 min = l - c / 2(因为 max = min + c,代入 (max + min)/2 = l 可得)。
    • m 的作用是 确保 min(R, G, B) 正确,使得:
      • 当 s = 1 且 l = 0.5 时,c = 1,m = 0.5 - 0.5 = 0(纯色)。
      • 当 s = 0 时,c = 0,m = l(灰度,所有分量等于 l)。

参考文章

  1. 由RGB到HSV的转换详解
  2. 13 个 颜色转换 的高级方法🌈
  3. 3D空间点到直线的距离
  4. 漫步色彩空间:解锁HSV(HSB)的奥秘

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/78747.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

智能资源管理机制-重传机制

一、发送端资源管理的核心机制 1. 滑动窗口&#xff08;Sliding Window&#xff09; 这是TCP协议的核心优化设计&#xff1a; 窗口动态滑动&#xff1a;发送端不需要保留所有已发送的分组&#xff0c;只需维护一个"发送窗口"窗口大小&#xff1a;由接收方通告的接…

基于SSM+Layui毕业设计选题系统源码

项目介绍 基于SSM+Layui毕业设计选题系统源码,可以作为课程设计项目参考,该系统分为三个角色: 管理员:用户管理(对学生和老师的信息进行维护),统计分析(对老师课题情况以及学生选题情况信息进行维护),修改密码 老师:个人信息维护,毕业设计题目管理,报名学生管理…

通过uri获取文件路径手机适配

青铜版本 return contentResolver.query(this, arrayOf(MediaStore.MediaColumns.DATA), null, null).let {if (it?.moveToFirst() true) {val columnIndex it.getColumnIndex(MediaStore.MediaColumns.DATA)val path it.getString(columnIndex)it.close()return path}&quo…

vue模拟扑克效果

vue模拟扑克效果 效果图&#xff1a; step1:C:\Users\wangrusheng\PycharmProjects\untitled18\src\views\Home.vue <template><div class"poker-container"><!-- 使用复合数据对象实现双行显示 --><divv-for"(card, index) in POKER_…

基础数学:图论与信息论

微积分与概率论由此进&#xff1a;基础数学&#xff1a;微积分和概率与统计-CSDN博客 线代与优化理论由此进&#xff1a;基础数学&#xff1a;线性代数与优化理论-CSDN博客 数值分析与离散数学由此进&#xff1a;基础数学&#xff1a;数值分析与离散数学-CSDN博客 四、图论与…

构建智能期货交易策略分析应用:MCP与AI的无缝集成

引言 随着金融科技的快速发展&#xff0c;数据驱动的交易决策已成为期货交易领域的重要趋势。本文将深入探讨一个结合了Model Content Protocol (MCP)和AI技术的期货交易策略分析应用——Futures MCP。该应用不仅提供了丰富的技术分析工具&#xff0c;还通过MCP协议与大型语言…

0x02.Redis 集群的实现原理是什么?

回答重点 Redis 集群&#xff08;Redis cluster&#xff09;是通过多个 Redis 实例组成的&#xff0c;每个主节点实例负责存储部分的数据&#xff0c;并且可以有一个或多个从节点作为备份。 具体是采用哈希槽&#xff08;Hash Slot&#xff09;机制来分配数据&#xff0c;将整…

基本的DOS命令

一.打开CMD方式&#xff1a; winR 输入cmd 开始系统命令提示符 在任意文件夹下&#xff0c;shift&#xff0b;鼠标右击&#xff0c;在此处打开命令 资源管理器的地址栏前面输入cmd 以管理员身份打开cmd&#xff1a;选择以管理员方式运行 二.常用的Dos命令 #盘符切换 盘符…

深度剖析:架构评估的常用方法与应用

架构评估是确保系统架构满足需求、性能和质量等方面要求的重要环节&#xff0c;以下是一些常见的架构评估方法的详细介绍&#xff1a; 一、基于调查问卷或检查表的评估方法 1.方法概述&#xff1a;该方法通过设计一系列针对性的问题或检查项&#xff0c;形成问卷或检查表&…

代码随想录算法训练营第十六天

LeetCode题目: 530. 二叉搜索树的最小绝对差501. 二叉搜索树中的众数236. 二叉树的最近公共祖先3272. 统计好整数的数目(每日一题) 其他: 今日总结 往期打卡 530. 二叉搜索树的最小绝对差 跳转: 530. 二叉搜索树的最小绝对差 学习: 代码随想录公开讲解 问题: 给你一个二叉搜…

基于双闭环PID控制器的永磁同步电机控制系统匝间故障Simulink仿真

欢迎微♥关注“电击小子程高兴的MATLAB小屋”获取巨额优惠 1.模型简介 本仿真模型基于MATLAB/Simulink&#xff08;版本MATLAB 2013Rb&#xff09;软件。建议采用matlab2013 Rb及以上版本打开。&#xff08;若需要其他版本可联系代为转换&#xff0c;高于该版本的matlab均可正…

02-libVLC的视频播放器:播放音视频文件以及网络流

libvlc_new(0, nullptr)功能:创建并初始化libVLC的核心实例,是使用所有libVLC功能的前提。 参数:第一个参数:参数数量(通常设为0)第二个参数:参数列表(通常为nullptr,表示使用默认配置)返回值:成功返回libvlc_instance_t*指针,失败返回nullptr。注意事项:可通过参…

2025蓝桥杯省赛C++B组解题思路

由于题面还没出来&#xff0c;现在先口胡一下思路 填空题直接打表找规律或者乱搞一下就能出&#xff0c;从大题开始说。 1&#xff0c;题意&#xff1a; 给你一个数组&#xff0c;这个数组里有几个数可以被一个连续递增的数字区间求和得出 思路&#xff1a;诈骗题&#xff0c;显…

防止邮件伪造的策略 SPF 介绍

SPF是Sender Policy Framework的缩写&#xff0c;即发件人策略框架&#xff0c;是一种用于防止电子邮件伪造的技术&#xff0c;用来验证发件人邮箱域名的真实性。以下是关于它的详细说明&#xff1a; 1. 定义与作用 SPF是一种电子邮件验证系统&#xff0c;它通过在域名的DNS记…

JavaScript Symbol与BigInt

目录 Symbol类型 一、Symbol 的核心特性 1. 唯一性 2. 不可变性 3. 不可枚举性 二、创建 Symbol 1. 基础创建 2. 全局 Symbol 注册表 三、Symbol 作为对象属性 1. 定义 Symbol 属性 2. 遍历 Symbol 属性 四、内置 Symbol 值 五、实际应用场景 1. 避免属性名冲突 …

AI Agent工程师认证-学习笔记(3)——【多Agent】MetaGPT

学习链接:【多Agent】MetaGPT学习教程 源代码链接(觉得很好,star一下):GitHub - 基于MetaGPT的多智能体入门与开发教程 MetaGPT链接:GitHub - MetaGPT 前期准备 1、获取MetaGPT (1)使用pip获取MetaGPT pip install metagpt==0.6.6#或者在国内加速安装镜像 #pip in…

【leetcode hot 100 416】分割等和子集

解法一&#xff1a;&#xff08;动态规划&#xff09;①定义&#xff1a;dp[i]表示是否可以在nums找到元素之和为i&#xff0c;dp[sum/21] ②初始状态&#xff1a;dp[0]true;dp[i]false ③状态转移方程&#xff1a;dp[i] dp[i] || dp[i - num]; class Solution {public boole…

高中数学联赛模拟试题精选第2套几何题(改编)

在 △ A B C \triangle ABC △ABC 中, 点 M M M 是边 A C AC AC 的中点. 在线段 A M AM AM, C M CM CM 上分别取点 P P P, Q Q Q, 使得 P Q A C / 2 PQAC/2 PQAC/2. 设 △ A B Q \triangle ABQ △ABQ 的外接圆与边 B C BC BC 相交于点 X X X, △ B C P \triangle …

UWB双通道隧道人员定位方案

技术基础&#xff1a;UWB&#xff08;超宽带技术&#xff09; 定义&#xff1a;UWB&#xff08;Ultra-Wideband&#xff09;是一种通过纳秒级窄脉冲传输数据的无线通信技术&#xff0c;占用500MHz以上的超宽频段。 核心优势&#xff1a; 高精度定位&#xff1a;时间分辨率极高&…

Linux 入门八:Linux 多进程

一、概述 1.1 什么是进程&#xff1f; 在 Linux 系统中&#xff0c;进程是程序的一次动态执行过程。程序是静态的可执行文件&#xff0c;而进程是程序运行时的实例&#xff0c;系统会为其分配内存、CPU 时间片等资源。例如&#xff0c;输入 ls 命令时&#xff0c;系统创建进程…