You are not logged in.

#1 2011-12-03 22:08:49

tavianator
Member
From: Waterloo, ON, Canada
Registered: 2007-08-21
Posts: 859
Website

What's a good interface for sRGB colours?

I'm writing a ray-tracer, which uses Python to define its scene files.  The ray-tracer itself handles sRGB gamma correctly, but I'm having a hard time coming up with an interface that exposes that functionality clearly to the user.  I'll explain with an example:

Intuitively, one would expect Color(1, 1, 1)/2 to equal Color(0.5, 0.5, 0.5).  But because of sRGB gamma, that's not a half-intensity white.  So two lights with Color(1, 1, 1)/2 would not look the same as one full-brightness light, which would be confusing.

My current idea is to have two different types for colours: "Color" for colours in the linear space, and "sRGB" for colours in the sRGB space.  Is there a better way, that would hide more of the complexity of sRGB gamma from users?

Offline

#2 2011-12-04 05:50:49

aspidites
Member
Registered: 2011-03-11
Posts: 30

Re: What's a good interface for sRGB colours?

I couldn't get the link to work to examine the code, so I'm just working off of assumptions.

If the Color object stores channel information in a list, iterators might be a natural fit:

color_1 = Color(1, 1, 1)

# one-liner using list comprehensions and parameter expansion
color_2 = Color(*[channel / 2 for channel in color_1.channels])

# slightly more verbose using an extra variable
channels  = [channel / 2 for channel in color_1.channels]
color_3 = Color(*channels)

# using a for loop
channels = []
for channel in color_1.channels:
    channels.append(channel)

color_4 = Color(*channels)

You might also try having a of_ratio (forgive unintuitive naming class method (alternate constructor) in your Color class:

# This code is untested, but the general idea should hopefully be obvious enough

class Color
    def __init__(self, r, g, b):
        self.r = r
        self.g = g
        self.b = b

    @classmethod
    def of_ratio(cls, ratio):
        return Color(*[channel * ratio for channel in cls.channels])
    
    @property
    def channels(self):
        return [self.r, self.g, self.b]

# example usage
color_1 = Color(1, 1, 1)
color_2 = Color.of_ratiof(color_1, 0.5)

edit:

I just remembered, you could do operator overloading.

Just implement __add__ __sub__ __div__ __mul__, etc respectively.

Last edited by aspidites (2011-12-04 05:59:26)


coder formally known as EnvoyRising

Offline

#3 2011-12-04 18:13:20

tavianator
Member
From: Waterloo, ON, Canada
Registered: 2007-08-21
Posts: 859
Website

Re: What's a good interface for sRGB colours?

Thanks for the tip about the link, turns out my /var was full.  If you want to look at the relevant code, it's here.

It is using operator overloading actually, but the issue is exactly what I want those operators to mean.  Performing the operations in sRGB space has its drawbacks, as does performing them in linear RGB space.

Offline

Board footer

Powered by FluxBB