3
$\begingroup$

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[0],color_inferior[1],color_inferior[2])

print (a)
    
$\endgroup$
3
  • $\begingroup$ 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. $\endgroup$
    – batFINGER
    Aug 15 at 7:54
  • $\begingroup$ That's counting colors where every RGB value is wrong, It's more like 17% where at least one RGB value is wrong. $\endgroup$
    – scurest
    Aug 15 at 8:09
  • $\begingroup$ @scurest No doubt it's OR ie 3 * 15 / 256 .. not AND never was good at stats $\endgroup$
    – batFINGER
    Aug 15 at 8:47
10
$\begingroup$

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),
    )
$\endgroup$
1
  • $\begingroup$ Fantastic !!! it works like a charm. thank you so very much for pointing it out and fixing it. $\endgroup$
    – sleepyhead
    Aug 15 at 18:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.