Skip to content
Color

Color

Mojo struct 🡭

Color

@memory_only
struct Color

An 8-bit-per-channel RGBA color. Two colors are equal when all four channels are, alpha included; there is no tolerance. Prints as Color(r, g, b, a), so a failed assert_equal on two colors says which channel differed.

Fields

  • r (UInt8)
  • g (UInt8)
  • b (UInt8)
  • a (UInt8)

Implemented traits

AnyType, Copyable, Deinitable, Equatable, ImplicitlyCopyable, Movable, Writable

Methods

__init__

fn def __init__(out self, r: UInt8, g: UInt8, b: UInt8, a: UInt8 = UInt8(255))

An 8-bit-per-channel RGBA color.

Args:

  • r (UInt8): Red channel, 0-255.
  • g (UInt8): Green channel, 0-255.
  • b (UInt8): Blue channel, 0-255.
  • a (UInt8): Alpha channel, 0-255, 255 fully opaque.
  • self (Self)

Returns:

Self

fn def __init__(out self, hex: String)

A color from a CSS-style hex string: "#rrggbb" or "#rrggbbaa", with or without the leading #, in either case. Digits are two per channel; the 3-digit #rgb shorthand is not accepted.

Args:

  • hex (String): "#rrggbb" or "#rrggbbaa". Alpha defaults to fully opaque when the string carries only six digits.
  • self (Self)

Returns:

Self

Raises:

Error: hex is not 6 or 8 hex digits, or contains a character that is not one.

__eq__

fn def __eq__(self, other: Self) -> Bool

Whether every channel matches, alpha included.

Exact on purpose: the caller merging same-colored cells into one rectangle needs identity, and “close enough” would blur a real boundary between two values. A caller who wants a tolerance writes one against the channels.

Args:

  • self (Self)
  • other (Self): The color to compare against.

Returns:

Bool: True when r, g, b and a all match.

__ne__

fn def __ne__(self, other: Self) -> Bool

Args:

  • self (Self)
  • other (Self)

Returns:

Bool

write_to

fn def write_to[W: Writer](self, mut writer: W)

Parameters:

  • W (Writer)

Args:

  • self (Self)
  • writer (W)

with_alpha

fn def with_alpha(self, a: UInt8) -> Self

This color at a different alpha, its channels untouched – the usual way a palette entry is faded for a hover state or a de-emphasized series.

Args:

  • self (Self)
  • a (UInt8): Alpha channel for the result, 0-255.

Returns:

Self: The same r/g/b at alpha a.

to_hex

fn def to_hex(self) -> String

This color as "#rrggbb", lowercase.

Alpha is not included: the two consumers of a hex string here, SVG and CSS, both carry opacity in a separate attribute, and svg.mojo writes self.a into one. Read .a for it.

Args:

  • self (Self)

Returns:

String: "#rrggbb".

blend_over

fn def blend_over(self, bg: Self) -> Self

Alpha-composite self over bg (straight-alpha src-over).

Correct for a translucent background as well as an opaque one: a Canvas stores per-pixel alpha, so a caller drawing onto a transparent-background canvas composites onto pixels that are themselves partly transparent.

Args:

  • self (Self)
  • bg (Self): Background color self is composited onto.

Returns:

Self: The composited color.

blend_over_opaque

fn def blend_over_opaque(self, bg_r: UInt8, bg_g: UInt8, bg_b: UInt8) -> Self

blend_over specialized to a background already known opaque. Canvas.write_pixel checks the destination alpha and calls this when it is 255, falling back to blend_over when it is not (see buffer.mojo).

With bg.a == 255 the general formula’s output alpha reduces to sa + (255 * inv) // 255 == sa + inv == 255, so the result is always fully opaque and the per-pixel division drops out. The caller passes the three background bytes it already read rather than packing them into a Color. The result is exactly what blend_over returns against Color(bg_r, bg_g, bg_b).

Args:

  • self (Self)
  • bg_r (UInt8): Background red channel.
  • bg_g (UInt8): Background green channel.
  • bg_b (UInt8): Background blue channel.

Returns:

Self: The composited color, always fully opaque.