From 2a0e05e228debbc38cfe46e1fbe08cf01535e700 Mon Sep 17 00:00:00 2001 From: "Azalea (on HyDEV-Daisy)" Date: Mon, 25 Jul 2022 21:02:10 -0400 Subject: [PATCH] [+] Create color scale without numpy --- hyfetch/color_scale.py | 47 +++++++++++++----------- hyfetch/color_scale_numpy.py | 71 ++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 21 deletions(-) create mode 100644 hyfetch/color_scale_numpy.py diff --git a/hyfetch/color_scale.py b/hyfetch/color_scale.py index e5b3616f..05347a49 100644 --- a/hyfetch/color_scale.py +++ b/hyfetch/color_scale.py @@ -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 -import numpy as np -from numpy import ndarray - 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 """ - 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) -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 for i in range(len(colors) - 1): - c1 = colors[i, :] - c2 = colors[i + 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) + for ri in range(resolution): + ratio = ri / resolution + 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 -def get_raw(gradient: ndarray, ratio: float) -> ndarray: +def get_raw(gradient: list[RGB], ratio: float) -> RGB: """ :param gradient: Gradient array (2d) :param ratio: Between 0-1 :return: RGB subarray (1d, has 3 values) """ if ratio == 1: - return gradient[-1, :] + return gradient[-1] i = int(ratio * len(gradient)) - return gradient[i, :] + return gradient[i] class Scale: - colors: ndarray - rgb: ndarray + colors: list[RGB] + rgb: list[RGB] 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) def __call__(self, ratio: float) -> RGB: """ :param ratio: Between 0-1 """ - return RGB(*get_raw(self.rgb, ratio)) + return get_raw(self.rgb, ratio) def test_color_scale(): diff --git a/hyfetch/color_scale_numpy.py b/hyfetch/color_scale_numpy.py new file mode 100644 index 00000000..e5b3616f --- /dev/null +++ b/hyfetch/color_scale_numpy.py @@ -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=' ')