Add procedure to blend a list of colors to a 16-length list for LED bars
This commit is contained in:
parent
a4cd232390
commit
9e06823fed
2 changed files with 88 additions and 0 deletions
87
pyjecteur/common.py
Normal file
87
pyjecteur/common.py
Normal file
|
@ -0,0 +1,87 @@
|
|||
import logging
|
||||
from colour import Color
|
||||
from typing import List, Callable, Optional, Union, Tuple
|
||||
from enum import Enum
|
||||
|
||||
LedBarLen = 16
|
||||
|
||||
def remove_duplicates(colors: List[Color]) -> Tuple[List[Color], List[int]]:
|
||||
if len(colors) == 0:
|
||||
return ([], [])
|
||||
colors_res = [colors[0]]
|
||||
res_nb = [1]
|
||||
for i in range(1, len(colors)):
|
||||
if colors[i] != colors_res[-1]:
|
||||
colors_res.append(colors[i])
|
||||
res_nb.append(1)
|
||||
else:
|
||||
res_nb[-1] += 1
|
||||
return (colors_res, res_nb)
|
||||
|
||||
def reduplicate(colors: List[Color], repetitions: List[int]) -> List[Color]:
|
||||
"""
|
||||
Re-duplicates a list. Takes in a list of elements and a list of numbers of
|
||||
repetitions. Concatetantes the repeted elements.
|
||||
|
||||
Requires both lists to have the same length
|
||||
"""
|
||||
|
||||
res = []
|
||||
for i in range(len(colors)):
|
||||
for _ in range(repetitions[i]):
|
||||
res.append(colors[i])
|
||||
|
||||
return res
|
||||
|
||||
class InterpType(Enum):
|
||||
"""
|
||||
Interpolation algorithm
|
||||
"""
|
||||
|
||||
NEAREST = 1
|
||||
LINEAR = 2
|
||||
|
||||
class Filling(Enum):
|
||||
|
||||
VOID = 1
|
||||
EXTREMA = 2
|
||||
GREATEST = 3
|
||||
|
||||
def blendLedBar(colors: List[Color],
|
||||
blending: Optional[InterpType] = InterpType.NEAREST,
|
||||
filling: Optional[Filling] = Filling.GREATEST,
|
||||
void_color: Optional[Color] = Color("black")) -> List[Color]:
|
||||
total_len = len(colors)
|
||||
(deduped, rep_nb) = remove_duplicates(colors)
|
||||
if len(deduped) > LedBarLen:
|
||||
# After dedup, there are still too many colors. Only show the first ones
|
||||
logging.warning(f"LED bar interpolation: More than {LedBarLen} colors. Dropping colors")
|
||||
return deduped[:LedBarLen]
|
||||
|
||||
if len(colors) > LedBarLen:
|
||||
# TODO: Try and dedup some colors to save space
|
||||
return colors[:LedBarLen]
|
||||
|
||||
if blending == InterpType.NEAREST:
|
||||
factor = LedBarLen // total_len
|
||||
|
||||
# First pass
|
||||
for i in range(len(rep_nb)):
|
||||
rep_nb[i] *= factor
|
||||
|
||||
gap = LedBarLen - total_len * factor
|
||||
|
||||
# TODO: Add GREATEST
|
||||
# The idea is to first add a repetition to the already longest
|
||||
# repetition to hurt the color ratio as little as possible
|
||||
if gap == 0:
|
||||
return reduplicate(deduped, rep_nb)
|
||||
# If there is still
|
||||
elif filling == Filling.VOID:
|
||||
return (reduplicate(deduped, rep_nb) + ([void_color] * gap))
|
||||
elif filling == Filling.EXTREMA:
|
||||
bot_gap = gap // 2
|
||||
top_gap = gap - bot_gap
|
||||
return (([deduped[0]] * top_gap) + reduplicate(deduped, rep_nb) +
|
||||
([deduped[-1]] * bot_gap))
|
||||
|
|
@ -21,6 +21,7 @@ in
|
|||
ps.black
|
||||
ps.pylint
|
||||
ps.ipython
|
||||
ps.python-lsp-server
|
||||
]))
|
||||
pkgs.pyright
|
||||
];
|
||||
|
|
Loading…
Reference in a new issue