How do I work with colours?
← Getting Started · Ref: Q34
Colour is EK9's built-in type for RGB colour values with hex literal syntax. No imports needed. Uses British spelling 'Colour' consistently.
LITERALS
#FF0000 Pure red (6-digit RGB) #FF186276 With alpha (8-digit ARGB)
OUTPUT FORMATS
.RGB() returns '#RRGGBB', .RGBA() returns '#RRGGBBAA', .ARGB() returns '#AARRGGBB'.
HSL MANIPULATION
Immutable methods return NEW colours: withLightness(80), withSaturation(90), withHue(200). Access HSL values with .hue(), .saturation(), .lightness(). Control transparency with withOpaque(percentage).
COLOUR ARITHMETIC
Add/subtract to blend/remove RGB components (auto-clamped to 0-255):
purple <- #FF0000 + #0000FF
BITS INTEROP
.bits() extracts 32-bit ARGB value. Colour(bitsValue) constructs from Bits.
Comparison: ==, <>, <, >, <=, >=, <=>.
Use 'ek9 -h Colour' to see the full API.
See Q37 for string interpolation. See Q40 for Bits interop.
Example
defines module qa.colour defines program ColourDemo() stdout <- Stdout() // === COLOUR LITERALS === // Hex literal with alpha channel: #AARRGGBB (ARGB format) opaqueBlue <- #FF186276 stdout.println(`Opaque blue: ${opaqueBlue}`) // Hex literal without alpha: #RRGGBB (RGB format) pureRed <- #FF0000 pureGreen <- #00FF00 pureBlue <- #0000FF stdout.println(`Red: ${pureRed}, Green: ${pureGreen}, Blue: ${pureBlue}`) // Unset colour unsetColour <- Colour() require ~unsetColour? // === OUTPUT FORMATS === // Three different hex string formats stdout.println(`RGB: ${opaqueBlue.RGB()}`) stdout.println(`RGBA: ${opaqueBlue.RGBA()}`) stdout.println(`ARGB: ${opaqueBlue.ARGB()}`) // === HSL ACCESSORS === // Hue (0-360), Saturation (0-100%), Lightness (0-100%) stdout.println(`Hue: ${opaqueBlue.hue()}`) stdout.println(`Saturation: ${opaqueBlue.saturation()}`) stdout.println(`Lightness: ${opaqueBlue.lightness()}`) // === HSL MANIPULATION === // Each with* method returns a NEW colour (immutable) lighterBlue <- opaqueBlue.withLightness(80) stdout.println(`Lighter: ${lighterBlue}`) moreSaturated <- lighterBlue.withSaturation(90) stdout.println(`More saturated: ${moreSaturated}`) shiftedHue <- opaqueBlue.withHue(200) stdout.println(`Shifted hue: ${shiftedHue}`) // === ALPHA CHANNEL (TRANSPARENCY) === // withOpaque(percentage) sets opacity: 100=fully opaque, 0=fully transparent semiTransparent <- opaqueBlue.withOpaque(50) stdout.println(`50% opaque: ${semiTransparent}`) mostlyOpaque <- opaqueBlue.withOpaque(80) stdout.println(`80% opaque: ${mostlyOpaque}`) // === COLOUR ARITHMETIC === // Add colours: blends RGB components (clamped to 0-255) purple <- pureRed + pureBlue stdout.println(`Red + Blue = Purple: ${purple}`) yellow <- pureRed + pureGreen stdout.println(`Red + Green = Yellow: ${yellow}`) cyan <- pureGreen + pureBlue stdout.println(`Green + Blue = Cyan: ${cyan}`) // Subtract colours: removes RGB components (clamped to 0) backToRed <- purple - pureBlue stdout.println(`Purple - Blue = Red: ${backToRed}`) require backToRed == pureRed backToGreen <- yellow - pureRed stdout.println(`Yellow - Red = Green: ${backToGreen}`) require backToGreen == pureGreen // Subtract specific amounts of a channel lessRed <- moreSaturated - #9A0000 stdout.println(`Less red: ${lessRed}`) moreBlue <- lessRed + #00001D stdout.println(`More blue: ${moreBlue}`) // === BITS INTEROP === // Convert Colour to Bits and back colourBits <- opaqueBlue.bits() stdout.println(`As bits: ${colourBits}`) fromBits <- Colour(colourBits) require fromBits == opaqueBlue // Build colour from raw bit patterns redBits <- 0b11111111111111110000000000000000 redFromBits <- Colour(redBits) stdout.println(`Red from bits: ${redFromBits}`) // === PROGRAMMATIC LIGHTENING === // Calculate a percentage lighter currentLightness <- opaqueBlue.lightness() proposedLightness <- currentLightness * 1.9 clampedLightness <- proposedLightness <? 100 percentLighter <- opaqueBlue.withLightness(clampedLightness) stdout.println(`90% lighter: ${percentLighter}`) // === COMPARISON === require pureRed <> pureBlue require #FF0000 == #FF0000 stdout.println(`Red == Red: ${pureRed == #FF0000}`)
Common mistakes
E50060 — EK9 Colour uses 'withLightness' not 'setLightness'. Methods return new immutable values rather than mutating. Check available methods with 'ek9 -h Colour'. See ek9 -h E50060 for details.
Incorrect:
opaqueBlue.setLightness(80)
Correct:
opaqueBlue.withLightness(80)
Other ways to ask this
- Does EK9 have a built-in colour type?
- How do I manipulate RGB colours in EK9?
- How does HSL colour manipulation work in EK9?
- How do I blend colours in EK9?
Coming from another language?
Java: java.awt.Color tied to AWT, no literals, no HSL. CSS: #hex but declarative only. Python/Rust/Go/JS: no built-in colour type. EK9: built-in #RRGGBB literals, HSL methods, colour arithmetic with clamping, Bits interop.
Keywords: saturation, start, blend, hsl, bits, rgba, argb, transparent, rgb, colour, color, alpha, intro, hex, first, hue, migrate, opacity, beginner, lightness