Search code examples
pythonpython-3.xcolorshexhsl

Converting hsl to hex in python3


I have the following string taken from the atom one-dark syntax:

one_dark_syn = """
@hue-1:   hsl(187, 47%, 55%); // <-cyan
@hue-2:   hsl(207, 82%, 66%); // <-blue
@hue-3:   hsl(286, 60%, 67%); // <-purple
@hue-4:   hsl( 95, 38%, 62%); // <-green
@hue-5:   hsl(355, 65%, 65%); // <-red 1
@hue-5-2: hsl(  5, 48%, 51%); // <-red 2
@hue-6:   hsl( 29, 54%, 61%); // <-orange 1
@hue-6-2: hsl( 39, 67%, 69%); // <-orange 2
"""

I would like to use python to exchange the hsl values for hex. So far I've concocted a pretty nasty looking set of loops to parse out the values into a numpy array:

od_colors = [i.split(";")[0].split(":")[1] for i in one_dark_syn.split("\n") if "hsl" in i]
od_colors = [i.strip().replace("%","").replace("hsl","").replace(" ","") for i in od_colors]
od_colors = [i.replace("(","").replace(")","").split(",") for i in od_colors]
od_colors = np.array(od_colors,dtype="int32")

See like I said nasty. Does anyone have a more pythonic way of parsing this? and most importantly how would you recommend I go about converting hsl to hex?


Solution

  • I would use regular expressions:

    regex = r'hsl\(\s*(\d+),\s*(\d+)%,\s*(\d+)%\s*\);'
    lines = [re.findall(regex,line) for line in one_dark_syn.split('\n')]
    rgbs = [colorsys.hsv_to_rgb(int(line[0][0])/360,
                                int(line[0][1])/100,
                                int(line[0][2])/100) for line in lines if line]
    # [(0.2915, 0.519842, 0.55), (0.1188, 0.41646, 0.66), (0.5762, 0.268, 0.67), 
    #  (0.48257, 0.62, 0.3844), (0.65, 0.2275, 0.2627), (0.51, 0.2856, 0.2652), 
    #  (0.61, 0.43981, 0.2806), (0.69, 0.528195, 0.2277)]
    

    Finally, convert RGB triplets to a HEX string:

    rgbhex = ["".join("%02X" % round(i*255) for i in rgb) for rgb in rgbs]
    # ['1D3437', '0C2A42', '3A1B43', '303E26', '41171A', '331D1B', '3D2C1C', '453517']