2022-04-12 11:13:05 +08:00
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
from typing import Iterable, Union
|
2018-03-30 18:19:23 -07:00
|
|
|
|
2018-03-31 15:11:35 -07:00
|
|
|
from colour import Color
|
2022-04-12 11:13:05 +08:00
|
|
|
from colour import hex2rgb
|
|
|
|
from colour import rgb2hex
|
2018-12-24 12:37:51 -08:00
|
|
|
import numpy as np
|
2018-03-31 15:11:35 -07:00
|
|
|
|
2018-12-24 12:37:51 -08:00
|
|
|
from manimlib.constants import WHITE
|
2021-02-25 08:48:22 -08:00
|
|
|
from manimlib.constants import COLORMAP_3B1B
|
2018-12-24 12:37:51 -08:00
|
|
|
from manimlib.utils.bezier import interpolate
|
2021-02-25 08:48:22 -08:00
|
|
|
from manimlib.utils.iterables import resize_with_interpolation
|
2018-03-30 18:19:23 -07:00
|
|
|
|
2022-04-12 11:13:05 +08:00
|
|
|
ManimColor = Union[str, Color]
|
|
|
|
|
2018-04-06 13:58:59 -07:00
|
|
|
|
2022-04-12 11:13:05 +08:00
|
|
|
def color_to_rgb(color: ManimColor) -> np.ndarray:
|
2018-08-18 20:13:49 -07:00
|
|
|
if isinstance(color, str):
|
|
|
|
return hex_to_rgb(color)
|
|
|
|
elif isinstance(color, Color):
|
|
|
|
return np.array(color.get_rgb())
|
|
|
|
else:
|
|
|
|
raise Exception("Invalid color type")
|
2018-03-30 18:19:23 -07:00
|
|
|
|
2018-04-06 13:58:59 -07:00
|
|
|
|
2022-04-12 11:13:05 +08:00
|
|
|
def color_to_rgba(color: ManimColor, alpha: float = 1.0) -> np.ndarray:
|
2018-08-15 17:30:24 -07:00
|
|
|
return np.array([*color_to_rgb(color), alpha])
|
2018-03-30 18:19:23 -07:00
|
|
|
|
2018-04-06 13:58:59 -07:00
|
|
|
|
2022-04-12 11:13:05 +08:00
|
|
|
def rgb_to_color(rgb: Iterable[float]) -> Color:
|
2018-03-30 18:19:23 -07:00
|
|
|
try:
|
2022-04-12 11:13:05 +08:00
|
|
|
return Color(rgb=tuple(rgb))
|
2020-02-22 13:20:37 -08:00
|
|
|
except ValueError:
|
2018-03-30 18:19:23 -07:00
|
|
|
return Color(WHITE)
|
|
|
|
|
2018-04-06 13:58:59 -07:00
|
|
|
|
2022-04-12 11:13:05 +08:00
|
|
|
def rgba_to_color(rgba: Iterable[float]) -> Color:
|
|
|
|
return rgb_to_color(tuple(rgba)[:3])
|
2018-03-30 18:19:23 -07:00
|
|
|
|
2018-04-06 13:58:59 -07:00
|
|
|
|
2022-04-12 11:13:05 +08:00
|
|
|
def rgb_to_hex(rgb: Iterable[float]) -> str:
|
|
|
|
return rgb2hex(rgb, force_long=True).upper()
|
2018-04-06 13:58:59 -07:00
|
|
|
|
2018-03-30 18:19:23 -07:00
|
|
|
|
2022-04-12 11:26:19 +08:00
|
|
|
def hex_to_rgb(hex_code: str) -> np.ndarray:
|
|
|
|
return np.array(hex2rgb(hex_code))
|
2018-08-18 20:13:49 -07:00
|
|
|
|
|
|
|
|
2022-04-12 11:13:05 +08:00
|
|
|
def invert_color(color: ManimColor) -> Color:
|
2018-03-30 18:19:23 -07:00
|
|
|
return rgb_to_color(1.0 - color_to_rgb(color))
|
|
|
|
|
2018-04-06 13:58:59 -07:00
|
|
|
|
2022-04-12 11:13:05 +08:00
|
|
|
def color_to_int_rgb(color: ManimColor) -> np.ndarray:
|
2018-04-06 13:58:59 -07:00
|
|
|
return (255 * color_to_rgb(color)).astype('uint8')
|
2018-03-30 18:19:23 -07:00
|
|
|
|
2018-04-06 13:58:59 -07:00
|
|
|
|
2022-04-12 11:13:05 +08:00
|
|
|
def color_to_int_rgba(color: ManimColor, opacity: float = 1.0) -> np.ndarray:
|
2018-05-21 12:11:46 -07:00
|
|
|
alpha = int(255 * opacity)
|
2020-02-13 12:03:54 -08:00
|
|
|
return np.array([*color_to_int_rgb(color), alpha])
|
2018-03-30 18:19:23 -07:00
|
|
|
|
2018-04-06 13:58:59 -07:00
|
|
|
|
2022-04-12 11:13:05 +08:00
|
|
|
def color_gradient(
|
|
|
|
reference_colors: Iterable[ManimColor],
|
|
|
|
length_of_output: int
|
|
|
|
) -> list[Color]:
|
2018-03-30 18:19:23 -07:00
|
|
|
if length_of_output == 0:
|
2022-04-12 11:13:05 +08:00
|
|
|
return []
|
2018-08-09 17:56:05 -07:00
|
|
|
rgbs = list(map(color_to_rgb, reference_colors))
|
2018-03-30 18:19:23 -07:00
|
|
|
alphas = np.linspace(0, (len(rgbs) - 1), length_of_output)
|
|
|
|
floors = alphas.astype('int')
|
|
|
|
alphas_mod1 = alphas % 1
|
2018-04-06 13:58:59 -07:00
|
|
|
# End edge case
|
2018-03-30 18:19:23 -07:00
|
|
|
alphas_mod1[-1] = 1
|
|
|
|
floors[-1] = len(rgbs) - 2
|
|
|
|
return [
|
2018-04-06 13:58:59 -07:00
|
|
|
rgb_to_color(interpolate(rgbs[i], rgbs[i + 1], alpha))
|
2018-03-30 18:19:23 -07:00
|
|
|
for i, alpha in zip(floors, alphas_mod1)
|
|
|
|
]
|
|
|
|
|
2018-04-06 13:58:59 -07:00
|
|
|
|
2022-04-12 11:13:05 +08:00
|
|
|
def interpolate_color(
|
|
|
|
color1: ManimColor,
|
|
|
|
color2: ManimColor,
|
|
|
|
alpha: float
|
|
|
|
) -> Color:
|
2018-03-30 18:19:23 -07:00
|
|
|
rgb = interpolate(color_to_rgb(color1), color_to_rgb(color2), alpha)
|
|
|
|
return rgb_to_color(rgb)
|
|
|
|
|
2018-04-06 13:58:59 -07:00
|
|
|
|
2022-04-12 11:13:05 +08:00
|
|
|
def average_color(*colors: ManimColor) -> Color:
|
2018-08-09 17:56:05 -07:00
|
|
|
rgbs = np.array(list(map(color_to_rgb, colors)))
|
2020-02-19 23:43:33 -08:00
|
|
|
return rgb_to_color(rgbs.mean(0))
|
2018-03-30 18:19:23 -07:00
|
|
|
|
2018-04-06 13:58:59 -07:00
|
|
|
|
2022-04-12 11:13:05 +08:00
|
|
|
def random_color() -> Color:
|
|
|
|
return Color(rgb=tuple(np.random.random(3)))
|
2018-04-06 13:58:59 -07:00
|
|
|
|
2018-03-30 18:19:23 -07:00
|
|
|
|
2022-04-12 11:13:05 +08:00
|
|
|
def random_bright_color() -> Color:
|
|
|
|
color = random_color()
|
|
|
|
return average_color(color, Color(WHITE))
|
2018-08-15 16:23:29 -07:00
|
|
|
|
|
|
|
|
2022-04-12 11:13:05 +08:00
|
|
|
def get_colormap_list(
|
|
|
|
map_name: str = "viridis",
|
|
|
|
n_colors: int = 9
|
|
|
|
) -> np.ndarray:
|
2021-02-25 08:48:22 -08:00
|
|
|
"""
|
|
|
|
Options for map_name:
|
|
|
|
3b1b_colormap
|
|
|
|
magma
|
|
|
|
inferno
|
|
|
|
plasma
|
|
|
|
viridis
|
|
|
|
cividis
|
|
|
|
twilight
|
|
|
|
twilight_shifted
|
|
|
|
turbo
|
|
|
|
"""
|
2021-02-11 12:21:06 -08:00
|
|
|
from matplotlib.cm import get_cmap
|
|
|
|
|
2021-02-25 08:48:22 -08:00
|
|
|
if map_name == "3b1b_colormap":
|
|
|
|
rgbs = [color_to_rgb(color) for color in COLORMAP_3B1B]
|
|
|
|
else:
|
|
|
|
rgbs = get_cmap(map_name).colors # Make more general?
|
|
|
|
return resize_with_interpolation(np.array(rgbs), n_colors)
|