Source code for veditor.utils.color_utils

# coding: utf-8
import math

from .generic_utils import handleTypeError

SUPPORTED_COLOR_CODES = ["hex", "rgb", "rgba"]


[docs]def detect_color_code_type(color): """Detect Color Code type Args: color (tuple / str): color code. Examples: >>> from pycharmers.utils import detect_color_code_type >>> detect_color_code_type("#FFFFFF") 'hex' >>> detect_color_code_type((255,255,255)) 'rgb' >>> detect_color_code_type((0,0,0,1)) 'rgba' """ handleTypeError(types=[str, tuple, list], color=color) if isinstance(color, str): color_code = "hex" elif isinstance(color, tuple) or isinstance(color, list): color_code = { 3: "rgb", 4: "rgba", }.get(len(color)) return color_code
[docs]def hex2rgb(hex, max_val=1): """Convert color code from ``hex`` to ``rgb``""" return tuple( [int(hex[-6:][i * 2 : (i + 1) * 2], 16) / 255 * max_val for i in range(3)] )
[docs]def hex2rgba(hex, max_val=1): """Convert color code from ``hex`` to ``rgba``""" return rgb2rgba(rgb=hex2rgb(hex=hex[-6:], max_val=max_val), max_val=max_val)
[docs]def rgb2hex(rgb, max_val=1): """Convert color code from ``rgb`` to ``hex``""" return "#" + "".join([format(int(255 / max_val * e), "02x") for e in rgb]).upper()
[docs]def rgb2rgba(rgb, max_val=1): """Convert color code from ``rgb`` to ``rgba``""" return (*rgb, 1)
[docs]def rgba2hex(rgba, max_val=1): """Convert color code from ``rgba`` to ``hex``""" return rgb2hex(rgb=rgba2rgb(rgba=rgba, max_val=max_val), max_val=max_val)
[docs]def rgba2rgb(rgba, max_val=1): """Convert color code from ``rgba`` to ``rgb``""" alpha = rgba[-1] rgb = rgba[:-1] type_ = int if max_val == 255 else float # compute the color as alpha against white return tuple([type_(alpha * e + (1 - alpha) * max_val) for e in rgb])
def _do_nothing(color, max_val=1): return color def _toColorCode_create(to_color_code): def toColorCode(color, max_val=1): color_code = detect_color_code_type(color=color) return { color_code: globals().get( f"{color_code}2{to_color_code.lower()}", _do_nothing ) for color_code in SUPPORTED_COLOR_CODES }.get(color_code)(color, max_val=max_val) toColorCode.__doc__ = f"""Convert color code to {to_color_code.upper()} Args: color (tuple / str): color code. Examples: >>> from pycharmers.utils import to{to_color_code.upper()} >>> to{to_color_code.upper()}("#FFFFFF") {toColorCode("#FFFFFF")} >>> to{to_color_code.upper()}((255, 255, 255), max_val=255) {toColorCode((255, 255, 255), max_val=255)} >>> to{to_color_code.upper()}((1, 1, 1, 1), max_val=1) {toColorCode((1, 1, 1, 1), max_val=1)} """ return toColorCode toHEX = _toColorCode_create("hex") toRGB = _toColorCode_create("rgb") toRGBA = _toColorCode_create("rgba")
[docs]def choose_text_color(color, max_val=255, is_bgr=False): """Select an easy-to-read text color from the given color. Args: color (tuple / str) : color code. max_val (int) : Maximum value. References: `WCAG <https://www.w3.org/TR/WCAG20/#relativeluminancede>`_ Examples: >>> from pycharmers.utils import choose_text_color >>> from pycharmers.opencv import (cv2BLACK, cv2RED, cv2GREEN, cv2YELLOW, cv2BLUE, cv2MAGENTA, cv2CYAN, cv2WHITE) >>> colors = locals().copy() >>> for name,color in colors.items(): ... if name.startswith("cv2") and isinstance(color, tuple): ... print(f"{name.lstrip('cv2'):<7}: {str(color):<15} -> {choose_text_color(color=color, max_val=255, is_bgr=True)}") """ color_code = detect_color_code_type(color=color) rgb = toRGB(color=color, max_val=max_val) if is_bgr: rgb = rgb[::-1] def sRGB2RGB(e): i = e / max_val return i / 12.92 if i <= 0.03928 else math.pow((i + 0.055) / 1.055, 2.4) R, G, B = [sRGB2RGB(e) for e in rgb] # Relative Brightness BackGround. Lbg = 0.2126 * R + 0.7152 * G + 0.0722 * B Lw = 1 # Relative Brightness of White Lb = 0 # Relative Brightness of Black Cw = (Lw + 0.05) / (Lbg + 0.05) Cb = (Lbg + 0.05) / (Lb + 0.05) text_rgb = (0, 0, 0) if Cb > Cw else (max_val, max_val, max_val) return {"rgb": _do_nothing, "hex": rgb2hex, "rgba": _do_nothing,}.get( color_code )(text_rgb, max_val=max_val)
[docs]def generate_color_series(color, variation, diff=10, reverse=False): """Generate light and dark color series. Args: color (tuple) : Color [0,255] variation (int) : How many colors to create. diff (int) : How much to change reverse (bool) : If ``True``, sort in descending order. Returns: colors (list) : colors. Examples: >>> from pycharmers.utils import generateLightDarks >>> generateLightDarks(color=(245,20,25), variation=3, diff=10) [(235, 10, 15), (245, 20, 25), (255, 30, 35)] >>> generateLightDarks(color=(245, 20, 25), variation=3, diff=-10) [(225, 0, 5), (235, 10, 15), (245, 20, 25)] """ val = max(color[:3]) if diff > 0 else min(color[:3]) u = 0 for _ in range(variation - 1): val += diff if not 255 >= val >= 0: break u += 1 return sorted( [ tuple( [ max(min(e + diff * (u - v), 255), 0) if i < 3 else e for i, e in enumerate(color) ] ) for v in range(variation) ], reverse=reverse, )