Skip to content

Commit 5170088

Browse files
committed
Add carryforward support to average
1 parent a47f7c5 commit 5170088

File tree

12 files changed

+52
-17
lines changed

12 files changed

+52
-17
lines changed

coloraide/__meta__.py

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

206206

207-
__version_info__ = Version(8, 5, 1, "final")
207+
__version_info__ = Version(8, 6, 0, "final")
208208
__version__ = __version_info__._get_canonical()

coloraide/average.py

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import itertools as it
66
from .spaces import HWBish
77
from .types import ColorInput, AnyColor
8+
from .interpolate import carryforward_convert
89
from typing import Iterable
910

1011

@@ -24,7 +25,8 @@ def average(
2425
colors: Iterable[ColorInput],
2526
weights: Iterable[float] | None,
2627
space: str,
27-
premultiplied: bool = True
28+
premultiplied: bool = True,
29+
carryforward: bool = False
2830
) -> AnyColor:
2931
"""
3032
Average a list of colors together.
@@ -33,10 +35,9 @@ def average(
3335
"""
3436

3537
sentinel = Sentinel()
36-
obj = color_cls(space, [])
3738

3839
# Get channel information
39-
cs = obj.CS_MAP[space]
40+
cs = color_cls.CS_MAP[space]
4041
if cs.is_polar():
4142
hue_index = cs.hue_index() # type: ignore[attr-defined]
4243
is_hwb = isinstance(cs, HWBish)
@@ -49,6 +50,8 @@ def average(
4950
hue_max = 0.0
5051
to_rad = 0.0
5152
to_hue = 0.0
53+
54+
obj = color_cls(space, [])
5255
channels = cs.channels
5356
chan_count = len(channels)
5457
avgs = [0.0] * chan_count
@@ -83,10 +86,15 @@ def average(
8386
elif w > mx:
8487
mx = w
8588

86-
obj.update(c) # type: ignore[arg-type]
87-
# If cylindrical color is achromatic, ensure hue is undefined
88-
if hue_index >= 0 and not math.isnan(obj[hue_index]) and obj.is_achromatic():
89-
obj[hue_index] = math.nan
89+
if carryforward:
90+
obj.mutate(c) # type: ignore[arg-type]
91+
carryforward_convert(obj, space, hue_index, True)
92+
else:
93+
obj.update(c) # type: ignore[arg-type]
94+
# If cylindrical color is achromatic, ensure hue is undefined
95+
if hue_index >= 0 and not math.isnan(obj[hue_index]) and obj.is_achromatic():
96+
obj[hue_index] = math.nan
97+
9098
coords = obj[:]
9199

92100
# Average weights

coloraide/color.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1226,6 +1226,7 @@ def average(
12261226
space: str | None = None,
12271227
out_space: str | None = None,
12281228
premultiplied: bool = True,
1229+
carryforward: bool | None = False,
12291230
**kwargs: Any
12301231
) -> Self:
12311232
"""Average the colors."""
@@ -1241,7 +1242,8 @@ def average(
12411242
colors,
12421243
weights,
12431244
space,
1244-
premultiplied
1245+
premultiplied,
1246+
carryforward if carryforward is not None else cls.CARRYFORWARD
12451247
).convert(out_space, in_place=True)
12461248

12471249
def filter( # noqa: A003

docs/src/markdown/about/changelog.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ icon: lucide/scroll-text
33
---
44
# Changelog
55

6-
## 8.5.1
6+
## 8.6
77

8+
- **NEW**: Add support for `carryforward` within `average()`.
89
- **ENHANCE**: More accurate dominant wavelength calculations.
910

1011
## 8.5

docs/src/markdown/average.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ It should be noted that when averaging colors with hues which are evenly distrib
6464
will produce an achromatic hue. When achromatic hues are produced during circular mean, the color will discard
6565
chroma/saturation information, producing an achromatic color.
6666

67+
![Evenly Distributed Angles](images/avg-evenly-distributed.png)
68+
6769
```py play
6870
Color.average(['red', 'green', 'blue'], space='hsl')
6971
```
@@ -157,14 +159,22 @@ Color.average(['hsl(30 0 100)', 'hsl(240 100 50 / 1)'], space='hsl')
157159
```
158160

159161
As stated earlier, undefined logic is applied to any channel with undefined values. It should be noted that no attempt
160-
to carry forward the undefined values through conversion is made at this time. If conversion is required, the
162+
to carry forward the undefined values through conversion is made by default. If conversion is required, the
161163
conversions will remove any undefined status unless the channel is an achromatic hues.
162164

163165
```py play
164166
for i in range(12):
165167
Color.average(['darkgreen', f'color(srgb 0 none 0 / {i / 11})', 'color(srgb 0 0 1)'])
166168
```
167169

170+
If desired, `carryforward` can be enabled, and if possible, undefined values will be carried into the target color
171+
space.
172+
173+
```py play
174+
for i in range(12):
175+
Color.average(['darkgreen', f'color(srgb 0 none 0 / {i / 11})', 'color(srgb 0 0 1)'], carryforward=True)
176+
```
177+
168178
When `premultiplied` is enabled, premultiplication will not be applied to a color if its `alpha` is undefined as it is
169179
unknown how to weight the color. Instead, a color with undefined transparency will be treated with full weight.
170180

docs/src/markdown/examples/3d_models.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1133,7 +1133,7 @@ <h1>ColorAide Color Space Models</h1>
11331133
let colorSpaces = null
11341134
let colorGamuts = null
11351135
let lastModel = null
1136-
let package = 'coloraide-8.5.1-py3-none-any.whl'
1136+
let package = 'coloraide-8.6-py3-none-any.whl'
11371137
const defaultSpace = 'lab'
11381138
const defaultGamut = 'srgb'
11391139
const exceptions = new Set(['hwb', 'ryb', 'ryb-biased'])

docs/src/markdown/examples/colorpicker.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,7 @@ <h1>ColorAide Color Picker</h1>
421421
let pyodide = null
422422
let webspace = ''
423423
let initial = 'oklab(0.69 0.13 -0.1 / 0.85)'
424-
let package = 'coloraide-8.5.1-py3-none-any.whl'
424+
let package = 'coloraide-8.6-py3-none-any.whl'
425425

426426
const base = `${window.location.origin}/${window.location.pathname.split('/')[1]}/playground/`
427427
package = base + package
128 KB
Loading

docs/src/zensical.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ extra_javascript:
355355
- assets/pymdownx-extras/extra-loader-Ccztcqfq.js
356356
- https://cdn.jsdelivr.net/npm/ace-builds@1.43.0/src-min-noconflict/ace.js
357357
- https://cdn.jsdelivr.net/npm/mermaid@11.12.1/dist/mermaid.min.js
358-
- playground-config-fadebc12.js
358+
- playground-config-53d4fff2.js
359359
- https://cdn.jsdelivr.net/pyodide/v0.29.0/full/pyodide.js
360360
- assets/coloraide-extras/extra-notebook.js
361361
- https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
var colorNotebook = {
2-
"playgroundWheels": ['micropip', 'pygments-2.19.2-py3-none-any.whl', 'coloraide-8.5.1-py3-none-any.whl'],
3-
"notebookWheels": ['pyyaml', 'markdown-3.10.1-py3-none-any.whl', 'pymdown_extensions-10.20-py3-none-any.whl', 'micropip', 'pygments-2.19.2-py3-none-any.whl', 'coloraide-8.5.1-py3-none-any.whl'],
2+
"playgroundWheels": ['micropip', 'pygments-2.19.2-py3-none-any.whl', 'coloraide-8.6-py3-none-any.whl'],
3+
"notebookWheels": ['pyyaml', 'markdown-3.10.1-py3-none-any.whl', 'pymdown_extensions-10.20-py3-none-any.whl', 'micropip', 'pygments-2.19.2-py3-none-any.whl', 'coloraide-8.6-py3-none-any.whl'],
44
"defaultPlayground": "import coloraide\ncoloraide.__version__\nColor('red')"
55
}

0 commit comments

Comments
 (0)