Source code for noisemaker.oklab
"""
Oklab color space conversion.
Based on https://bottosson.github.io/posts/oklab/
"""
from __future__ import annotations
import tensorflow as tf
from noisemaker.util import from_linear_rgb, from_srgb
[docs]
def rgb_to_oklab(tensor: tf.Tensor) -> tf.Tensor:
"""
Convert RGB color space to Oklab.
Args:
tensor: RGB tensor with shape [height, width, channels]
Returns:
Oklab tensor with shape [height, width, 3]
"""
tensor = from_srgb(tensor)
r = tensor[:, :, 0]
g = tensor[:, :, 1]
b = tensor[:, :, 2]
l = 0.4121656120 * r + 0.5362752080 * g + 0.0514575653 * b
m = 0.2118591070 * r + 0.6807189584 * g + 0.1074065790 * b
s = 0.0883097947 * r + 0.2818474174 * g + 0.6302613616 * b
l_ = l ** (1 / 3.0)
m_ = m ** (1 / 3.0)
s_ = s ** (1 / 3.0)
return tf.stack(
[
0.2104542553 * l_ + 0.7936177850 * m_ - 0.0040720468 * s_,
1.9779984951 * l_ - 2.4285922050 * m_ + 0.4505937099 * s_,
0.0259040371 * l_ + 0.7827717662 * m_ - 0.8086757660 * s_,
],
2,
)
[docs]
def oklab_to_rgb(tensor: tf.Tensor) -> tf.Tensor:
"""
Convert Oklab color space to RGB.
Args:
tensor: Oklab tensor with shape [height, width, 3]
Returns:
RGB tensor with shape [height, width, channels]
"""
L = tensor[:, :, 0]
a = tensor[:, :, 1]
b = tensor[:, :, 2]
l_ = L + 0.3963377774 * a + 0.2158037573 * b
m_ = L - 0.1055613458 * a - 0.0638541728 * b
s_ = L - 0.0894841775 * a - 1.2914855480 * b
l = l_ * l_ * l_
m = m_ * m_ * m_
s = s_ * s_ * s_
tensor = tf.stack(
[
+4.0767245293 * l - 3.3072168827 * m + 0.2307590544 * s,
-1.2681437731 * l + 2.6093323231 * m - 0.3411344290 * s,
-0.0041119885 * l - 0.7034763098 * m + 1.7068625689 * s,
],
2,
)
return from_linear_rgb(tensor)