Skip to content

Commit

Permalink
Adjust internal handling of compositing
Browse files Browse the repository at this point in the history
  • Loading branch information
facelessuser committed Sep 5, 2024
1 parent 98980f2 commit 78eba69
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 29 deletions.
7 changes: 4 additions & 3 deletions coloraide/color.py
Original file line number Diff line number Diff line change
Expand Up @@ -1207,11 +1207,12 @@ def compose(
"""Blend colors using the specified blend mode."""

if not isinstance(backdrop, str) and isinstance(backdrop, Sequence):
bcolor = [self._handle_color_input(c) for c in backdrop]
colors = [self._handle_color_input(c) for c in backdrop]
else:
bcolor = [self._handle_color_input(backdrop)]
colors = [self._handle_color_input(backdrop)]
colors.insert(0, self)

color = compositing.compose(self, bcolor, blend, operator, space, out_space)
color = compositing.compose(type(self), colors, blend, operator, space, out_space)
return self._hotswap(color) if in_place else color

def delta_e(
Expand Down
48 changes: 22 additions & 26 deletions coloraide/compositing/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
from . import blend_modes
from .. import algebra as alg
from ..channels import Channel
from typing import TYPE_CHECKING
from ..types import Vector, ColorInput
from typing import TYPE_CHECKING, Sequence

if TYPE_CHECKING: # pragma: no cover
from ..color import Color
Expand All @@ -34,18 +35,19 @@ def clip_channel(coord: float, channel: Channel) -> float:


def apply_compositing(
color1: Color,
color2: Color,
color1: Vector,
color2: Vector,
channels: tuple[Channel, ...],
blender: blend_modes.Blend | None,
operator: str | bool
) -> Color:
) -> Vector:
"""Perform the actual blending."""

# Get the color coordinates
csa = color1.alpha(nans=False)
cba = color2.alpha(nans=False)
coords1 = color1.coords(nans=False)
coords2 = color2.coords(nans=False)
csa = color1[-1]
cba = color2[-1]
coords1 = color1[:-1]
coords2 = color2[:-1]

# Setup compositing
compositor = None # type: porter_duff.PorterDuff | None
Expand All @@ -57,9 +59,6 @@ def apply_compositing(
compositor = porter_duff.compositor('source-over')(cba, csa)
cra = alg.clamp(compositor.ao(), 0, 1)

# Perform compositing
channels = color1._space.CHANNELS

# Blend each channel. Afterward, clip and apply alpha compositing.
i = 0
for cb, cr in zip(coords2, blender.blend(coords2, coords1) if blender else coords1):
Expand All @@ -77,15 +76,18 @@ def apply_compositing(


def compose(
color: Color,
backdrop: list[Color],
color_cls: type[Color],
colors: Sequence[ColorInput],
blend: str | bool = True,
operator: str | bool = True,
space: str | None = None,
out_space: str | None = None
) -> Color:
"""Blend colors using the specified blend mode."""

if not colors: # pragma: no cover
raise ValueError('At least one color is required for compositing.')

# We need to go ahead and grab the blender as we need to check what type of blender it is.
blender = None # blend_modes.Blend | None
if isinstance(blend, str):
Expand All @@ -100,18 +102,12 @@ def compose(
if out_space is None:
out_space = space

if not isinstance(color.CS_MAP[space], RGBish):
raise ValueError(f"Can only compose in an RGBish color space, not {type(color.CS_MAP[space])}")

if not backdrop:
return color

dest = backdrop[-1].convert(space)
if len(backdrop) > 1:
for x in range(len(backdrop) - 2, -1, -1):
src = backdrop[x].convert(space)
dest = apply_compositing(src, dest, blender, operator)
if not isinstance(color_cls.CS_MAP[space], RGBish):
raise ValueError(f"Can only compose in an RGBish color space, not {type(color_cls.CS_MAP[space])}")

src = color.convert(space)
dest = color_cls._handle_color_input(colors[-1]).convert(space).normalize(nans=False)[:]
for x in range(len(colors) - 2, -1, -1):
src = color_cls._handle_color_input(colors[x]).convert(space).normalize(nans=False)[:]
dest = apply_compositing(src, dest, color_cls.CS_MAP[space].channels, blender, operator)

return apply_compositing(src, dest, blender, operator).convert(out_space, in_place=True)
return color_cls(space, dest[:-1], dest[-1]).convert(out_space, in_place=True)

0 comments on commit 78eba69

Please sign in to comment.