Python colorsys 怎样在 RGB 与 HLS 之间转换
来源:17golang原创
时间:2026-10-30 19:42:56 482浏览 收藏
如果手里拿的是常见的 (R, G, B) 三通道整数,Python 标准库 colorsys 的正确用法是:先把每个通道除以 255 归一化,再调用 rgb_to_hls;需要显示或保存时,使用 hls_to_rgb 转回 0 到 1 的 RGB,最后再裁剪、四舍五入到 0 到 255。
最容易出错的地方有两个:colorsys接受的是 0 到 1 的浮点数,HLS 元组顺序是(h, l, s),不是 HSV 的(h, s, v)。
官方文档:https://docs.python.org/3/library/colorsys.html
先分清 colorsys 的数值范围
colorsys 同时提供 RGB、YIQ、HLS 和 HSV 之间的双向转换。对 RGB、HLS、HSV 来说,坐标都使用 0 到 1 的浮点数;因此网页颜色常见的 255 不能直接作为参数传入。
HLS 的三个位置分别是色相 h、亮度 l、饱和度 s。其中色相也是 0 到 1 的归一化坐标,如果业务界面需要角度,可以把它乘以 360;亮度和饱和度则继续保持 0 到 1。

最小配方:RGB 转 HLS
先写一个只负责换算的函数,把外部常见的 8 位 RGB 和 colorsys 的内部坐标隔离开。这样后面无论颜色来自表单、接口还是图片元数据,都不会把两种尺度混在一起。
import colorsys
def rgb255_to_hls(rgb):
# 把外部常见的 0 到 255 通道转换为 colorsys 使用的 0 到 1 浮点数。
normalized = tuple(channel / 255 for channel in rgb)
# HLS 的返回顺序固定是 hue、lightness、saturation。
return colorsys.rgb_to_hls(*normalized)
color_hls = rgb255_to_hls((52, 152, 219))
# h 是 0 到 1 的色相坐标,乘 360 后更适合在角度界面中展示。
print(color_hls[0] * 360, color_hls[1], color_hls[2])
这个配方的关键不是把除法写在一行,而是明确边界:函数输入是 0 到 255,函数输出是 (h, l, s)。调用方如果需要色相角度,只在展示层转换,不要把角度再传回 hls_to_rgb。
HLS 里的亮度和饱和度怎样调整
HLS 适合表达“保持大致色相,只把颜色调亮一点”这类操作。可以先解包元组,再限制调整后的亮度和饱和度仍在 0 到 1。色相通常按环形坐标处理,超过 1 或小于 0 时用取模回到这个范围。
def shift_hls(hls, lightness_delta=0.0, saturation_delta=0.0):
h, l, s = hls
# 色相是环形坐标,取模可以处理超过 1 或小于 0 的情况。
h = h % 1.0
# 亮度和饱和度是区间值,调整后要限制在合法范围内。
l = min(1.0, max(0.0, l + lightness_delta))
s = min(1.0, max(0.0, s + saturation_delta))
return h, l, s
brighter = shift_hls(color_hls, lightness_delta=0.08)
# brighter 仍然是 colorsys 可以接受的 (h, l, s) 三元组。
print(brighter)
这里的“限制”是业务层保护,不是 colorsys 额外提供的校验器。把参数集中在一个小函数里,能避免多个页面分别处理边界,最后出现同一颜色在不同页面亮度不一致的情况。
调整 HLS 后怎样转回 RGB
hls_to_rgb 返回的三个通道仍然是 0 到 1 的浮点数。要交给 CSS、JSON 接口或图像库时,再统一乘以 255,并用 round 得到整数。乘法前后都保留裁剪,可以防止浮点误差把边界推到合法范围之外。

def hls_to_rgb255(hls):
h, l, s = hls
# hls_to_rgb 要求 h、l、s 都是 0 到 1 的坐标,而不是色相角度。
rgb01 = colorsys.hls_to_rgb(h % 1.0, l, s)
# 裁剪并四舍五入,得到 CSS 或接口常用的 8 位整数通道。
return tuple(round(min(1.0, max(0.0, channel)) * 255) for channel in rgb01)
rgb255 = hls_to_rgb255(brighter)
print(rgb255)
如果你要生成 CSS,可以把结果拼成 rgb(r g b);如果接口约定的是小数 RGB,则不要做最后的乘 255,直接保留 rgb01 即可。
HLS 和 HSV 不要把位置顺序混用
同一个模块里还有 rgb_to_hsv 和 hsv_to_rgb。HLS 使用 (h, l, s),HSV 使用 (h, s, v),第二、第三个值的含义不同。把 HSV 元组直接传给 HLS 的逆转换,代码通常不会报错,却会得到明显不同的颜色。
| 目标 | 调用 | 返回顺序 | 坐标范围 |
|---|---|---|---|
| RGB 转 HLS | rgb_to_hls(r, g, b) | h, l, s | 都在 0 到 1 |
| HLS 转 RGB | hls_to_rgb(h, l, s) | r, g, b | 都在 0 到 1 |
| RGB 转 HSV | rgb_to_hsv(r, g, b) | h, s, v | 都在 0 到 1 |
几个实际使用时容易踩到的坑
- 把 0 到 255 直接传入。先在入口归一化,返回显示值时再反向换算。
- 把色相角度传给逆函数。界面上的 180 度要先除以 360,才能成为
colorsys的h。 - 混淆 HLS 和 HSV 的顺序。看到第二个值时先确认它是 lightness 还是 saturation。
- 忽略灰度色。当饱和度接近 0 时,色相对视觉颜色区分的作用很弱,业务上不应依赖灰度色的 h 值做分类。
- 直接截断浮点数。显示层优先使用
round,并在乘 255 前后保持 0 到 1 的边界保护。
可以直接复用的完整片段
如果项目只需要一条稳定的 RGB/HLS 往返路径,可以把归一化、调整和反归一化收拢成下面这个小工具。它不负责读取图片文件,输入输出也保持为普通 Python 元组,便于在 Web 接口或颜色选择器中复用。
import colorsys
def rgb255_to_hls(rgb):
# 统一把 8 位 RGB 通道送入 0 到 1 的标准库坐标。
r, g, b = (channel / 255 for channel in rgb)
return colorsys.rgb_to_hls(r, g, b)
def hls_to_rgb255(hls):
h, l, s = hls
# 亮度和饱和度由调用方控制,色相按环形坐标归一化。
rgb01 = colorsys.hls_to_rgb(h % 1.0, l, s)
# 将标准库输出转换为可显示的整数 RGB,并抵抗边界浮点误差。
return tuple(round(min(1.0, max(0.0, value)) * 255) for value in rgb01)
original = (52, 152, 219)
hls = rgb255_to_hls(original)
# 只调整亮度,保持色相和饱和度的业务含义不变。
adjusted_hls = (hls[0], min(1.0, hls[1] + 0.08), hls[2])
adjusted_rgb = hls_to_rgb255(adjusted_hls)
print(adjusted_rgb)
这套写法的边界很清楚:输入输出层使用 0 到 255,转换层使用 0 到 1,HLS 内部始终按 h、l、s 解包。后续如果换成 HSV,只需要同时替换函数名和元组语义,不要只改一个调用点。
相关问题
colorsys 的色相为什么不是 0 到 360?
它把色相也表示为 0 到 1 的归一化坐标。需要角度时在展示边界乘以 360,传回转换函数前再除以 360。
能不能把十六进制颜色直接传给 colorsys?
不能直接传入。先把十六进制拆成三个 0 到 255 的通道,再按本文的归一化方式转换。
只想调亮颜色,为什么不直接给 RGB 每个通道加值?
直接改 RGB 会同时改变颜色的综合色相和饱和度。先转到 HLS,可以把亮度调整表达得更清楚,再统一转回显示通道。
-
369 收藏
-
344 收藏
-
464 收藏
-
327 收藏
-
440 收藏
-
123 收藏
-
文章 · python教程 | 1小时前 | 标准库 · 持久化 · python · Python Cookiejar expires http.CookieJar FileCookieJar ignore_expires330 收藏
-
299 收藏
-
309 收藏
-
360 收藏
-
131 收藏
-
491 收藏
-
491 收藏
-
147 收藏
-
197 收藏
-
413 收藏
-
154 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习