4
$\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
    Commented Aug 15, 2021 at 7:54
  • 1
    $\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
    Commented Aug 15, 2021 at 8:09
  • 1
    $\begingroup$ @scurest No doubt it's OR ie 3 * 15 / 256 .. not AND never was good at stats $\endgroup$
    – batFINGER
    Commented Aug 15, 2021 at 8:47

1 Answer 1

13
$\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
    Commented Aug 15, 2021 at 18:40

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .