Interpolation
Description
Interpolation plugins allow for interpolation between one or more colors. All interpolation in ColorAide is provided via plugins.
Plugin Class
Plugins are created by subclassing coloraide.interpolate.Interpolate.
class Interpolate(Generic[AnyColor], Plugin, metaclass=ABCMeta):
"""Interpolation plugin."""
NAME = ""
@abstractmethod
def interpolator(
self,
coordinates: list[Vector],
channel_names: Sequence[str],
color_cls: type[AnyColor],
easings: list[Callable[..., float] | None],
stops: dict[int, float],
space: str,
out_space: str,
progress: Union[Mapping[str, Callable[..., float]], Callable[..., float]] | None,
premultiplied: bool,
extrapolate: bool = False,
domain: list[float] | None = None,
hue: str = 'shorter',
**kwargs: Any
) -> Interpolator[AnyColor]:
"""Get the interpolator object."""
def get_space(self, space: str | None, color_cls: type[AnyColor]) -> str:
"""
Get and validate the color space for interpolation.
If no space is defined, return an appropriate default color space.
"""
Once registered, the plugin can then be used via interpolate, steps, or mix by passing its NAME via the method
parameter along with any additional key word arguments to override default behavior. An Interpolator object will be
returned which allows for interpolating between the given list of colors.
The Interpolate class also defines a get_space method that will be passed a the user defined space (if one is
specified) and can validate whether the space is supported, raising an error if not, or return the space. If a space
is not specified, an appropriate default can be returned, usually Color.INTERPOLATE but can differ if the interpolator
can only support very specific spaces.
color.interpolate(colors, method=NAME)
In general, the Interpolate plugin is mainly a wrapper to ensure the interpolation setup uses an appropriate
Interpolator object which does the actual work. An interpolation plugin should derive their Interpolator class from
coloraide.interpolate.Interpolator. While we won't show all the methods of the class, we will show the two functions
that must be defined.
class Interpolator(Generic[AnyColor], metaclass=ABCMeta):
"""Interpolator."""
@abstractmethod
def setup(self) --> None:
"""Setup."""
@abstractmethod
def interpolate(
self,
point: float,
index: int,
) -> Vector:
"""Interpolate."""
__init__ usually shouldn't be changed as it handles the general initialization for all interpolations. It could be
extended with super() to set some class specific initialization flags for specific features, but generally,
interpolation specific setup logic should be done in Interpolator.setup(). This is often used to restructure data
points to a more agreeable format for a given interpolation method, precalculate premultiplication, or normalize
undefined values when required. There are cases where ColorAide may update data points and re-call setup() directly.
As an example. setup() can be recalled when a continuous interpolation is converted to a discretized one.
Interpolator.interpolate is where the actual interpolation takes place. It expects an index from [1, n], the index
referencing the second color out of the two colors to be interpolated. point, usually between [0, 1], represents the
point on the interpolation line between the two colors under evaluation.
While point is usually a value between [0, 1], where 0 would be the color stop to the left, and 1 would be the color
stop to the right, if point exceeds the range of [0, 1], it can be assumed that the request is on the far left or far
right of all color stops and could be beyond the absolute range of the entire color interpolation chain.
By default, extrapolation is disabled between all colors in an interpolation chain, and any point that exceeds the
range of [0, 1], before easing functions are applied, will be clamped. If extrapolate is set to $!py True, the
points will not be clamped between any colors, in which case, it is an easing functions responsibility to ensure a value
between 0 or 1 if extreme values are not desired.
Check out the source code to see some example plugins.