3b1b-manim/manimlib/utils/color.py

111 lines
2.6 KiB
Python
Raw Normal View History

import random
from colour import Color
import numpy as np
from manimlib.constants import PALETTE
from manimlib.constants import WHITE
from manimlib.utils.bezier import interpolate
from manimlib.utils.simple_functions import clip_in_place
from manimlib.utils.space_ops import normalize
def color_to_rgb(color):
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")
def color_to_rgba(color, alpha=1):
2018-08-15 17:30:24 -07:00
return np.array([*color_to_rgb(color), alpha])
def rgb_to_color(rgb):
try:
return Color(rgb=rgb)
except:
return Color(WHITE)
def rgba_to_color(rgba):
return rgb_to_color(rgba[:3])
def rgb_to_hex(rgb):
2020-02-05 14:44:35 -08:00
return "#" + "".join(hex(int(255 * x))[2:] for x in rgb)
def hex_to_rgb(hex_code):
hex_part = hex_code[1:]
if len(hex_part) == 3:
hex_part = "".join([2 * c for c in hex_part])
return np.array([
int(hex_part[i:i + 2], 16) / 255
for i in range(0, 6, 2)
])
def invert_color(color):
return rgb_to_color(1.0 - color_to_rgb(color))
def color_to_int_rgb(color):
return (255 * color_to_rgb(color)).astype('uint8')
def color_to_int_rgba(color, opacity=1.0):
alpha = int(255 * opacity)
2020-02-13 12:03:54 -08:00
return np.array([*color_to_int_rgb(color), alpha])
def color_gradient(reference_colors, length_of_output):
if length_of_output == 0:
return reference_colors[0]
2018-08-09 17:56:05 -07:00
rgbs = list(map(color_to_rgb, reference_colors))
alphas = np.linspace(0, (len(rgbs) - 1), length_of_output)
floors = alphas.astype('int')
alphas_mod1 = alphas % 1
# End edge case
alphas_mod1[-1] = 1
floors[-1] = len(rgbs) - 2
return [
rgb_to_color(interpolate(rgbs[i], rgbs[i + 1], alpha))
for i, alpha in zip(floors, alphas_mod1)
]
def interpolate_color(color1, color2, alpha):
rgb = interpolate(color_to_rgb(color1), color_to_rgb(color2), alpha)
return rgb_to_color(rgb)
def average_color(*colors):
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))
def random_bright_color():
color = random_color()
curr_rgb = color_to_rgb(color)
new_rgb = interpolate(
curr_rgb, np.ones(len(curr_rgb)), 0.5
)
return Color(rgb=new_rgb)
def random_color():
return random.choice(PALETTE)
def get_shaded_rgb(rgb, point, unit_normal_vect, light_source):
2018-08-15 17:30:24 -07:00
to_sun = normalize(light_source - point)
factor = 0.5 * np.dot(unit_normal_vect, to_sun)**3
if factor < 0:
factor *= 0.5
result = rgb + factor
clip_in_place(rgb + factor, 0, 1)
return result