Skip to content

Instantly share code, notes, and snippets.

@facelessuser
Created February 26, 2024 18:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save facelessuser/e5144f6846c83e24f0c5619fc82ee45d to your computer and use it in GitHub Desktop.
Save facelessuser/e5144f6846c83e24f0c5619fc82ee45d to your computer and use it in GitHub Desktop.
Compare GMA
from coloraide.gamut import Fit
from coloraide.spaces import RGBish
from coloraide import algebra as alg
class OkLChScale(Fit):
"""
Gamut mapping by scaling.
Expected gamut mapping spaces are RGB type spaces.
For best results, linear light RGB spaces are preferred.
"""
NAME = "oklch-scale"
SPACE = "oklch"
def fit(self, color, space, **kwargs):
"""Scale the color within its gamut but preserve L and h as much as possible."""
# Requires an RGB-ish space, preferably a linear space.
if not isinstance(color.CS_MAP[space], RGBish):
raise ValueError("Scaling only works in an RGBish color space, not {}".format(type(color.CS_MAP[space])))
# For now, if a non-linear CSS variant is specified, just use the linear form.
if space in {'srgb', 'display-p3', 'rec2020', 'a98-rgb', 'prophoto-rgb'}:
space += '-linear'
orig = color.space()
mapcolor = color.convert(self.SPACE, norm=False) if orig != self.SPACE else color.clone().normalize(nans=False)
gamutcolor = color.convert(space, norm=False) if orig != space else color.clone().normalize(nans=False)
self.scale(gamutcolor)
gamutcolor.set(
{
self.SPACE + '.l': mapcolor['l'],
self.SPACE + '.h': mapcolor['h']
}
)
self.scale(gamutcolor)
color.update(gamutcolor)
def scale(self, color):
"""Scale the RGB color within its gamut."""
deltas = [c - 0.5 for c in color[:-1]]
max_distance = max(abs(c) for c in deltas)
scalingFactor = max_distance / 0.5;
color[:-1] = [c / scalingFactor + 0.5 for c in deltas]
class ColorScale(Color):
FIT = 'oklch-scale'
ColorScale.register(OkLChScale())
class ColorRayTrace(Color):
FIT = 'oklch-raytrace'
class ColorCSS(Color):
FIT = 'oklch-chroma'
ColorScale.interpolate(['red', 'green'], space='oklch')
ColorRayTrace.interpolate(['red', 'green'], space='oklch')
ColorCSS.interpolate(['red', 'green'], space='oklch')
ColorScale.interpolate(['white', 'blue'], space='oklch')
ColorRayTrace.interpolate(['white', 'blue'], space='oklch')
ColorCSS.interpolate(['white', 'blue'], space='oklch')
ColorScale.interpolate(['oklch(20% 0.8 0)', 'oklch(20% 0.8 360)'], space='oklch', hue='longer')
ColorRayTrace.interpolate(['oklch(20% 0.8 0)', 'oklch(20% 0.8 360)'], space='oklch', hue='longer')
ColorCSS.interpolate(['oklch(20% 0.8 0)', 'oklch(20% 0.8 360)'], space='oklch', hue='longer')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment