# how to convert rgb to hex? almost there. 1% error colors

I am trying to get a hex value out of material color. I find an reply here by @douripo: Get Hex triplet for color and real 256 RGB from diffuse Color using python

it successfully converts most of the colors to hex correctly. except a few. here is an example it does not convert right.

in blender, add a material to default cube and manually set its diffuse_color to hex 60590A (brown-ish yellow)

run below code in text editor, it would return 6059AA (purple-ish blue). could anyone check where went wrong? and hopefully a fix?

import bpy
import math

#code by : brecht - devtalk.blender.org
def to_hex(c):
if c < 0.0031308:
srgb = 0.0 if c < 0.0 else c * 12.92
else:
srgb = 1.055 * math.pow(c, 1.0 / 2.4) - 0.055

return hex(max(min(int(srgb * 255 + 0.5), 255), 0))

def toHex(r,g,b):
rgb = [r,g,b]
result = ""
i=0
while i < 3:
val = str(to_hex(rgb[i]))
val = val[2:]
if len(val) == 1:
val += val
result+=val
i+=1
return result

ob = bpy.context.object
color_inferior = ob.active_material.diffuse_color

a = toHex(color_inferior,color_inferior,color_inferior)

print (a)


• 1% is a gross exaggeration: with just integers for colors it would be 16 / 256 cubed or less than one ten thousands of one percent of all possible colors.... , lol. Good spot. IIRC there is another answer re this converting both ways. ... actually prob less, 15 numerator since zero 00 would have worked as expected too. Aug 15 at 7:54
• That's counting colors where every RGB value is wrong, It's more like 17% where at least one RGB value is wrong. Aug 15 at 8:09
• @scurest No doubt it's OR ie 3 * 15 / 256 .. not AND never was good at stats Aug 15 at 8:47

The issue occurs when str(to_hex(rgb[i]))[2:] returns a length 1 value, which is the case for blue in example given "0xa".

        if len(val) == 1:
val += val


incorrectly turning it into "aa" instead of "0a". Using val = "0" + val will correct the issue. Another option, used below, is string formatting to convert an integer i into a zero padded length 2 hex string "%02x" % i

Here's a cleaned up version:

def linear_to_srgb8(c):
if c < 0.0031308:
srgb = 0.0 if c < 0.0 else c * 12.92
else:
srgb = 1.055 * math.pow(c, 1.0 / 2.4) - 0.055

if srgb > 1: srgb = 1

return round(255*srgb)

def toHex(r, g, b):
return "%02x%02x%02x" % (
linear_to_srgb8(r),
linear_to_srgb8(g),
linear_to_srgb8(b),
)

• Fantastic !!! it works like a charm. thank you so very much for pointing it out and fixing it. Aug 15 at 18:40