字符串、hex 与命名色
有两个覆盖面不同的解析器。Hex(plt_from_hex、plt_to_hex)是 palette 自己的读写器:紧凑、
严格,不认识颜色名。CSS(plt_css_parse、plt_css_serialize)走 csscolorparser,能理解完整的
CSS Color Level 4 语法,包括 lab()、oklch() 与 color(display-p3 …)。
两个解析器产出的都是 sRGB 颜色,因为这两种格式编码的都是 sRGB。字符串永远不会直接解析成
oklch 值:先解析,想要别的 space 再用 plt_convert。
Hex
plt_from_hex(text)
签名:plt_from_hex(text VARCHAR) -> plt_color
解析 #rgb、#rgba、#rrggbb 或 #rrggbbaa;开头的 # 可以省略。短格式把每一位重复展开
(#f80 就是 #ff8800),4 位或 8 位的值带 alpha。不是 hex 颜色的文本返回 NULL 而不是报错
—— 所以它能和 WHERE、COALESCE 一起用:
SELECT plt_to_hex(plt_from_hex('#f80')) AS short,
plt_to_hex(plt_from_hex('#ff800080')) AS with_alpha,
plt_to_hex(plt_from_hex('ff8000')) AS without_hash,
plt_from_hex('orange') IS NULL AS unknown_is_null;
plt_to_hex(color)
签名:plt_to_hex(color plt_color) -> VARCHAR
先转成 sRGB,再把每个通道量化到 8 位并写成 #rrggbb;alpha 不恰好是 1 时改写成 #rrggbbaa。
超出色域的分量会被夹紧,所以结果永远是一个合法的 hex 字符串:
SELECT plt_to_hex(plt_srgb(1, 0.5, 0)) AS orange,
plt_to_hex(plt_color('srgb', 1, 0.5, 0, 0.5)) AS translucent,
plt_to_hex(plt_oklch(0.7, 0.1, 120)) AS from_oklch;
plt_to_hex6(color) 与 plt_to_hex8(color)
签名:plt_to_hex6(color plt_color) -> VARCHAR
签名:plt_to_hex8(color plt_color) -> VARCHAR
plt_to_hex 的定宽版本:plt_to_hex6 永远写六位并丢掉 alpha,plt_to_hex8 永远写八位并带上它。
下游要求固定宽度时用它们,而不是看颜色恰好是不是不透明再决定:
SELECT plt_to_hex6(plt_color('srgb', 1, 0, 0, 0.5)) AS six,
plt_to_hex8(plt_srgb(1, 0, 0)) AS eight;
CSS 语法
plt_css_parse(text)
签名:plt_css_parse(text VARCHAR) -> plt_color
把任意 CSS Color Level 4 颜色解析成带 alpha 的 sRGB 颜色。这涵盖命名色、所有 hex 形式、rgb()、
rgba()、hsl()、hsla()、hwb()、lab()、lch()、oklab()、oklch(),以及带常见颜色空间的
color(...)。分隔符可以是逗号或空格,alpha 可以是数字或百分比。
无法解析的文本返回 NULL:
SELECT plt_to_hex(plt_css_parse('hsl(120 100% 50% / 0.5)')) AS hsl,
plt_to_hex(plt_css_parse('rgb(255, 128, 0)')) AS rgb,
plt_to_hex(plt_css_parse('oklch(0.7 0.15 250)')) AS oklch,
plt_css_parse('not a color') IS NULL AS invalid_is_null;
plt_css_is_valid(text)
签名:plt_css_is_valid(text VARCHAR) -> BOOLEAN
plt_css_parse 会不会成功。可以在解析前用它校验一列,或者用它把无效的行留在报表里可见:
SELECT plt_css_is_valid('#ff0000') AS hex_ok,
plt_css_is_valid('rgb(300 0 0)') AS clampable,
plt_css_is_valid('rgb(nope)') AS broken;
plt_css_serialize(color, format)
签名:plt_css_serialize(color plt_color, format VARCHAR) -> VARCHAR
把颜色写成 CSS 文本,写之前先转成 sRGB。八种格式就是 csscolorparser 提供的八个函数:hex、rgb、
hsl、hwb、lab、lch、oklab、oklch。
SELECT plt_css_formats() AS formats;
SELECT plt_css_serialize(plt_srgb(1, 0.5, 0), 'hex') AS hex,
plt_css_serialize(plt_srgb(1, 0.5, 0), 'rgb') AS rgb,
plt_css_serialize(plt_srgb(1, 0.5, 0), 'oklch') AS oklch,
plt_css_serialize(plt_srgb(1, 0.5, 0), 'lab') AS lab;
走一趟 CSS 文本的完整往返仍留在 sRGB,并且保留 alpha:
SELECT plt_css_parse(plt_css_serialize(c, 'oklch')) AS reparsed,
plt_to_hex(plt_css_parse(plt_css_serialize(c, 'oklch'))) AS hex
FROM (SELECT plt_color('srgb', 0.2, 0.4, 0.6, 0.5) AS c);
未知的格式让整条语句失败:
SELECT plt_css_serialize(plt_srgb(1, 0, 0), 'hsv');
plt_css_name(color)
签名:plt_css_name(color plt_color) -> VARCHAR
sRGB 字节与该颜色完全一致的 CSS 关键字;没有关键字匹配时是 NULL。这是精确匹配查找,不是找最接近的 名字 —— 大多数颜色根本没有名字:
SELECT plt_css_name(plt_srgb(1, 0, 0)) AS red,
plt_css_name(plt_named('rebeccapurple')) AS purple,
plt_css_name(plt_srgb(0.2, 0.4, 0.6)) IS NULL AS unnamed;
plt_css_formats()
签名:plt_css_formats() -> VARCHAR[]
plt_css_serialize 接受的八个格式名。
更多输出格式
plt_to_percentage_rgb 与 plt_to_hsv_string 是 tinycolor 的另外两个写出器。它们都先转成 sRGB,
把通道百分比与色相四舍五入到整数、把 alpha 保留两位小数,并在 alpha 不恰好是 1 时换成带 alpha 的
写法 —— 所以文本足够稳定,可以直接用于展示与日志。
plt_to_percentage_rgb(color)
签名:plt_to_percentage_rgb(color plt_color) -> VARCHAR
rgb(100%, 50%, 0%);带透明度时是 rgba(…, 0.5)。
SELECT plt_to_percentage_rgb(plt_srgb(1, 0.5, 0)) AS opaque,
plt_to_percentage_rgb(plt_with_alpha(plt_srgb(1, 0.5, 0), 0.5)) AS translucent;
plt_to_hsv_string(color)
签名:plt_to_hsv_string(color plt_color) -> VARCHAR
hsv(0, 100%, 100%);带透明度时是 hsva(…)。CSS 本身没有 HSV 写法,这是 tinycolor 的拼法,文本
交给设计工具而不是浏览器时用得上。
SELECT plt_to_hsv_string(plt_srgb(1, 0, 0)) AS opaque,
plt_to_hsv_string(plt_with_alpha(plt_srgb(0, 0.5, 1), 0.25)) AS translucent;
命名色
plt_named(name)
签名:plt_named(name VARCHAR) -> plt_color
palette 的 148 个 SVG/CSS3 关键字颜色之一,作为不透明的 sRGB 颜色返回。匹配不区分大小写。未知的 名字返回 NULL:
SELECT plt_to_hex(plt_named('rebeccapurple')) AS purple,
plt_to_hex(plt_named('Gold')) AS gold,
plt_named('notacolor') IS NULL AS unknown_is_null;
plt_nearest_named(color)
签名:plt_nearest_named(color plt_color) -> VARCHAR
用 CIEDE2000 找出 148 个关键字颜色里最接近的那个 —— 与精确匹配的 plt_css_name 正好相反。它总会
返回一个名字,所以适合用来生成人可读的标签,或把一套色板吸附到命名色上。距离相同时按字母序取。
SELECT plt_nearest_named(plt_srgb(1, 0, 0)) AS red,
plt_nearest_named(plt_srgb(0.99, 0.01, 0.02)) AS almost_red,
plt_nearest_named(plt_oklch(0.7, 0.1, 150)) AS from_oklch,
plt_css_name(plt_srgb(0.99, 0.01, 0.02)) IS NULL AS no_exact_name;
plt_named_names()
签名:plt_named_names() -> VARCHAR[]
全部关键字名字,按字母顺序排列。用它来建一张参考表,不必把清单抄进 SQL:
SELECT list_count(plt_named_names()) AS count,
plt_named_names() AS names;
SELECT name, plt_to_hex(plt_named(name)) AS hex
FROM unnest(plt_named_names()) t(name)
WHERE name IN ('red', 'green', 'blue', 'rebeccapurple');
该用哪个函数?
| 输入或输出 | 函数 |
|---|---|
| 来自数据库列的 hex 字符串 | plt_from_hex |
| 来自样式表或 API 的 CSS 颜色 | plt_css_parse |
| 用于展示的短 hex 字符串 | plt_to_hex |
| 固定六位或固定八位的 hex 字符串 | plt_to_hex6 / plt_to_hex8 |
某个特定的 CSS 函数,例如 oklch(...) | plt_css_serialize |
百分比 rgb() 或 hsv() 文本 | plt_to_percentage_rgb / plt_to_hsv_string |
| 148 个关键字颜色之一 | plt_named / plt_named_names |
| 某个颜色的关键字名字,要求精确匹配 | plt_css_name |
| 最接近的关键字名字 | plt_nearest_named |
| 文本是不是合法的 CSS 颜色 | plt_css_is_valid |