Source code for console.proximity

'''
    .. console - Comprehensive utility library for ANSI terminals.
    .. © 2018, Mike Miller - ADDITIONAL PORTIONS released under the LGPL 3+.

    Given an (3x) 8-bit RGB color,
    find the closest extended 8-bit terminal color index.

    Nearest-color algorithm derived from:

    .. code-block:: text

        pygments.formatters.terminal256
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

        Formatter for 256-color terminal output with ANSI sequences.

        RGB-to-XTERM color conversion routines adapted from xterm256-conv
        tool (http://frexx.de/xterm-256-notes/data/xterm256-conv2.tar.bz2)
        by Wolfgang Frisch.

        :copyright: Copyright 2006-2017 by the Pygments team, see AUTHORS.
        :license: BSD, see LICENSE for details.

    Note:
        An experiment was done using a more accurate CIELAB distance algorithm,
        but the solution was quite heavy and therefore removed.
'''
from . import color_tables


color_table4 = []   # 16 colors
color_table8 = []   # 265 colors


def _build_color_table(base, extended=True):
    # start with first 16 colors
    color_table = []
    color_table.extend(base)  # handle tuples

    if extended:
        # colors 16..232: the 6x6x6 color cube
        valuerange = (0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff)

        for i in range(217):
            r = valuerange[(i // 36) % 6]
            g = valuerange[(i // 6) % 6]
            b = valuerange[i % 6]
            color_table.append((r, g, b))

        # colors 233..253: grayscale  # to 255!
        for i in range(1, 24):  # odd, this should go to 255, added 2 to range
            v = 8 + i * 10
            color_table.append((v, v, v))

    return color_table


[docs]def build_color_tables(base=color_tables.vga_palette4): ''' Create the color tables for palette downgrade support, starting with the platform-specific 16 from the color tables module. Save as global state. :-/ ''' base = [] if base is None else base # make sure we have them before clearing table4 = _build_color_table(base, extended=False) if table4: color_table4.clear() color_table4.extend(table4) table8 = _build_color_table(base) if table8: color_table8.clear() color_table8.extend(table8)
[docs]def find_nearest_color_index(r, g, b, color_table=None, method='euclid'): ''' Given three integers representing R, G, and B, return the nearest color index. Arguments: r: int - of range 0…255 g: int - of range 0…255 b: int - of range 0…255 Returns: int, None: index, or None on error. ''' shortest_distance = 257*257*3 # max eucl. distance from #000000 to #ffffff index = 0 # default to black if not color_table: if not color_table8: build_color_tables() color_table = color_table8 for i, values in enumerate(color_table): rd = r - values[0] gd = g - values[1] bd = b - values[2] this_distance = (rd * rd) + (gd * gd) + (bd * bd) if this_distance < shortest_distance: # closer index = i shortest_distance = this_distance return index
[docs]def find_nearest_color_hexstr(hexdigits, color_table=None, method='euclid'): ''' Given a three or six-character hex digit string, return the nearest color index. Arguments: hexdigits: a three/6 digit hex string, e.g. 'b0b', '123456' Returns: int, None: index, or None on error. ''' triplet = [] try: if len(hexdigits) == 3: for digit in hexdigits: digit = int(digit, 16) triplet.append((digit * 16) + digit) elif len(hexdigits) == 6: triplet.extend(int(hexdigits[i:i+2], 16) for i in (0, 2, 4)) else: raise ValueError('wrong length: %r' % hexdigits) except ValueError: return None return find_nearest_color_index(*triplet, color_table=color_table, method=method)