RGB值转HSL值的转换器

8
Google地图API V3允许应用“风格”到地图上,其中包括设置各种要素的颜色。然而,它使用的颜色格式是HSL(或者看起来像是这样):
• 色相(一个RGB十六进制字符串) • 亮度(一个浮点值在-100和100之间) • 饱和度(一个浮点值在-100和100之间)
(来源于文档
我设法在网上找到RGB转HSL转换器,但我不确定如何以一种谷歌地图接受的方式指定转换后的值。例如,转换器给出的典型HSL值为:209° 72% 49%
该HSL值如何映射到我从google maps api中指定的参数?即色相度数值如何映射到RGB十六进制字符串,百分比如何映射到-100和100之间的浮点数值?
我仍然不确定如何进行转换。我需要快速将RGB值转换为Google地图所期望的值,以使颜色完全相同。
4个回答

7

由于hue参数需要RGB值,因此您可以将原始颜色用作hue。

rgb2hsl.py:

#!/usr/bin/env python

def rgb2hsl(r, g, b):
    #Hue: the RGB string
    H = (r<<16) + (g<<8) + b
    H = "0x%06X" % H

    #convert to [0 - 1] range
    r = float(r) / 0xFF
    g = float(g) / 0xFF
    b = float(b) / 0xFF

    #http://en.wikipedia.org/wiki/HSL_and_HSV#Lightness
    M = max(r,g,b)
    m = min(r,g,b)
    C = M - m

    #Lightness
    L = (M + m) / 2

    #Saturation (HSL)
    if L == 0:
        S = 0
    elif L <= .5:
        S = C/(2*L)
    else:
        S = C/(2 - 2*L)

    #gmaps wants values from -100 to 100
    S = int(round(S * 200 - 100))
    L = int(round(L * 200 - 100))

    return (H, S, L)


def main(r, g, b):
    r = int(r, base=16)
    g = int(g, base=16)
    b = int(b, base=16)
    print rgb2hsl(r,g,b)

if __name__ == '__main__':
    from sys import argv
    main(*argv[1:])

例子:

$ ./rgb2hsl.py F0 FF FF
('0xF0FFFF', 100, 94)

结果:

以下是一个屏幕截图,显示了页面的背景颜色为rgb(#2800E2),并且使用上述计算出来的值('0x2800E2',100,-11)对谷歌地图进行了道路几何样式的处理。

很明显,谷歌使用您的样式以创建围绕给定颜色中心的约六种不同的颜色,而轮廓线最接近输入的颜色。我认为这已经非常接近了。

alt text


从试验中发现: http://gmaps-samples-v3.googlecode.com/svn/trunk/styledmaps/wizard/index.html

对于水域,gmaps 减去了 0.5 的伽马值。要获得所需的确切颜色,请使用上面的计算,并将其加回 0.5 个伽马值。

例如:

{
  featureType: "water",
  elementType: "geometry",
  stylers: [
    { hue: "#2800e2" },
    { saturation: 100 },
    { lightness: -11 },
    { gamma: 0.5 },
  ]
}

@aeq:我已经根据您的描述进行了修改并更新了示例。 - bukzor
嗯...你的修改和我在评论中提到的基本相同。转换后的值在地图上显示得非常接近原始的RGB值。但仍然有一点偏差。例如,#2800E2稍微呈紫色...我想知道为什么还是有偏差。 - aeq
有趣。我实际上正在尝试为地图上的水体着色,因此没有轮廓或边框的概念。他们这样做很奇怪...谢谢。 - aeq
@aeq:我对S的计算进行了更正。之前我使用的是HSV公式。 - bukzor
你的脚本正确计算了S和L。我通过尝试在线RGB到HSL转换器并将值缩放为-100到100来确认,我得到了与你的脚本相同的输出。因此,可能是gmaps在处理H值时做了一些不同的事情,或者他们以某种方式进行了调整...或者我可能漏掉了什么。 - aeq
显示剩余4条评论

4
我们编写了一个工具,可以将十六进制的RGB值转换成所需的HSL代码。它带有预览和Google地图JavaScript API V3代码输出功能。享受吧;D http://googlemapscolorizr.stadtwerk.org/

你们好,这是最好的答案!!我爱你们,STADT.WERK!!我花了整整一个小时尝试让被接受的答案中的脚本工作,但它从未成功过,而这个答案在第一次尝试时就起作用了。 - lfborjas

0

我需要精确匹配颜色。所以我使用@stadt.werk提供的工具(http://googlemapscolorizr.stadtwerk.org/)来接近匹配。

但是,我遇到了@bukzor解释的问题,即Google Maps API会在您的阴影上创建变化,其中没有一个似乎完全符合我指定的内容。

因此,我在浏览器中打开地图,在屏幕截图中仅获取两个不完全匹配的阴影区域,将其在图像编辑器中打开(在我的情况下为pixlr.com),使用吸管工具获取阴影的饱和度和亮度,通过调整Google API调用中的饱和度和/或亮度1次,重复此过程,直到获得看起来完美匹配的东西。

当然,Google Maps API可能会在不同的设备/浏览器等上对颜色进行不同的处理,但目前为止还不错。

这很繁琐,但它有效。


0

来自链接页面:

注意:虽然色调采用HTML十六进制颜色值,但它仅使用此值来确定基本颜色(其在色轮周围的方向),而不是饱和度或亮度,这些指示为百分比变化。例如,纯绿色的色调可以定义为“#00ff00”或“#000100”,两个色调都将相同。(两个值在HSL颜色模型中指向纯绿色。)由等量的红色,绿色和蓝色组成的RGB色调值 - 例如“#000000”(黑色)和“#FFFFFF”(白色)以及所有纯灰色调 - 不表示任何色调,因为这些值都不表示在HSL坐标空间中的方向。要表示黑色,白色或灰色,必须去除所有饱和度(将值设置为-100),并调整亮度。

至少我理解的是,这意味着您需要根据颜色轮转换您的角度。例如,假设0度是纯红色,120度是纯蓝色,240度是纯绿色。然后,您将取得您的角度,确定它落在哪两个主色之间,并插值以确定每个主色的使用量。理论上,您可能应该使用二次插值 - 但很有可能您可以通过线性插值得到合理的结果。

使用这个方法,90度(例如)是从红色到蓝色的3/4,因此您的色相的十六进制数应为0x00010003 - 或任何其他绿色设置为0,红色和蓝色之间的比率为1:3的数字。


如果使用RGB到HSL转换器来计算角度,那么RGB值已经存在了... RGB值可以直接转换为十六进制并作为H值发送,然后只需使用转换器来计算S和L。或者我有什么误解。 - Andrew Shelansky
我有一个相关的设计问题。如果想要HSL颜色的系统接受RGB值作为H,那么它为什么需要S和L呢?似乎如果它要进行颜色空间转换来计算H,它可能会直接使用指定的颜色。或者说,在RGB空间中使用HSL方式提供了一些RGB空间缺失的东西吗? - Andrew Shelansky
@Andrew:关于直接使用RGB值,也许可以,但也可能不行。特别是,我相当确定它真的希望至少有一个分量被设置为0,而原始的RGB颜色通常不会这样。 - Jerry Coffin
我怀疑他们在使用HSL来实现设备无关性。RGB值(仅仅是它本身)基本上是参考给定设备产生的颜色,所以0,0,0表示它能产生的最暗黑色,而255,255,255则表示它能产生的最亮白色 - 但是(例如)这些值在显示器和打印机之间会有很大的差异(即使在同一台打印机上,也会因为所用纸张的不同而有所变化)。HSL值比较容易参考到某个“中性”颜色空间(CIE XYZ更好,但更难以可视化、解释或转换为/从RGB)。 - Jerry Coffin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接