Skip to content

Commit 663106b

Browse files
committed
Update to latest ColorAide
1 parent 028c322 commit 663106b

File tree

21 files changed

+467
-221
lines changed

21 files changed

+467
-221
lines changed

CHANGES.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
## 6.2.0
44

55
- **NEW**: Since browsers do not and may not introduce Color Level 4
6-
gamut mapping at until some future spec, make gamut mapping approach
6+
gamut mapping until some future spec, make gamut mapping approach
77
configurable. Use clipping by default to match browsers as this is
88
likely what people expect even if it is not an ideal approach. Use
9-
`gamut_map` option to manually control the approach.
10-
- **NEW**: Upgrade ColorAide to 2.0.2.
9+
`gamut_map` in settings option to manually control the approach.
10+
- **NEW**: Upgrade ColorAide to 2.3.
1111
- **FIX**: Fix regression where contrast logic could not adjust to a
1212
given contrast due to a property access.
1313

ch_preview.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -676,7 +676,10 @@ def set_file_scan_rules(self, view):
676676
ch_preview_thread.ignore_all = True
677677

678678
view.settings().clear_on_change('color_helper.reload')
679-
view.window().run_command("color_helper_preview", {"clear": True})
679+
win = view.window()
680+
if win is None:
681+
return
682+
win.run_command("color_helper_preview", {"clear": True})
680683

681684
file_name = view.file_name()
682685
ext = os.path.splitext(file_name)[1].lower() if file_name is not None else None

color_helper.sublime-settings

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@
150150
// "ColorHelper.lib.coloraide.spaces.rec2100_hlg.Rec2100HLG",
151151
// "ColorHelper.lib.coloraide.spaces.rec2100_pq.Rec2100PQ",
152152
// "ColorHelper.lib.coloraide.spaces.rlab.RLAB",
153+
// "ColorHelper.lib.coloraide.spaces.xyb.XYB",
153154
// "ColorHelper.lib.coloraide.spaces.xyy.xyY",
154155
"ColorHelper.lib.coloraide.spaces.hsluv.HSLuv",
155156
"ColorHelper.lib.coloraide.spaces.lchuv.LChuv",

lib/coloraide/__meta__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,5 +192,5 @@ def parse_version(ver: str) -> Version:
192192
return Version(major, minor, micro, release, pre, post, dev)
193193

194194

195-
__version_info__ = Version(2, 0, 2, "final")
195+
__version_info__ = Version(2, 3, 0, "final")
196196
__version__ = __version_info__._get_canonical()

lib/coloraide/algebra.py

Lines changed: 80 additions & 93 deletions
Large diffs are not rendered by default.

lib/coloraide/average.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
"""Average colors together."""
2+
import math
3+
from .types import ColorInput
4+
from typing import Iterable, TYPE_CHECKING, Type
5+
6+
if TYPE_CHECKING: # pragma: no cover
7+
from .color import Color
8+
9+
10+
def average(create: Type['Color'], colors: Iterable[ColorInput], space: str, premultiplied: bool = True) -> 'Color':
11+
"""Average a list of colors together."""
12+
13+
obj = create(space, [])
14+
15+
# Get channel information
16+
cs = obj.CS_MAP[space]
17+
hue_index = cs.hue_index() if hasattr(cs, 'hue_index') else -1
18+
channels = cs.channels
19+
chan_count = len(channels)
20+
alpha_index = chan_count - 1
21+
sums = [0.0] * chan_count
22+
totals = [0.0] * chan_count
23+
sin = 0.0
24+
cos = 0.0
25+
26+
# Sum channel values
27+
i = -1
28+
for c in colors:
29+
coords = obj.update(c)[:]
30+
alpha = coords[-1]
31+
if math.isnan(alpha):
32+
alpha = 1.0
33+
i = 0
34+
for coord in coords:
35+
if not math.isnan(coord):
36+
totals[i] += 1
37+
if i == hue_index:
38+
rad = math.radians(coord)
39+
sin += math.sin(rad)
40+
cos += math.cos(rad)
41+
else:
42+
sums[i] += (coord * alpha) if premultiplied and i != alpha_index else coord
43+
i += 1
44+
45+
if i == -1:
46+
raise ValueError('At least one color must be provided in order to average colors')
47+
48+
# Get the mean
49+
alpha = sums[-1]
50+
alpha_t = totals[-1]
51+
sums[-1] = float('nan') if not alpha_t else alpha / alpha_t
52+
alpha = sums[-1]
53+
if math.isnan(alpha) or alpha in (0.0, 1.0):
54+
alpha = 1.0
55+
for i in range(chan_count - 1):
56+
total = totals[i]
57+
if not total:
58+
sums[i] = float('nan')
59+
elif i == hue_index:
60+
sums[i] = math.degrees(math.atan2(sin / total, cos / total))
61+
else:
62+
sums[i] /= total * alpha if premultiplied else total
63+
64+
# Return the color
65+
return obj.update(space, sums[:-1], sums[-1])

lib/coloraide/color.py

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from . import filters
1212
from . import contrast
1313
from . import harmonies
14+
from . import average
1415
from . import util
1516
from . import algebra as alg
1617
from itertools import zip_longest as zipl
@@ -61,7 +62,7 @@
6162
from .interpolate.bspline_natural import NaturalBSpline
6263
from .interpolate.monotone import Monotone
6364
from .types import Plugin
64-
from typing import overload, Union, Sequence, Dict, List, Optional, Any, Callable, Tuple, Type, Mapping
65+
from typing import overload, Union, Sequence, Iterable, Dict, List, Optional, Any, Callable, Tuple, Type, Mapping
6566

6667

6768
class ColorMatch:
@@ -131,6 +132,7 @@ class Color(metaclass=ColorMeta):
131132
INTERPOLATE = util.DEF_INTERPOLATE
132133
DELTA_E = util.DEF_DELTA_E
133134
HARMONY = util.DEF_HARMONY
135+
AVERAGE = util.DEF_AVERAGE
134136
CHROMATIC_ADAPTATION = 'bradford'
135137
CONTRAST = 'wcag21'
136138

@@ -657,7 +659,7 @@ def clip(self, space: Optional[str] = None) -> 'Color':
657659
space = self.space()
658660

659661
# Convert to desired space
660-
c = self.convert(space, in_place=True)
662+
c = self.convert(space, in_place=True, norm=False)
661663
gamut.clip_channels(c)
662664

663665
# Adjust "this" color
@@ -820,6 +822,26 @@ def interpolate(
820822
**kwargs
821823
)
822824

825+
@classmethod
826+
def average(
827+
cls,
828+
colors: Iterable[ColorInput],
829+
*,
830+
space: Optional[str] = None,
831+
out_space: Optional[str] = None,
832+
premultiplied: bool = True,
833+
**kwargs: Any
834+
) -> 'Color':
835+
"""Average the colors."""
836+
837+
if space is None:
838+
space = cls.AVERAGE
839+
840+
if out_space is None:
841+
out_space = space
842+
843+
return average.average(cls, colors, space, premultiplied).convert(out_space, in_place=True)
844+
823845
def filter( # noqa: A003
824846
self,
825847
name: str,

lib/coloraide/everything.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from .spaces.cmy import CMY
2020
from .spaces.cmyk import CMYK
2121
from .spaces.xyy import xyY
22+
from .spaces.xyb import XYB
2223
from .spaces.hunter_lab import HunterLab
2324
from .spaces.prismatic import Prismatic
2425
from .spaces.rlab import RLAB
@@ -73,6 +74,7 @@ class ColorAll(Base):
7374
CMY(),
7475
CMYK(),
7576
xyY(),
77+
XYB(),
7678
HunterLab(),
7779
Prismatic(),
7880
RLAB(),

lib/coloraide/gamut/fit_lch_chroma.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from ..gamut import Fit, clip_channels
33
from ..cat import WHITES
44
from .. import util
5+
import math
56
from typing import TYPE_CHECKING, Any, Dict
67

78
if TYPE_CHECKING: # pragma: no cover
@@ -49,7 +50,7 @@ def fit(self, color: 'Color', **kwargs: Any) -> None:
4950

5051
# Return white or black if lightness is out of dynamic range for lightness.
5152
# Extreme light case only applies to SDR, but dark case applies to all ranges.
52-
if sdr and lightness >= self.MAX_LIGHTNESS:
53+
if sdr and (lightness >= self.MAX_LIGHTNESS or math.isclose(lightness, self.MAX_LIGHTNESS, abs_tol=1e-6)):
5354
clip_channels(color.update('xyz-d65', WHITE, mapcolor[-1]))
5455
return
5556
elif lightness <= self.MIN_LIGHTNESS:

lib/coloraide/interpolate/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -665,13 +665,13 @@ def interpolator(
665665
if isinstance(x, stop):
666666
i += 1
667667
stops[i] = x.stop
668-
color = current._handle_color_input(x.color)
668+
color = current.new(x.color)
669669
elif callable(x):
670670
easing = x
671671
continue
672672
else:
673673
i += 1
674-
color = current._handle_color_input(x)
674+
color = current.new(x)
675675
stops[i] = None
676676

677677
# Adjust color to space

0 commit comments

Comments
 (0)