fluttersmith/py-snippetsGitHub ↗

Convert between hex colours and RGB

Parse #RRGGBB and #RGB colours into (r, g, b), and format them back.

Strings#conversionO(1) time✓ 4 examples pass on 3.11–3.14

Design tokens are hex, maths on colours wants numbers.

hex_rgb.py✓ ruff · mypy --strict
def hex_to_rgb(color: str) -> tuple[int, int, int]:
    """Convert ``"#RRGGBB"`` or ``"RGB"`` shorthand to an ``(r, g, b)`` tuple."""
    digits = color.removeprefix("#")
    if len(digits) == 3:
        digits = "".join(c * 2 for c in digits)
    if len(digits) != 6:
        raise ValueError(f"expected 3 or 6 hex digits, got {color!r}")
    value = int(digits, 16)
    return value >> 16, (value >> 8) & 0xFF, value & 0xFF


def rgb_to_hex(r: int, g: int, b: int) -> str:
    """Convert red, green and blue (each 0-255) to ``"#RRGGBB"``."""
    if not all(0 <= c <= 255 for c in (r, g, b)):
        raise ValueError(f"channels must be 0-255, got {(r, g, b)}")
    return f"#{r:02X}{g:02X}{b:02X}"
  1. "0af" is shorthand for "00aaff"
  2. 02X: two uppercase hex digits, zero-padded
examples✓ 4 doctests · 3.11–3.14
passed on Python 3.11 to 3.14: >>> hex_to_rgb("#FFA501")(255, 165, 1)passed on Python 3.11 to 3.14: >>> hex_to_rgb("0af")(0, 170, 255)passed on Python 3.11 to 3.14: >>> rgb_to_hex(255, 165, 1)'#FFA501'passed on Python 3.11 to 3.14: >>> rgb_to_hex(256, 0, 0)Traceback (most recent call last):...ValueError: channels must be 0-255, got (256, 0, 0)
Edit the function or the examples and run the doctests here, on Python 3.14. Python loads only when you click (about 7 MB, cached after the first time).

How it works

  • removeprefix('#') drops an optional leading #.
  • Three-digit shorthand doubles each digit: 0af is 00aaff.
  • int(digits, 16) parses all six digits at once; shifts and masks pull out each channel.
  • :02X formats a channel as two uppercase hex digits.

Complexity: O(1) time and space

Importfrom pysnippets.strings.hex_rgb import hex_to_rgb, rgb_to_hexNo dependencies: copy hex_rgb.py into your project, or clone the repo.

Adapted from hex-to-rgb and rgb-to-hex in 30-seconds-of-python by the 30 seconds of code contributors, CC BY 4.0. Changed: Merged both directions; accepts # and 3-digit shorthand; validates input; typed. Suggest an edit.