[+] Create color scale without numpy

This commit is contained in:
Azalea (on HyDEV-Daisy) 2022-07-25 21:02:10 -04:00
parent 8d3a3cc7f0
commit 2a0e05e228
2 changed files with 97 additions and 21 deletions

View file

@ -1,66 +1,71 @@
"""
This version of color_scale is a special version made without numpy dependency. The numpy version
would be faster, but numpy is 11 MB large. In comparison, hyfetch 1.0.7 is only 105 kB, so it's not
a good idea to depend on numpy.
"""
from __future__ import annotations from __future__ import annotations
import numpy as np
from numpy import ndarray
from .color_util import RGB from .color_util import RGB
def create_gradient_hex(colors: list[str], resolution: int = 300) -> ndarray: def create_gradient_hex(colors: list[str], resolution: int = 300) -> list[RGB]:
""" """
Create gradient array from hex Create gradient array from hex
""" """
colors = np.array([RGB.from_hex(s) for s in colors]) colors = [RGB.from_hex(s) for s in colors]
return create_gradient(colors, resolution) return create_gradient(colors, resolution)
def create_gradient(colors: ndarray, resolution: int) -> ndarray: def create_gradient(colors: list[RGB], resolution: int) -> list[RGB]:
""" """
Create gradient 2d array. Create gradient array
Usage: arr[ratio / len(arr), :] = Scaled gradient color at that point Usage: arr[ratio / len(arr)] = Scaled gradient color at that point
""" """
result = np.zeros((resolution * (len(colors) - 1), 3), dtype='uint8') result = []
# Create gradient mapping # Create gradient mapping
for i in range(len(colors) - 1): for i in range(len(colors) - 1):
c1 = colors[i, :] c1 = colors[i]
c2 = colors[i + 1, :] c2 = colors[i + 1]
bi = i * resolution bi = i * resolution
for r in range(resolution): for ri in range(resolution):
ratio = r / resolution ratio = ri / resolution
result[bi + r, :] = c2 * ratio + c1 * (1 - ratio) r = int(c2.r * ratio + c1.r * (1 - ratio))
g = int(c2.g * ratio + c1.g * (1 - ratio))
b = int(c2.b * ratio + c1.b * (1 - ratio))
result.append(RGB(r, g, b))
return result return result
def get_raw(gradient: ndarray, ratio: float) -> ndarray: def get_raw(gradient: list[RGB], ratio: float) -> RGB:
""" """
:param gradient: Gradient array (2d) :param gradient: Gradient array (2d)
:param ratio: Between 0-1 :param ratio: Between 0-1
:return: RGB subarray (1d, has 3 values) :return: RGB subarray (1d, has 3 values)
""" """
if ratio == 1: if ratio == 1:
return gradient[-1, :] return gradient[-1]
i = int(ratio * len(gradient)) i = int(ratio * len(gradient))
return gradient[i, :] return gradient[i]
class Scale: class Scale:
colors: ndarray colors: list[RGB]
rgb: ndarray rgb: list[RGB]
def __init__(self, scale: list[str], resolution: int = 300): def __init__(self, scale: list[str], resolution: int = 300):
self.colors = np.array([RGB.from_hex(s) for s in scale]) self.colors = [RGB.from_hex(s) for s in scale]
self.rgb = create_gradient(self.colors, resolution) self.rgb = create_gradient(self.colors, resolution)
def __call__(self, ratio: float) -> RGB: def __call__(self, ratio: float) -> RGB:
""" """
:param ratio: Between 0-1 :param ratio: Between 0-1
""" """
return RGB(*get_raw(self.rgb, ratio)) return get_raw(self.rgb, ratio)
def test_color_scale(): def test_color_scale():

View file

@ -0,0 +1,71 @@
from __future__ import annotations
import numpy as np
from numpy import ndarray
from .color_util import RGB
def create_gradient_hex(colors: list[str], resolution: int = 300) -> ndarray:
"""
Create gradient array from hex
"""
colors = np.array([RGB.from_hex(s) for s in colors])
return create_gradient(colors, resolution)
def create_gradient(colors: ndarray, resolution: int) -> ndarray:
"""
Create gradient 2d array.
Usage: arr[ratio / len(arr), :] = Scaled gradient color at that point
"""
result = np.zeros((resolution * (len(colors) - 1), 3), dtype='uint8')
# Create gradient mapping
for i in range(len(colors) - 1):
c1 = colors[i, :]
c2 = colors[i + 1, :]
bi = i * resolution
for r in range(resolution):
ratio = r / resolution
result[bi + r, :] = c2 * ratio + c1 * (1 - ratio)
return result
def get_raw(gradient: ndarray, ratio: float) -> ndarray:
"""
:param gradient: Gradient array (2d)
:param ratio: Between 0-1
:return: RGB subarray (1d, has 3 values)
"""
if ratio == 1:
return gradient[-1, :]
i = int(ratio * len(gradient))
return gradient[i, :]
class Scale:
colors: ndarray
rgb: ndarray
def __init__(self, scale: list[str], resolution: int = 300):
self.colors = np.array([RGB.from_hex(s) for s in scale])
self.rgb = create_gradient(self.colors, resolution)
def __call__(self, ratio: float) -> RGB:
"""
:param ratio: Between 0-1
"""
return RGB(*get_raw(self.rgb, ratio))
def test_color_scale():
scale = Scale(['#232323', '#4F1879', '#B43A78', '#F98766', '#FCFAC0'])
colors = 100
for i in range(colors + 1):
print(scale(i / colors).to_ansi_rgb(False), end=' ')