Skip to content

Commit

Permalink
Add a new optional parameter to colortemp() to control normalising
Browse files Browse the repository at this point in the history
  • Loading branch information
jonathanhogg committed Jan 4, 2025
1 parent d16e3f6 commit 30201c9
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 7 deletions.
6 changes: 4 additions & 2 deletions docs/builtins.md
Original file line number Diff line number Diff line change
Expand Up @@ -441,15 +441,17 @@ MIT license.

## Color functions

`colortemp(` *t* `)`
`colortemp(` *t* [, *normalize*`=false` ] `)`
: Return a 3-vector of *R*, *G* and *B* **linear sRGB** values for an
approximation of the irradiance of a Planckian (blackbody) radiator at
temperature *t*, scaled so that `colortemp(6503.5)` (the sRGB whitepoint
correlated colour temperature) is close to `1;1;1`; the approximation only holds
within the range *[1667,25000]* and, strictly speaking, values below 1900°K are
outside the sRGB gamut; irradiance is proportional to the 4th power of the
temperature, so the values are very small at low temperatures and become
*significantly* larger at higher temperatures.
*significantly* larger at higher temperatures. If the optional *normalize*
parameter is `true` then the returned color will be normalized by dividing each
channel by the larger of the 3.

`hsl(` *h* `;` *s* `;` *l* `)`
: Return a 3-vector of *R*, *G* and *B* in the range *[0,1]* from a 3-vector of
Expand Down
19 changes: 14 additions & 5 deletions src/flitter/language/functions.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -1018,11 +1018,12 @@ def hsv(Vector color):

@cython.cdivision(True)
@cython.cpow(True)
def colortemp(Vector t):
def colortemp(Vector t, Vector normalize=false_):
if t.numbers == NULL:
return null_
cdef int64_t i, n = t.length
cdef double T, T2, x, x2, y, X, Y, Z
cdef bint norm = normalize.as_bool()
cdef double T, T2, x, x2, y, X, Y, Z, r, g, b, c
cdef Vector rgb = Vector.__new__(Vector)
rgb.allocate_numbers(3*n)
for i in range(n):
Expand All @@ -1042,9 +1043,17 @@ def colortemp(Vector t):
Y = (max(0, t.numbers[i]) / 6503.5)**4
X = Y * x / y
Z = Y * (1 - x - y) / y
rgb.numbers[3*i] = max(0, 3.2406255*X - 1.537208*Y - 0.4986286*Z)
rgb.numbers[3*i+1] = max(0, -0.9689307*X + 1.8757561*Y + 0.0415175*Z)
rgb.numbers[3*i+2] = max(0, 0.0557101*X - 0.2040211*Y + 1.0569959*Z)
r = max(0, 3.2406255*X - 1.537208*Y - 0.4986286*Z)
g = max(0, -0.9689307*X + 1.8757561*Y + 0.0415175*Z)
b = max(0, 0.0557101*X - 0.2040211*Y + 1.0569959*Z)
if norm:
c = max(r, g, b)
r /= c
g /= c
b /= c
rgb.numbers[3*i] = r
rgb.numbers[3*i+1] = g
rgb.numbers[3*i+2] = b
return rgb


Expand Down
2 changes: 2 additions & 0 deletions tests/test_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -687,6 +687,8 @@ def test_split(self):
class TestColorFuncs(utils.TestCase):
def test_colortemp(self):
self.assertAllAlmostEqual(colortemp(Vector(6503.5)), Vector([1, 1, 1]), places=None, delta=0.05)
self.assertAllAlmostEqual(colortemp(Vector(1900)), Vector([0.0192550289, 0.0044625883, 0]), places=7)
self.assertAllAlmostEqual(colortemp(Vector(1900), Vector(1)), Vector([1, 0.0044625883/0.0192550289, 0]), places=7)

def test_oklab(self):
self.assertAllAlmostEqual(oklab(Vector([0, 0, 0])), Vector([0, 0, 0]), places=2)
Expand Down

0 comments on commit 30201c9

Please sign in to comment.