|
@@ -0,0 +1,70 @@
|
|
|
+from __future__ import annotations
|
|
|
+
|
|
|
+import numpy as np
|
|
|
+from .color_util import RGB
|
|
|
+from numpy import ndarray
|
|
|
+
|
|
|
+
|
|
|
+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))
|
|
|
+
|
|
|
+
|
|
|
+if __name__ == '__main__':
|
|
|
+ scale = Scale(['#232323', '#4F1879', '#B43A78', '#F98766', '#FCFAC0'])
|
|
|
+
|
|
|
+ colors = 100
|
|
|
+ for i in range(colors + 1):
|
|
|
+ print(scale(i / colors).to_ansi_rgb(False), end=' ')
|