为什么RGB与HLS颜色系统之间的转换不精确?
我有一个应用程序需要把颜色从RGB格式转换成HLS格式,反过来也需要。查了一下,发现Python的标准库里有一个叫做colorsys的模块可以做到这一点。
不过,问题是这些转换有时候不太准确,得到的结果和这个在线颜色转换器的结果稍微有点不同。
下面是我写的两个小函数,方便使用:
from __future__ import division
import colorsys
def convert_rgb_to_hls(r, g, b):
h, l, s = colorsys.rgb_to_hls(r/255, g/255, b/255)
return "HLS(" + str(int(round(h * 359))) + ", " + str(int(round(l * 100))) + ", " + str(int(round(s * 100))) + ")"
def convert_hls_to_rgb(h, l, s):
r, g, b = colorsys.hls_to_rgb(h/359, l/100, s/100)
return "RGB(" + str(int(round(r * 255))) + ", " + str(int(round(g * 255))) + ", " + str(int(round(b * 255))) + ")"
根据这个在线颜色转换器,RGB(123, 243, 61)应该等于HLS(100, 60, 88)。但是我用colorsys函数得到的结果却不一样:
>>> convert_rgb_to_hls(123, 243, 61)
'HLS(99, 59, 88)' # should be HLS(100, 60, 88)
>>> convert_hls_to_rgb(100, 60, 88)
'RGB(122, 243, 63)' # should be RGB(123, 243, 61)
我最开始以为这只是个四舍五入的问题,但仔细看61和63之间的差别,似乎还有其他原因。那么,究竟是什么呢?是否有可能保证颜色系统之间的转换绝对精确呢?
1 个回答
4
from __future__ import division
import colorsys
def convert_rgb_to_hls(r, g, b):
h, l, s = colorsys.rgb_to_hls(r/255, g/255, b/255)
return "HLS(" + str(int(round(h * 360))) + ", " + str(int(round(l * 100))) + ", " + str(int(round(s * 100))) + ")"
def convert_hls_to_rgb(h, l, s):
r, g, b = colorsys.hls_to_rgb(h/360, l/100, s/100)
return "RGB(" + str(int(round(r * 255))) + ", " + str(int(round(g * 255))) + ", " + str(int(round(b * 255))) + ")"
更改内容:
- 使用360而不是359,因为范围是[0, 360)(维基百科)。
- 在
convert_rgb_to_hls(r, g, b)
中缺少了两个舍入步骤。 - 添加了Python 3的除法,以防你使用的是Python 2。
测试:
>>> convert_rgb_to_hls(123, 243, 61)
'HLS(100, 60, 88)'
>>> convert_hls_to_rgb(100, 60, 88)
'RGB(123, 243, 63)'
你说得对,确实存在舍入错误,但61和63之间的差别是因为舍入时会失去精度。为了更好的精度,不要进行舍入:
>>> (r_orig, g_orig, b_orig) = (123, 243, 61)
>>> h,l,s = colorsys.rgb_to_hls(r_orig/255, g_orig/255, b_orig/255)
>>> r, g, b = colorsys.hls_to_rgb(h, l, s)
>>> r*255, g*255, b*255
(123.00000000000003, 242.99999999999997, 61.000000000000036)