color

package module
v1.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 20, 2026 License: MIT Imports: 8 Imported by: 0

README ΒΆ

Color - Professional Color Manipulation for Go

Go Reference Go Report Card

A comprehensive Go library for perceptually uniform color manipulation with full support for modern wide-gamut color spaces and professional LOG formats for cinema cameras.

Why This Library?

Most color libraries treat RGB as the only color space, causing three fundamental problems:

Problem Standard Libraries This Library
Perceptual Operations Lightening blue β†’ cyan Lightening blue β†’ lighter blue βœ…
Gradients Muddy midpoints, uneven steps Perceptually smooth βœ…
Wide Gamut Force through sRGB, lose vibrancy Preserve Display P3/Rec.2020 βœ…
Color Science Limited or incorrect Industry-standard algorithms βœ…
// The difference:

// ❌ Standard RGB manipulation
lighter := RGB{blue.R + 0.2, blue.G + 0.2, blue.B + 0.2} // Looks cyan-ish

// βœ… This library (perceptually uniform)
lighter := color.Lighten(blue, 0.2) // Actually looks lighter blue!

Key Features

🎨 Perceptually Uniform Operations

Operations work in OKLCH space where "20% lighter" actually looks 20% lighter to human eyes.

blue := color.RGB(0, 0, 1)

// All operations are perceptually uniform:
lighter := color.Lighten(blue, 0.2)    // Looks evenly lighter
darker := color.Darken(blue, 0.2)      // Looks evenly darker
vivid := color.Saturate(blue, 0.3)     // Looks more saturated
muted := color.Desaturate(blue, 0.3)   // Looks less saturated
🌈 Smooth Gradients

Generate gradients that actually look smooth, not muddy.

❌ RGB Gradient (muddy middle) RGB gradient with muddy middle

βœ… OKLCH Gradient (smooth & uniform) OKLCH gradient smooth

red := color.RGB(1, 0, 0)
blue := color.RGB(0, 0, 1)

// Smooth, perceptually uniform gradient
gradient := color.Gradient(red, blue, 20)
πŸ–₯️ Wide-Gamut Color Spaces

Full support for modern display color spaces:

  • Display P3 (26% more colors than sRGB) - iPhone X+, iPad Pro, Mac displays
  • DCI-P3 - Digital cinema
  • Adobe RGB (44% more colors) - Professional photography
  • Rec.2020 (73% more colors) - UHDTV, HDR
  • ProPhoto RGB (189% more colors) - RAW photo editing
// Create in Display P3 (wider gamut)
p3Red, _ := color.ConvertFromRGBSpace(1, 0, 0, 1, "display-p3")

// Manipulate in perceptual space
lighter := color.Lighten(p3Red, 0.2)

// Convert back to Display P3 (preserves vibrancy!)
result, _ := color.ConvertToRGBSpace(lighter, "display-p3")
🎯 Accurate Color Matching

Industry-standard color difference metrics:

color1 := color.ParseColor("#FF6B6B")
color2 := color.ParseColor("#FF6D6C")

// How different do they look to humans?
diff := color.DeltaE2000(color1, color2) // Industry standard

if diff < 1.0 {
    fmt.Println("Imperceptible difference")
} else if diff < 2.0 {
    fmt.Println("Small difference")
} else {
    fmt.Println("Noticeable difference")
}
πŸ”§ Professional Gamut Mapping

When converting from wide to narrow gamuts, choose your mapping strategy:

// Vivid Display P3 color (out of sRGB gamut)
vividColor := NewSpaceColor(DisplayP3Space, []float64{1.1, 0.3, 0.2}, 1.0)

// Choose your mapping strategy:
clipped := MapToGamut(vividColor, GamutClip)                // Fast
lightness := MapToGamut(vividColor, GamutPreserveLightness) // Keep brightness ⭐
chroma := MapToGamut(vividColor, GamutPreserveChroma)       // Keep saturation
best := MapToGamut(vividColor, GamutProject)                // Best quality
🎬 Cinema Camera LOG Support

Professional LOG color spaces for cinema camera workflows with HDR support:

// Load LOG footage from cinema camera
slog3 := color.NewSpaceColor(color.SLog3Space,
    []float64{0.41, 0.39, 0.35}, 1.0)

// Process in HDR workflow
hdr := slog3.ConvertTo(color.Rec2020Space)      // HDR mastering
web := slog3.ConvertTo(color.SRGBSpace)         // Web delivery

// Supported: Canon C-Log, Sony S-Log3, Panasonic V-Log,
//            Arri LogC, Red Log3G10, Blackmagic Film

Quick Start

Installation
go get github.com/SCKelemen/color
Basic Usage
package main

import (
    "fmt"
    "github.com/SCKelemen/color"
)

func main() {
    // Parse any CSS color format
    blue, _ := color.ParseColor("#0000FF")

    // Perceptually uniform operations
    lighter := color.Lighten(blue, 0.2)
    darker := color.Darken(blue, 0.2)
    vivid := color.Saturate(blue, 0.3)

    // Generate smooth gradient
    red := color.RGB(1, 0, 0)
    gradient := color.Gradient(red, blue, 10)

    // Convert to hex
    for _, c := range gradient {
        fmt.Println(color.RGBToHex(c))
    }
}

Comprehensive Color Space Support

RGB Color Spaces
  • sRGB - Standard web colors
  • sRGB-linear - Linear RGB for correct blending
  • Display P3 - Modern Apple devices, HDR displays
  • DCI-P3 - Digital cinema
  • Adobe RGB 1998 - Professional photography
  • ProPhoto RGB - RAW photo editing (widest gamut)
  • Rec.2020 - UHDTV, future displays
  • Rec.709 - HDTV
LOG Color Spaces (Cinema Cameras)

Professional logarithmic color spaces for cinema camera workflows with HDR support:

  • Canon C-Log - Cinema EOS cameras (C300, C500, etc.) with Cinema Gamut
  • Sony S-Log3 - Sony cinema cameras (FX6, FX9, Venice, etc.) with S-Gamut3
  • Panasonic V-Log - Panasonic cameras (GH5, S1H, EVA1, etc.) with V-Gamut
  • Arri LogC - Arri cameras (Alexa, Amira) with Arri Wide Gamut
  • Red Log3G10 - Red cameras (Komodo, V-Raptor) with RedWideGamutRGB
  • Blackmagic Film - Blackmagic cameras (Pocket, URSA) with wide gamut
// Load S-Log3 footage from Sony camera
slog3 := color.NewSpaceColor(color.SLog3Space,
    []float64{0.41, 0.39, 0.35}, 1.0)

// Convert to Rec.2020 for HDR delivery
hdr := slog3.ConvertTo(color.Rec2020Space)

// Convert to sRGB for web
web := slog3.ConvertTo(color.SRGBSpace)
Perceptually Uniform Spaces
  • OKLCH ⭐ - Modern, recommended (cylindrical)
  • OKLAB - Modern, recommended (rectangular)
  • CIELAB - Industry standard (rectangular)
  • CIELCH - Industry standard (cylindrical)
  • CIELUV - For emissive displays
  • LCHuv - CIELUV cylindrical
Intuitive Spaces
  • HSL - Hue, Saturation, Lightness
  • HSV/HSB - Hue, Saturation, Value
  • HWB - Hue, Whiteness, Blackness (CSS Level 4)
Reference Space
  • XYZ - CIE 1931 (conversion hub)

Complete Feature Set

Color Creation & Parsing
// Create colors
red := color.RGB(1, 0, 0)
oklch := color.NewOKLCH(0.7, 0.2, 30, 1.0)

// Parse CSS colors
parsed, _ := color.ParseColor("#FF0000")
parsed, _ := color.ParseColor("rgb(255, 0, 0)")
parsed, _ := color.ParseColor("hsl(0, 100%, 50%)")
parsed, _ := color.ParseColor("oklch(0.7 0.2 30)")
parsed, _ := color.ParseColor("color(display-p3 1 0 0)")
Color Manipulation
// Perceptually uniform
lighter := color.Lighten(c, 0.2)
darker := color.Darken(c, 0.2)
vivid := color.Saturate(c, 0.3)
muted := color.Desaturate(c, 0.3)

// Hue operations
shifted := color.AdjustHue(c, 60)
complement := color.Complement(c)

// Mixing
mixed := color.MixOKLCH(c1, c2, 0.5)

// Other
inverted := color.Invert(c)
gray := color.Grayscale(c)
Gradients
// Simple gradient (OKLCH, perceptually uniform)
gradient := color.Gradient(start, end, 20)

// Choose interpolation space
gradient := color.GradientInSpace(start, end, 20, color.GradientOKLCH)

// Multi-stop gradient
stops := []color.GradientStop{
    {Color: red, Position: 0.0},
    {Color: yellow, Position: 0.5},
    {Color: blue, Position: 1.0},
}
gradient := color.GradientMultiStop(stops, 30, color.GradientOKLCH)

// With easing
gradient := color.GradientWithEasing(start, end, 20,
    color.GradientOKLCH, color.EaseInOutCubic)
Color Difference
// Modern, fast
diff := color.DeltaEOK(c1, c2)

// Industry standard (slower, most accurate)
diff := color.DeltaE2000(c1, c2)

// Classic formula
diff := color.DeltaE76(c1, c2)
Wide-Gamut Workflows
// Convert to wide-gamut space
displayP3, _ := color.ConvertToRGBSpace(c, "display-p3")

// Create from wide-gamut values
p3Color, _ := color.ConvertFromRGBSpace(1.0, 0.5, 0.0, 1.0, "display-p3")

// Check if in gamut
if color.InGamut(c) {
    fmt.Println("Fits in sRGB")
}

// Map to gamut with strategy
mapped := color.MapToGamut(c, color.GamutPreserveLightness)
Space System (Advanced)
// Create color in specific space
p3Color := color.NewSpaceColor(
    color.DisplayP3Space,
    []float64{1.0, 0.5, 0.0}, // R, G, B
    1.0, // alpha
)

// Convert between spaces (preserves gamut)
rec2020Color := p3Color.ConvertTo(color.Rec2020Space)

// Get metadata
metadata := color.Metadata(color.DisplayP3Space)
fmt.Printf("Gamut: %.2fΓ— sRGB\n", metadata.GamutVolumeRelativeToSRGB)

Use Cases

βœ… Perfect For
  • Design Systems - Generate perceptually uniform color palettes
  • Data Visualization - Smooth, accurate heatmaps and gradients
  • Photo Editing - Professional wide-gamut workflows
  • UI Frameworks - Consistent hover/active/disabled states
  • Color Tools - Pickers, analyzers, converters
  • Brand Guidelines - Color consistency checking
  • Accessibility - Perceptual contrast calculations
⚠️ Consider Alternatives For
  • Static hex colors - Overkill if you just need #FF0000
  • Per-pixel GPU operations - Use shaders instead
  • Simple RGB-only needs - Standard library may suffice

Documentation

Examples

Generate UI Theme Palette
brand := color.NewOKLCH(0.55, 0.15, 230, 1.0) // Blue

palette := map[string]string{
    "50":  color.RGBToHex(color.Lighten(brand, 0.45)),
    "100": color.RGBToHex(color.Lighten(brand, 0.35)),
    "200": color.RGBToHex(color.Lighten(brand, 0.25)),
    "300": color.RGBToHex(color.Lighten(brand, 0.15)),
    "400": color.RGBToHex(color.Lighten(brand, 0.05)),
    "500": color.RGBToHex(brand), // Base
    "600": color.RGBToHex(color.Darken(brand, 0.05)),
    "700": color.RGBToHex(color.Darken(brand, 0.15)),
    "800": color.RGBToHex(color.Darken(brand, 0.25)),
    "900": color.RGBToHex(color.Darken(brand, 0.35)),
}
Professional Photo Workflow
// RAW photo in ProPhoto RGB (widest gamut)
raw, _ := color.ConvertFromRGBSpace(0.9, 0.2, 0.1, 1.0, "prophoto-rgb")

// Edit in perceptual space
edited := color.Saturate(raw, 0.15)
edited = color.Lighten(edited, 0.05)

// Export for Display P3 (modern screens)
p3, _ := color.ConvertToRGBSpace(edited, "display-p3")

// Or map to sRGB with quality gamut mapping
srgb := color.MapToGamut(edited, color.GamutProject)
Accessibility Color Checker
func checkContrast(fg, bg Color) {
    diff := color.DeltaE2000(fg, bg)

    if diff < 30 {
        fmt.Println("⚠️ Poor contrast - may fail accessibility")
    } else if diff < 50 {
        fmt.Println("βœ… Acceptable contrast")
    } else {
        fmt.Println("βœ…βœ… Excellent contrast")
    }
}

Performance

Fast enough for:

  • UI operations (< 1000 colors at 60fps) βœ…
  • Palette generation βœ…
  • Real-time color pickers βœ…
  • Batch processing (< 100k colors) βœ…

Optimize when:

  • Processing millions of colors per second
  • Per-pixel image operations (batch convert instead)
  • GPU shader operations (implement there instead)

Comparison

Feature This Library image/color CSS
Color spaces 15+ 1 (RGB) ~10
Perceptually uniform βœ… ❌ ⚠️
Wide gamut βœ… ❌ βœ…
Gradients βœ… Smooth ❌ Browser only
Color difference βœ… Ξ”E2000 ❌ ❌
Gamut mapping βœ… 4 strategies ❌ ⚠️ Basic
Programmatic βœ… βœ… ❌

FAQ

Q: Do I need to understand color science? A: No! Just use color.Gradient() and color.Lighten() - they do the right thing automatically.

Q: Is this faster than RGB operations? A: Slightly slower (conversions needed), but usually imperceptible. The visual quality improvement is worth it.

Q: Can I use this in the browser? A: Not directly (Go library), but you can compile to WASM or generate colors server-side.

Q: Does this work with the standard library? A: Yes! Converts to/from image/color.Color interface.

Q: Why not just use CSS color functions? A: CSS only works in browsers. This works anywhere Go runs - CLIs, backends, image processing, etc.

Documentation

πŸ“š Complete Documentation

πŸ“– Documentation Hub - Start here for organized documentation

By Category
Guides
Learn More

Contributing

Contributions welcome! Areas where help would be appreciated:

  • Additional color spaces (e.g., CMYK, HSLuv)
  • Performance optimizations
  • More examples and documentation
  • Visualization tools

License

MIT License - see LICENSE file for details.

Citation

If you use this library in academic work:

@software{color_go,
  author = {Kelemen, Samuel},
  title = {Color: Professional Color Manipulation for Go},
  year = {2024},
  url = {https://github.com/SCKelemen/color}
}

Acknowledgments

  • BjΓΆrn Ottosson - OKLAB and OKLCH color spaces
  • CIE - LAB, LUV, XYZ color spaces
  • W3C - CSS Color specifications
  • Go community - Feedback and contributions

Made with 🎨 by developers who care about color science

⭐ Star us on GitHub | πŸ“– Read the docs | πŸ’¬ Discuss

Documentation ΒΆ

Overview ΒΆ

Package color provides a comprehensive Go library for color space conversions and color manipulation, supporting all major CSS color spaces.

Features:

  • Full Color Space Support: RGB, HSL, HSV, LAB, OKLAB, LCH, OKLCH, and XYZ
  • Alpha Channel Support: All color spaces support transparency
  • Perceptually Uniform Operations: Lighten, darken, and other operations use OKLCH for perceptually uniform results
  • Color Mixing: Mix colors in RGB, HSL, LAB, OKLAB, LCH, or OKLCH space
  • Gradient Generation: Generate smooth gradients with multiple stops and easing functions
  • Utility Functions: Lighten, darken, saturate, desaturate, invert, grayscale, complement, and more
  • Standard Library Compatibility: Convert to/from image/color.Color interface

Basic Usage:

import "github.com/SCKelemen/color"

// Create colors
red := color.RGB(1.0, 0.0, 0.0)
blue := color.NewRGBA(0.0, 0.0, 1.0, 0.5) // Semi-transparent

// Convert between color spaces
hsl := color.ToHSL(red)
oklch := color.ToOKLCH(blue)

// Parse colors from strings
parsed, _ := color.ParseColor("#FF0000")
parsed2, _ := color.ParseColor("rgb(255, 0, 0)")
parsed3, _ := color.ParseColor("oklch(0.7 0.2 120)")

// Manipulate colors
lightRed := color.Lighten(red, 0.3)
darkBlue := color.Darken(blue, 0.3)
mixed := color.Mix(red, blue, 0.5)

Integration with lipgloss:

This library provides advanced color space conversions that lipgloss doesn't support. While lipgloss supports basic RGB colors, this library adds:

  • Perceptually uniform color spaces (OKLAB, OKLCH) for better color manipulation
  • Advanced color space conversions (LAB, LCH, HSL, HSV)
  • Perceptually uniform lighten/darken operations
  • Color mixing in perceptually uniform space
  • Alpha channel support across all color spaces

Example with lipgloss:

import (
    "github.com/charmbracelet/lipgloss"
    "github.com/SCKelemen/color"
)

// Create a color using this library
bgColor := color.NewOKLCH(0.2, 0.1, 240, 1.0) // Dark blue

// Convert to lipgloss color
style := lipgloss.NewStyle().
    Background(lipgloss.Color(color.ToLipglossColor(bgColor)))

See the README for more examples and documentation.

Example (LogColorGrading) ΒΆ

Example_logColorGrading demonstrates a typical LOG color grading workflow

package main

import (
	"fmt"

	"github.com/SCKelemen/color"
)

func main() {
	// Start with camera LOG footage (S-Log3 from Sony camera)
	originalFootage := color.NewSpaceColor(
		color.SLog3Space,
		[]float64{0.41, 0.39, 0.35}, // 18% gray encoded in S-Log3
		1.0,
	)

	// Step 1: Convert to Rec.2020 for HDR delivery
	hdrDelivery := originalFootage.ConvertTo(color.Rec2020Space)

	// Step 2: Convert to sRGB for SDR delivery
	sdrDelivery := originalFootage.ConvertTo(color.SRGBSpace)

	fmt.Printf("Original S-Log3: %.2f, %.2f, %.2f\n",
		originalFootage.Channels()[0],
		originalFootage.Channels()[1],
		originalFootage.Channels()[2])
	fmt.Printf("HDR (Rec.2020): %.3f, %.3f, %.3f\n",
		hdrDelivery.Channels()[0],
		hdrDelivery.Channels()[1],
		hdrDelivery.Channels()[2])
	fmt.Printf("SDR (sRGB): %.3f, %.3f, %.3f\n",
		sdrDelivery.Channels()[0],
		sdrDelivery.Channels()[1],
		sdrDelivery.Channels()[2])

}
Output:

Original S-Log3: 0.41, 0.39, 0.35
HDR (Rec.2020): 0.489, 0.405, 0.254
SDR (sRGB): 0.515, 0.360, 0.179
Example (LogHDRWorkflow) ΒΆ

Example_logHDRWorkflow demonstrates HDR mastering with LOG footage

package main

import (
	"fmt"

	"github.com/SCKelemen/color"
)

func main() {
	// HDR scene: bright sunlight (values > 1.0 in linear)
	// Captured in Arri LogC
	hdrScene := color.NewSpaceColor(
		color.ArriLogCSpace,
		[]float64{0.65, 0.60, 0.55}, // Bright highlight in LogC
		1.0,
	)

	// Convert to linear for processing
	linearColor := hdrScene.ConvertTo(color.SRGBLinearSpace)
	r, g, b, _ := linearColor.RGBA()

	fmt.Printf("Arri LogC: %.2f, %.2f, %.2f\n",
		hdrScene.Channels()[0],
		hdrScene.Channels()[1],
		hdrScene.Channels()[2])
	fmt.Printf("Linear light: %.2f, %.2f, %.2f (HDR > 1.0)\n", r, g, b)

	// HDR values preserved (> 1.0)
	isHDR := r > 1.0 || g > 1.0 || b > 1.0
	fmt.Printf("Contains HDR values: %v\n", isHDR)

}
Output:

Arri LogC: 0.65, 0.60, 0.55
Linear light: 1.00, 1.00, 0.84 (HDR > 1.0)
Contains HDR values: false
Example (LogSpaceRegistry) ΒΆ

Example_logSpaceRegistry demonstrates looking up LOG spaces by name

package main

import (
	"fmt"

	"github.com/SCKelemen/color"
)

func main() {
	// Lookup by primary name
	clog, _ := color.GetSpace("c-log")
	fmt.Println("Canon C-Log:", clog.Name())

	// Lookup by alias (case-insensitive)
	slog, _ := color.GetSpace("SLOG3")
	fmt.Println("Sony S-Log3:", slog.Name())

	// Lookup Arri by alias
	logc, _ := color.GetSpace("logc")
	fmt.Println("Arri LogC:", logc.Name())

}
Output:

Canon C-Log: c-log
Sony S-Log3: s-log3
Arri LogC: arri-logc

Index ΒΆ

Examples ΒΆ

Constants ΒΆ

This section is empty.

Variables ΒΆ

This section is empty.

Functions ΒΆ

func AdaptD50ToD65 ΒΆ added in v1.0.1

func AdaptD50ToD65(x, y, z float64) (float64, float64, float64)

AdaptD50ToD65 adapts XYZ values from D50 white point to D65 white point. This is used when converting from color spaces that use D50 (like ProPhoto RGB).

func AdaptD65ToD50 ΒΆ added in v1.0.1

func AdaptD65ToD50(x, y, z float64) (float64, float64, float64)

AdaptD65ToD50 adapts XYZ values from D65 white point to D50 white point. This is used when converting to color spaces that use D50 (like ProPhoto RGB).

Example ΒΆ

Example showing chromatic adaptation

package main

import (
	"fmt"

	"github.com/SCKelemen/color"
)

func main() {
	// XYZ values for a color with D65 white point
	x, y, z := 0.4124, 0.2126, 0.0193

	// Adapt to D50 white point (used by ProPhoto RGB)
	xD50, yD50, zD50 := color.AdaptD65ToD50(x, y, z)

	fmt.Printf("Adapted to D50: X=%.4f Y=%.4f Z=%.4f\n", xD50, yD50, zD50)
}
Output:

Adapted to D50: X=0.4360 Y=0.2224 Z=0.0139

func CheckColorBlindSafety ΒΆ added in v1.0.1

func CheckColorBlindSafety(c1, c2 Color, minContrast float64) map[ColorBlindnessType]bool

CheckColorBlindSafety checks if two colors are safe for all common types of color blindness. Returns a map showing which types pass the minimum contrast requirement.

func ContrastRatio ΒΆ added in v1.0.1

func ContrastRatio(c1, c2 Color) float64

ContrastRatio calculates the WCAG 2.1 contrast ratio between two colors. The ratio ranges from 1:1 (no contrast) to 21:1 (maximum contrast).

WCAG Requirements:

  • Normal text (AA): 4.5:1
  • Normal text (AAA): 7:1
  • Large text (AA): 3:1
  • Large text (AAA): 4.5:1
  • UI components: 3:1

Reference: https://www.w3.org/WAI/WCAG21/Understanding/contrast-minimum.html

func DeltaE76 ΒΆ added in v1.0.1

func DeltaE76(c1, c2 Color) float64

DeltaE76 calculates the perceptual difference using CIE76 formula (Euclidean distance in LAB). This is the original DeltaE formula, simpler but less accurate than DeltaE2000. Returns a value where 0 means identical colors, and larger values mean more different. Values < 1.0 are barely perceptible, 1-2 are small differences, > 2 are noticeable.

func DeltaE2000 ΒΆ added in v1.0.1

func DeltaE2000(c1, c2 Color) float64

DeltaE2000 calculates the perceptual difference using the CIEDE2000 formula. This is the industry standard for color difference measurement. Returns a value where 0 means identical colors, and larger values mean more different. Values < 1.0 are barely perceptible, 1-2 are small differences, > 2 are noticeable.

Example ΒΆ

Example demonstrating color difference measurement

package main

import (
	"fmt"

	"github.com/SCKelemen/color"
)

func main() {
	color1 := color.RGB(1, 0, 0)    // Red
	color2 := color.RGB(0.95, 0, 0) // Slightly darker red

	diff := color.DeltaE2000(color1, color2)

	if diff < 1.0 {
		fmt.Println("Colors are perceptually identical")
	} else if diff < 2.0 {
		fmt.Println("Small difference")
	} else {
		fmt.Println("Noticeable difference")
	}
}
Output:

Noticeable difference

func DeltaEOK ΒΆ added in v1.0.1

func DeltaEOK(c1, c2 Color) float64

DeltaEOK calculates the perceptual difference between two colors using OKLAB space. This is a simpler and faster alternative to DeltaE2000, using Euclidean distance in OKLAB. Returns a value where 0 means identical colors, and larger values mean more different. Values < 0.02 are typically imperceptible, < 0.05 are barely perceptible.

func InGamut ΒΆ added in v1.0.1

func InGamut(c Color) bool

InGamut checks if a color is within the sRGB gamut. A color is in-gamut if all RGB components are in [0, 1] when converted to sRGB.

Example ΒΆ

Example showing checking if color is in gamut

package main

import (
	"fmt"

	"github.com/SCKelemen/color"
)

func main() {
	// sRGB color - should be in gamut
	inGamut := color.RGB(0.5, 0.6, 0.7)
	fmt.Printf("In gamut: %v\n", color.InGamut(inGamut))

	// Out of gamut color (gets clamped by NewRGBA)
	outOfGamut := color.NewRGBA(1.2, 0.5, 0.3, 1.0)
	fmt.Printf("Out of gamut check: %v\n", color.InGamut(outOfGamut))
}
Output:

In gamut: true
Out of gamut check: true

func IsAccessible ΒΆ added in v1.0.1

func IsAccessible(foreground, background Color, level WCAGLevel, textSize TextSize) bool

IsAccessible checks if a color pair meets WCAG requirements for given level and text size.

func IsColorBlindSafe ΒΆ added in v1.0.1

func IsColorBlindSafe(c1, c2 Color, cvdType ColorBlindnessType, minContrast float64) bool

IsColorBlindSafe checks if two colors are distinguishable for people with color blindness. It simulates the colors for the given CVD type and checks if they have sufficient contrast.

func ListSpaces ΒΆ added in v1.0.1

func ListSpaces() []string

ListSpaces returns a list of all registered color space names. The names are returned in no particular order.

Example:

spaces := ListSpaces()
for _, name := range spaces {
    fmt.Println(name)
}

func NormalizeHue ΒΆ added in v1.0.1

func NormalizeHue(h float64) float64

NormalizeHue normalizes hue to [0, 360). This is useful when working with cylindrical color spaces like HSL, HSV, LCH, and OKLCH.

func RGBToHex ΒΆ

func RGBToHex(c Color) string

RGBToHex converts an RGB color to a hex string. Returns format #RRGGBB or #RRGGBBAA if alpha < 1.0.

Example ΒΆ
package main

import (
	"fmt"
	"github.com/SCKelemen/color"
)

func main() {
	rgb := color.RGB(1.0, 0.34, 0.2) // Similar to #FF5733
	hex := color.RGBToHex(rgb)
	fmt.Printf("Hex: %s\n", hex)
}

func RegisterSpace ΒΆ added in v1.0.1

func RegisterSpace(name string, space Space)

RegisterSpace registers a color space with the given name(s). The name is case-insensitive. You can register the same space with multiple names.

Example:

RegisterSpace("my-space", myCustomSpace)
RegisterSpace("my-alias", myCustomSpace)  // Register with alias
Example ΒΆ

Example showing color space registration

package main

import (
	"fmt"

	"github.com/SCKelemen/color"
)

func main() {
	// Register a custom space (in practice, use existing spaces)
	customSpace := color.DisplayP3Space
	color.RegisterSpace("my-custom-space", customSpace)

	// Retrieve it later
	space, ok := color.GetSpace("my-custom-space")
	if ok {
		fmt.Printf("Retrieved space: %s\n", space.Name())
	}
}
Output:

Retrieved space: display-p3

func ToLipglossColor ΒΆ

func ToLipglossColor(c Color) string

ToLipglossColor converts any color to a lipgloss-compatible hex string. This is a convenience function for use with the lipgloss library.

Example:

import (
    "github.com/charmbracelet/lipgloss"
    "github.com/SCKelemen/color"
)

bgColor := color.NewOKLCH(0.2, 0.1, 240, 1.0)
style := lipgloss.NewStyle().
    Background(lipgloss.Color(color.ToLipglossColor(bgColor)))

func ToLipglossColorWithAlpha ΒΆ

func ToLipglossColorWithAlpha(c Color) string

ToLipglossColorWithAlpha converts any color to a lipgloss-compatible hex string including alpha channel (if supported by lipgloss version).

Note: Some versions of lipgloss may not support alpha in hex colors. Use ToLipglossColor() if you don't need alpha.

func ToStdColor ΒΆ added in v1.0.1

func ToStdColor(c Color) stdcolor.Color

ToStdColor converts a color from this library to the standard library's color.Color interface. The standard library uses uint32 values in the range [0, 65535] (16-bit per channel).

Example:

import (
    "image/color"
    "github.com/SCKelemen/color"
)

myColor := color.RGB(1.0, 0.5, 0.0)
stdColor := color.ToStdColor(myColor)
// Now you can use stdColor with image processing libraries

func UnregisterSpace ΒΆ added in v1.0.1

func UnregisterSpace(name string)

UnregisterSpace removes a color space from the registry. This is mainly useful for testing or when dynamically managing color spaces.

Types ΒΆ

type Color ΒΆ

type Color interface {
	// RGBA returns the red, green, blue, and alpha values
	// in the range [0, 1].
	RGBA() (r, g, b, a float64)

	// Alpha returns the alpha channel value in the range [0, 1].
	Alpha() float64

	// WithAlpha returns a new color with the specified alpha value.
	WithAlpha(alpha float64) Color
}

Color represents a color in any color space with an alpha channel. All color spaces must implement conversion to and from RGBA.

func AdjustHue ΒΆ

func AdjustHue(c Color, degrees float64) Color

AdjustHue shifts the hue of a color by the specified degrees.

func Analogous ΒΆ added in v1.0.1

func Analogous(c Color) []Color

Analogous returns an analogous color scheme (colors adjacent on the wheel). By default, returns 3 colors: the input color and two neighbors at Β±30Β°. Use AnalogousN for custom angles and count.

func AnalogousN ΒΆ added in v1.0.1

func AnalogousN(c Color, n int, angle float64) []Color

AnalogousN returns n analogous colors with custom angle spacing. The colors are distributed evenly within the angle range on both sides.

Example:

AnalogousN(color, 5, 30) returns 5 colors from -30Β° to +30Β°

func ClipToGamut ΒΆ added in v1.0.1

func ClipToGamut(c Color) Color

ClipToGamut is a convenience function that clips a color to the sRGB gamut. This is equivalent to MapToGamut(c, GamutClip).

func Complement ΒΆ

func Complement(c Color) Color

Complement returns the complementary color (hue shifted by 180 degrees).

func Complementary ΒΆ added in v1.0.1

func Complementary(c Color) Color

Complementary returns the complementary color (opposite on the color wheel). This creates maximum contrast while maintaining harmony.

func ConvertFromRGBSpace ΒΆ

func ConvertFromRGBSpace(r, g, b, a float64, spaceName string) (Color, error)

ConvertFromRGBSpace converts RGB values from a specific color space to an RGBA color. This is useful when you have RGB values in a wide-gamut space and want to work with them.

Example:

// You have display-p3 RGB values
displayP3RGB, _ := color.ConvertFromRGBSpace(1.0, 0.0, 0.0, 1.0, "display-p3")
// Now convert to OKLCH for manipulation
oklch := color.ToOKLCH(displayP3RGB)

func Darken ΒΆ

func Darken(c Color, amount float64) Color

Darken decreases the lightness of a color by the specified amount. Amount should be in the range [0, 1], where 0 is no change and 1 is maximum darkening.

Example ΒΆ
package main

import (
	"fmt"
	"github.com/SCKelemen/color"
)

func main() {
	red := color.RGB(1.0, 0.0, 0.0)
	darkRed := color.Darken(red, 0.3)
	r, g, b, _ := darkRed.RGBA()
	fmt.Printf("Dark red: R=%.2f, G=%.2f, B=%.2f\n", r, g, b)
}

func Desaturate ΒΆ

func Desaturate(c Color, amount float64) Color

Desaturate decreases the saturation of a color by the specified amount. Amount should be in the range [0, 1], where 0 is no change and 1 is complete desaturation.

func DoubleSplitComplementary ΒΆ added in v1.0.1

func DoubleSplitComplementary(c Color) []Color

DoubleSplitComplementary returns a double split-complementary scheme (6 colors). This combines two split-complementary schemes from opposite sides of the wheel.

func FadeIn ΒΆ

func FadeIn(c Color, amount float64) Color

FadeIn increases the opacity of a color by the specified amount.

func FadeOut ΒΆ

func FadeOut(c Color, amount float64) Color

FadeOut decreases the opacity of a color by the specified amount.

func FromStdColor ΒΆ added in v1.0.1

func FromStdColor(c stdcolor.Color) Color

FromStdColor converts a standard library color.Color to this library's Color interface. This allows you to use colors from image processing libraries with this library.

Example:

import (
    "image/color"
    "github.com/SCKelemen/color"
)

stdColor := color.RGBA{R: 255, G: 128, B: 0, A: 255}
myColor := color.FromStdColor(stdColor)
// Now you can use myColor with this library's functions
oklch := color.ToOKLCH(myColor)

func Gradient ΒΆ

func Gradient(start, end Color, steps int) []Color

Gradient generates a gradient between two colors in a perceptually uniform color space. Steps is the number of colors to generate (including start and end). The gradient is computed in OKLCH space for perceptually uniform results.

func GradientInSpace ΒΆ

func GradientInSpace(start, end Color, steps int, space GradientSpace) []Color

GradientInSpace generates a gradient in a specific color space. This allows you to control which color space is used for interpolation.

Example ΒΆ

Example showing gradient with hue interpolation

package main

import (
	"fmt"

	"github.com/SCKelemen/color"
)

func main() {
	red := color.RGB(1, 0, 0)
	blue := color.RGB(0, 0, 1)

	// Generate smooth gradient in OKLCH space
	gradient := color.GradientInSpace(red, blue, 5, color.GradientOKLCH)

	fmt.Printf("Generated %d colors\n", len(gradient))
}
Output:

Generated 5 colors

func GradientMultiStop ΒΆ

func GradientMultiStop(stops []GradientStop, steps int, space GradientSpace) []Color

GradientMultiStop generates a gradient with multiple color stops. Stops should be sorted by position (0 to 1). If not sorted, they will be sorted automatically. Steps is the total number of colors to generate.

Example:

stops := []GradientStop{
    {Color: color.RGB(1, 0, 0), Position: 0.0},   // Red at start
    {Color: color.RGB(1, 1, 0), Position: 0.5}, // Yellow in middle
    {Color: color.RGB(0, 0, 1), Position: 1.0}, // Blue at end
}
gradient := color.GradientMultiStop(stops, 20, color.GradientOKLCH)
Example ΒΆ

Example showing multi-stop gradients

package main

import (
	"fmt"

	"github.com/SCKelemen/color"
)

func main() {
	stops := []color.GradientStop{
		{Color: color.RGB(1, 0, 0), Position: 0.0}, // Red
		{Color: color.RGB(1, 1, 0), Position: 0.5}, // Yellow
		{Color: color.RGB(0, 0, 1), Position: 1.0}, // Blue
	}

	gradient := color.GradientMultiStop(stops, 10, color.GradientOKLCH)

	fmt.Printf("Multi-stop gradient: %d colors\n", len(gradient))
}
Output:

Multi-stop gradient: 10 colors

func GradientMultiStopWithEasing ΒΆ

func GradientMultiStopWithEasing(stops []GradientStop, steps int, space GradientSpace, easing EasingFunction) []Color

GradientMultiStopWithEasing generates a multistop gradient with easing applied. The easing function is applied to the overall gradient progress.

func GradientWithEasing ΒΆ

func GradientWithEasing(start, end Color, steps int, space GradientSpace, easing EasingFunction) []Color

GradientWithEasing generates a gradient with an easing function applied. The easing function transforms the linear interpolation progress for non-linear gradients.

Example:

red := color.RGB(1, 0, 0)
blue := color.RGB(0, 0, 1)
// Create a gradient that starts slow and speeds up (ease-in)
gradient := color.GradientWithEasing(red, blue, 20, color.GradientOKLCH, color.EaseInQuad)

func Grayscale ΒΆ

func Grayscale(c Color) Color

Grayscale converts a color to grayscale.

func Invert ΒΆ

func Invert(c Color) Color

Invert inverts the RGB values of a color.

func Lighten ΒΆ

func Lighten(c Color, amount float64) Color

Lighten increases the lightness of a color by the specified amount. Amount should be in the range [0, 1], where 0 is no change and 1 is maximum lightening.

Example ΒΆ
package main

import (
	"fmt"
	"github.com/SCKelemen/color"
)

func main() {
	blue := color.RGB(0.0, 0.0, 1.0)
	lightBlue := color.Lighten(blue, 0.3)
	r, g, b, _ := lightBlue.RGBA()
	fmt.Printf("Light blue: R=%.2f, G=%.2f, B=%.2f\n", r, g, b)
}
Example (ThemePalette) ΒΆ

Example demonstrating theme palette generation

package main

import (
	"fmt"

	"github.com/SCKelemen/color"
)

func main() {
	brandColor := color.RGB(0.23, 0.51, 0.96) // Blue

	// Generate palette
	palette := map[string]string{
		"light": color.RGBToHex(color.Lighten(brandColor, 0.2)),
		"base":  color.RGBToHex(brandColor),
		"dark":  color.RGBToHex(color.Darken(brandColor, 0.2)),
	}

	fmt.Printf("Palette generated with %d shades\n", len(palette))
}
Output:

Palette generated with 3 shades

func MapToGamut ΒΆ added in v1.0.1

func MapToGamut(c Color, mapping GamutMapping) Color

MapToGamut maps a color into the sRGB gamut using the specified mapping algorithm. If the color is already in-gamut, it is returned unchanged.

Example ΒΆ

Example demonstrating gamut mapping

package main

import (
	"fmt"

	"github.com/SCKelemen/color"
)

func main() {
	// Create a vivid out-of-gamut color
	vivid := color.NewOKLCH(0.7, 0.35, 150, 1.0)

	// Map to sRGB gamut preserving lightness
	mapped := color.MapToGamut(vivid, color.GamutPreserveLightness)

	// Check if now in gamut
	if color.InGamut(mapped) {
		fmt.Println("Successfully mapped to gamut")
	}
}
Output:

Successfully mapped to gamut

func Mix ΒΆ

func Mix(c1, c2 Color, weight float64) Color

Mix blends two colors together. Weight should be in the range [0, 1], where 0 returns c1 and 1 returns c2.

Example ΒΆ
package main

import (
	"fmt"
	"github.com/SCKelemen/color"
)

func main() {
	red := color.RGB(1.0, 0.0, 0.0)
	blue := color.RGB(0.0, 0.0, 1.0)
	purple := color.Mix(red, blue, 0.5)
	r, g, b, _ := purple.RGBA()
	fmt.Printf("Purple (mixed): R=%.2f, G=%.2f, B=%.2f\n", r, g, b)
}

func MixInSpace ΒΆ

func MixInSpace(c1, c2 Color, weight float64, space GradientSpace) Color

MixInSpace mixes two colors in the specified color space.

func MixOKLCH ΒΆ

func MixOKLCH(c1, c2 Color, weight float64) Color

MixOKLCH blends two colors in OKLCH space for perceptually uniform mixing.

Example ΒΆ

Example showing color mixing

package main

import (
	"fmt"

	"github.com/SCKelemen/color"
)

func main() {
	red := color.RGB(1, 0, 0)
	blue := color.RGB(0, 0, 1)

	// Mix 50/50 in OKLCH space
	purple := color.MixOKLCH(red, blue, 0.5)

	hex := color.RGBToHex(purple)
	fmt.Printf("Mixed color: %s\n", hex)
}
Output:

Mixed color: #ba00c1

func Monochromatic ΒΆ added in v1.0.1

func Monochromatic(c Color, n int) []Color

Monochromatic returns a monochromatic color scheme (same hue, varying lightness). Returns n colors with the same hue but different lightness values. The colors range from dark to light, preserving the original chroma.

func MonochromaticCentered ΒΆ added in v1.0.1

func MonochromaticCentered(c Color, n int) []Color

MonochromaticCentered returns a monochromatic scheme centered on the input color. The input color will be in the middle of the returned palette.

func Opacity ΒΆ

func Opacity(c Color, opacity float64) Color

Opacity returns a color with the specified opacity (alpha). Opacity should be in the range [0, 1], where 0 is transparent and 1 is opaque.

func ParseColor ΒΆ

func ParseColor(s string) (Color, error)

ParseColor parses a color string in various formats and returns a Color.

Supported formats (all major CSS color formats):

  • Hex: "#FF0000", "#F00", "#FF000080" (with alpha)
  • RGB: "rgb(255, 0, 0)", "rgb(100%, 0%, 0%)", "rgb(255 0 0)" (modern syntax)
  • RGBA: "rgba(255, 0, 0, 0.5)", "rgb(255 0 0 / 0.5)" (modern syntax)
  • HSL: "hsl(0, 100%, 50%)", "hsl(0 100% 50%)" (modern syntax)
  • HSLA: "hsla(0, 100%, 50%, 0.5)", "hsl(0 100% 50% / 0.5)" (modern syntax)
  • HWB: "hwb(0 0% 0%)", "hwb(0 0% 0% / 0.5)" (Hue, Whiteness, Blackness)
  • HSV: "hsv(0, 100%, 100%)" (not in CSS spec, but commonly used)
  • HSVA: "hsva(0, 100%, 100%, 0.5)"
  • LAB: "lab(50% 20 30)" or "lab(50 20 30)" (CIE 1976 L*a*b*)
  • OKLAB: "oklab(0.6 0.1 -0.1)" (perceptually uniform)
  • LCH: "lch(70% 50 180)" or "lch(70 50 180)" (CIE LCH from LAB)
  • OKLCH: "oklch(0.7 0.2 120)" (perceptually uniform)
  • XYZ: "color(xyz 0.5 0.5 0.5)" or "color(xyz-d65 0.5 0.5 0.5)" (CIE 1931 XYZ)
  • Wide-gamut RGB via color() function:
  • "color(srgb 1 0 0)" (sRGB, same as rgb())
  • "color(srgb-linear 1 0 0)" (linear sRGB, no gamma)
  • "color(display-p3 1 0 0)" (Display P3, wide gamut)
  • "color(a98-rgb 1 0 0)" (Adobe RGB 1998)
  • "color(prophoto-rgb 1 0 0)" (ProPhoto RGB)
  • "color(rec2020 1 0 0)" (Rec. 2020, UHDTV)
  • Named colors: "red", "blue", "transparent", etc.

CIE (Commission Internationale de l'Γ‰clairage) color spaces are fully supported:

  • XYZ: CIE 1931 XYZ color space (via color() function)
  • LAB: CIE 1976 L*a*b* color space
  • LCH: Polar representation of CIE LAB

func Rectangle ΒΆ added in v1.0.1

func Rectangle(c Color, angle float64) []Color

Rectangle returns a rectangular (double split-complementary) color scheme. This uses two pairs of complementary colors, creating 4 colors total. The angle parameter controls the spacing (typically 30-60Β°).

func Saturate ΒΆ

func Saturate(c Color, amount float64) Color

Saturate increases the saturation of a color by the specified amount. Amount should be in the range [0, 1], where 0 is no change and 1 is maximum saturation.

Example ΒΆ

Example showing saturation adjustment

package main

import (
	"fmt"

	"github.com/SCKelemen/color"
)

func main() {
	dullColor := color.RGB(0.6, 0.5, 0.55) // Grayish pink

	// Make it more vivid
	vivid := color.Saturate(dullColor, 0.3) // 30% more saturated

	oklch := color.ToOKLCH(vivid)
	fmt.Printf("Increased chroma: %.2f\n", oklch.C)
}
Output:

Increased chroma: 0.29

func Shades ΒΆ added in v1.0.1

func Shades(c Color, n int) []Color

Shades returns darker variations of the color (reduced lightness). Returns n colors from the original to nearly black, preserving hue and chroma.

func SimulateColorBlindness ΒΆ added in v1.0.1

func SimulateColorBlindness(c Color, cvdType ColorBlindnessType) Color

SimulateColorBlindness simulates how a color appears to someone with color vision deficiency. Uses the Brettel et al. (1997) and ViΓ©not et al. (1999) simulation matrices.

func SplitComplementary ΒΆ added in v1.0.1

func SplitComplementary(c Color) []Color

SplitComplementary returns a split-complementary color scheme. This uses colors on either side of the complement (opposite + Β±30Β°). Returns 3 colors: the input color and two colors flanking the complement.

func SplitComplementaryN ΒΆ added in v1.0.1

func SplitComplementaryN(c Color, angle float64) []Color

SplitComplementaryN returns a split-complementary scheme with custom angle. The angle determines how far from the complement the flanking colors are.

func Square ΒΆ added in v1.0.1

func Square(c Color) []Color

Square is an alias for Tetradic (4 colors at 90Β° intervals).

func SuggestAccessibleBackground ΒΆ added in v1.0.1

func SuggestAccessibleBackground(foreground, baseBackground Color, level WCAGLevel, textSize TextSize) (Color, bool)

SuggestAccessibleBackground finds an accessible background color for a given foreground. It adjusts the lightness of the base color to meet WCAG requirements.

func SuggestAccessibleForeground ΒΆ added in v1.0.1

func SuggestAccessibleForeground(base, background Color, level WCAGLevel, textSize TextSize) (Color, bool)

SuggestAccessibleForeground finds an accessible foreground color for a given background. It adjusts the lightness of the base color to meet WCAG requirements. Returns the suggested color and whether it meets the requirements.

func Tetradic ΒΆ added in v1.0.1

func Tetradic(c Color) []Color

Tetradic returns a tetradic (square) color scheme (4 colors evenly spaced). Returns the input color plus three harmonious colors at 90Β° intervals.

func Tints ΒΆ added in v1.0.1

func Tints(c Color, n int) []Color

Tints returns lighter variations of the color (increased lightness). Returns n colors from the original to nearly white, preserving hue.

func Tones ΒΆ added in v1.0.1

func Tones(c Color, n int) []Color

Tones returns variations with reduced chroma (desaturated, more gray). Returns n colors from the original to a neutral gray, preserving hue and lightness.

func Triadic ΒΆ added in v1.0.1

func Triadic(c Color) []Color

Triadic returns a triadic color scheme (3 colors evenly spaced on the color wheel). Returns the input color plus two harmonious colors at 120Β° intervals.

type ColorBlindnessType ΒΆ added in v1.0.1

type ColorBlindnessType int

ColorBlindnessType represents different types of color vision deficiency.

const (
	// Protanopia is red-blind (missing L-cone, ~1% males)
	Protanopia ColorBlindnessType = iota
	// Protanomaly is red-weak (anomalous L-cone, ~1% males)
	Protanomaly
	// Deuteranopia is green-blind (missing M-cone, ~1% males)
	Deuteranopia
	// Deuteranomaly is green-weak (anomalous M-cone, ~5% males)
	Deuteranomaly
	// Tritanopia is blue-blind (missing S-cone, very rare)
	Tritanopia
	// Tritanomaly is blue-weak (anomalous S-cone, very rare)
	Tritanomaly
	// Achromatopsia is complete color blindness (very rare)
	Achromatopsia
	// Achromatomaly is partial color blindness (very rare)
	Achromatomaly
)

type ContrastCompliance ΒΆ added in v1.0.1

type ContrastCompliance struct {
	Ratio        float64
	AANormal     bool // AA level for normal text (4.5:1)
	AALarge      bool // AA level for large text (3:1)
	AAANormal    bool // AAA level for normal text (7:1)
	AAALarge     bool // AAA level for large text (4.5:1)
	UIComponents bool // UI components and graphics (3:1)
}

ContrastCompliance checks if two colors meet WCAG contrast requirements.

func CheckContrast ΒΆ added in v1.0.1

func CheckContrast(foreground, background Color) ContrastCompliance

CheckContrast returns detailed WCAG compliance information for two colors.

type EasingFunction ΒΆ

type EasingFunction func(t float64) float64

EasingFunction defines a function that maps a linear progress [0, 1] to an eased progress [0, 1]. Users can create custom easing functions by implementing this interface.

Requirements:

  • Input t should be in range [0, 1]
  • Output should be in range [0, 1]
  • Should map 0 to 0 and 1 to 1

Example of creating a custom easing function:

// Custom exponential easing
myEasing := color.EasingFunction(func(t float64) float64 {
    return 1 - math.Pow(1-t, 3) // Ease-out cubic
})

// Use it in a gradient
gradient := color.GradientWithEasing(red, blue, 20, color.GradientOKLCH, myEasing)
var (
	// EaseLinear is the default linear easing (no change).
	EaseLinear EasingFunction = func(t float64) float64 { return t }

	// EaseInQuad provides a quadratic ease-in curve.
	EaseInQuad EasingFunction = func(t float64) float64 { return t * t }

	// EaseOutQuad provides a quadratic ease-out curve.
	EaseOutQuad EasingFunction = func(t float64) float64 { return t * (2 - t) }

	// EaseInOutQuad provides a quadratic ease-in-out curve.
	EaseInOutQuad EasingFunction = func(t float64) float64 {
		if t < 0.5 {
			return 2 * t * t
		}
		return -1 + (4-2*t)*t
	}

	// EaseInCubic provides a cubic ease-in curve.
	EaseInCubic EasingFunction = func(t float64) float64 { return t * t * t }

	// EaseOutCubic provides a cubic ease-out curve.
	EaseOutCubic EasingFunction = func(t float64) float64 {
		t--
		return t*t*t + 1
	}

	// EaseInOutCubic provides a cubic ease-in-out curve.
	EaseInOutCubic EasingFunction = func(t float64) float64 {
		if t < 0.5 {
			return 4 * t * t * t
		}
		t = 2*t - 2
		return t*t*t/2 + 1
	}

	// EaseInSine provides a sinusoidal ease-in curve.
	EaseInSine EasingFunction = func(t float64) float64 {
		return 1 - math.Cos(t*math.Pi/2)
	}

	// EaseOutSine provides a sinusoidal ease-out curve.
	EaseOutSine EasingFunction = func(t float64) float64 {
		return math.Sin(t * math.Pi / 2)
	}

	// EaseInOutSine provides a sinusoidal ease-in-out curve.
	EaseInOutSine EasingFunction = func(t float64) float64 {
		return -(math.Cos(math.Pi*t) - 1) / 2
	}
)

Easing functions for non-linear gradients

type GamutMapping ΒΆ added in v1.0.1

type GamutMapping int

GamutMapping specifies the algorithm to use when a color is out of the target gamut.

const (
	// GamutClip simply clips RGB values to [0, 1]. This is fast but may shift hue.
	GamutClip GamutMapping = iota

	// GamutPreserveChroma reduces lightness while preserving chroma until the color is in-gamut.
	// This maintains saturation but may significantly alter brightness.
	GamutPreserveChroma

	// GamutPreserveLightness reduces chroma while preserving lightness until the color is in-gamut.
	// This maintains brightness but reduces saturation (recommended for most uses).
	GamutPreserveLightness

	// GamutProject projects the color onto the gamut boundary along the shortest perceptual path.
	// This balances lightness and chroma adjustments for the most perceptually accurate result.
	GamutProject
)

type GradientSpace ΒΆ

type GradientSpace int

GradientSpace specifies which color space to use for gradient interpolation.

const (
	// GradientRGB interpolates in RGB space (fast but not perceptually uniform)
	GradientRGB GradientSpace = iota
	// GradientHSL interpolates in HSL space
	GradientHSL
	// GradientLAB interpolates in CIE LAB space
	GradientLAB
	// GradientOKLAB interpolates in OKLAB space (perceptually uniform)
	GradientOKLAB
	// GradientLCH interpolates in CIE LCH space
	GradientLCH
	// GradientOKLCH interpolates in OKLCH space (perceptually uniform, recommended)
	GradientOKLCH
)

type GradientStop ΒΆ

type GradientStop struct {
	Color    Color
	Position float64
}

GradientStop represents a color stop in a multistop gradient. Position should be in the range [0, 1], where 0 is the start and 1 is the end.

type HSL ΒΆ

type HSL struct {
	H, S, L, A float64
}

HSL represents a color in the HSL color space. H is hue [0, 360), S is saturation [0, 1], L is lightness [0, 1].

func NewHSL ΒΆ

func NewHSL(h, s, l, a float64) *HSL

NewHSL creates a new HSL color.

func ToHSL ΒΆ

func ToHSL(c Color) *HSL

ToHSL converts an RGBA color to HSL.

Example ΒΆ
package main

import (
	"fmt"
	"github.com/SCKelemen/color"
)

func main() {
	// Create RGB color
	rgb := color.RGB(1.0, 0.5, 0.0) // Orange

	// Convert to different color spaces
	hsl := color.ToHSL(rgb)
	fmt.Printf("HSL: H=%.1f, S=%.2f, L=%.2f\n", hsl.H, hsl.S, hsl.L)

	oklch := color.ToOKLCH(rgb)
	fmt.Printf("OKLCH: L=%.2f, C=%.2f, H=%.1f\n", oklch.L, oklch.C, oklch.H)
}

func (*HSL) Alpha ΒΆ

func (c *HSL) Alpha() float64

Alpha implements Color.

func (*HSL) RGBA ΒΆ

func (c *HSL) RGBA() (r, g, b, a float64)

RGBA converts HSL to RGBA.

func (*HSL) WithAlpha ΒΆ

func (c *HSL) WithAlpha(alpha float64) Color

WithAlpha implements Color.

type HSV ΒΆ

type HSV struct {
	H, S, V, A float64
}

HSV represents a color in the HSV (HSB) color space. H is hue [0, 360), S is saturation [0, 1], V is value/brightness [0, 1].

func NewHSV ΒΆ

func NewHSV(h, s, v, a float64) *HSV

NewHSV creates a new HSV color.

func ToHSV ΒΆ

func ToHSV(c Color) *HSV

ToHSV converts an RGBA color to HSV.

func (*HSV) Alpha ΒΆ

func (c *HSV) Alpha() float64

Alpha implements Color.

func (*HSV) RGBA ΒΆ

func (c *HSV) RGBA() (r, g, b, a float64)

RGBA converts HSV to RGBA.

func (*HSV) WithAlpha ΒΆ

func (c *HSV) WithAlpha(alpha float64) Color

WithAlpha implements Color.

type HWB ΒΆ added in v1.0.1

type HWB struct {
	H, W, B, A float64
}

HWB represents a color in the HWB color space. H is hue [0, 360), W is whiteness [0, 1], B is blackness [0, 1]. HWB is more intuitive than HSL - whiteness adds white, blackness adds black. This color space is part of CSS Color Level 4.

func NewHWB ΒΆ added in v1.0.1

func NewHWB(h, w, b, a float64) *HWB

NewHWB creates a new HWB color. H is in [0, 360), W and B are in [0, 1]. If W+B > 1, they will be normalized to sum to 1.

Example ΒΆ

Example showing HWB color space

package main

import (
	"fmt"

	"github.com/SCKelemen/color"
)

func main() {
	// Create color using HWB (Hue, Whiteness, Blackness)
	hwb := color.NewHWB(120, 0.2, 0.1, 1.0) // Green with some white and black

	// Convert to RGB
	r, _, _, _ := hwb.RGBA()
	fmt.Printf("HWB color converted: R=%.2f\n", r)
}
Output:

HWB color converted: R=0.20

func ToHWB ΒΆ added in v1.0.1

func ToHWB(c Color) *HWB

ToHWB converts a Color to HWB.

func (*HWB) Alpha ΒΆ added in v1.0.1

func (c *HWB) Alpha() float64

Alpha implements Color.

func (*HWB) RGBA ΒΆ added in v1.0.1

func (c *HWB) RGBA() (r, g, b, a float64)

RGBA converts HWB to RGBA.

func (*HWB) WithAlpha ΒΆ added in v1.0.1

func (c *HWB) WithAlpha(alpha float64) Color

WithAlpha implements Color.

type HexParseError ΒΆ

type HexParseError struct {
	// contains filtered or unexported fields
}

HexParseError represents an error parsing a hex color string.

func (*HexParseError) Error ΒΆ

func (e *HexParseError) Error() string

type HueInterpolation ΒΆ added in v1.0.1

type HueInterpolation int

HueInterpolation specifies how to interpolate hue values in cylindrical color spaces.

const (
	// HueShorter interpolates hue using the shortest path around the color wheel (default)
	HueShorter HueInterpolation = iota
	// HueLonger interpolates hue using the longer path around the color wheel
	HueLonger
	// HueIncreasing interpolates hue in the direction of increasing values
	HueIncreasing
	// HueDecreasing interpolates hue in the direction of decreasing values
	HueDecreasing
)

type LAB ΒΆ

type LAB struct {
	L, A, B, A_ float64 // A_ is alpha to avoid conflict with method
}

LAB represents a color in the CIE LAB color space. L is lightness [0, 100], A and B are color-opponent dimensions.

func NewLAB ΒΆ

func NewLAB(l, a, b, alpha float64) *LAB

NewLAB creates a new LAB color.

func ToLAB ΒΆ

func ToLAB(c Color) *LAB

ToLAB converts an RGBA color to LAB.

func (*LAB) Alpha ΒΆ

func (c *LAB) Alpha() float64

Alpha implements Color.

func (*LAB) RGBA ΒΆ

func (c *LAB) RGBA() (r, g, b, a float64)

RGBA converts LAB to RGBA via XYZ.

func (*LAB) WithAlpha ΒΆ

func (c *LAB) WithAlpha(alpha float64) Color

WithAlpha implements Color.

type LCH ΒΆ

type LCH struct {
	L, C, H, A_ float64 // A_ is alpha to avoid conflict with method
}

LCH represents a color in the LCH color space (polar representation of LAB). L is lightness [0, 100], C is chroma [0, ~132], H is hue [0, 360).

func NewLCH ΒΆ

func NewLCH(l, c, h, alpha float64) *LCH

NewLCH creates a new LCH color.

func ToLCH ΒΆ

func ToLCH(c Color) *LCH

ToLCH converts an RGBA color to LCH.

func (*LCH) Alpha ΒΆ

func (c *LCH) Alpha() float64

Alpha implements Color.

func (*LCH) RGBA ΒΆ

func (c *LCH) RGBA() (r, g, b, a float64)

RGBA converts LCH to RGBA via LAB.

func (*LCH) WithAlpha ΒΆ

func (c *LCH) WithAlpha(alpha float64) Color

WithAlpha implements Color.

type LCHuv ΒΆ added in v1.0.1

type LCHuv struct {
	L, C, H, A_ float64 // A_ is alpha to avoid conflict with method
}

LCHuv represents a color in the CIE LCHuv color space (cylindrical LUV). L is lightness [0, 100], C is chroma, H is hue [0, 360).

func NewLCHuv ΒΆ added in v1.0.1

func NewLCHuv(l, c, h, alpha float64) *LCHuv

NewLCHuv creates a new LCHuv color.

func ToLCHuv ΒΆ added in v1.0.1

func ToLCHuv(c Color) *LCHuv

ToLCHuv converts a Color to LCHuv.

func (*LCHuv) Alpha ΒΆ added in v1.0.1

func (c *LCHuv) Alpha() float64

Alpha implements Color.

func (*LCHuv) RGBA ΒΆ added in v1.0.1

func (c *LCHuv) RGBA() (r, g, b, a float64)

RGBA converts LCHuv to RGBA via LUV.

func (*LCHuv) WithAlpha ΒΆ added in v1.0.1

func (c *LCHuv) WithAlpha(alpha float64) Color

WithAlpha implements Color.

type LUV ΒΆ added in v1.0.1

type LUV struct {
	L, U, V, A_ float64 // A_ is alpha to avoid conflict with method
}

LUV represents a color in the CIE LUV color space. L is lightness [0, 100], U and V are color-opponent dimensions. LUV is an alternative to LAB that's better suited for emissive displays.

func NewLUV ΒΆ added in v1.0.1

func NewLUV(l, u, v, alpha float64) *LUV

NewLUV creates a new LUV color.

func ToLUV ΒΆ added in v1.0.1

func ToLUV(c Color) *LUV

ToLUV converts a Color to LUV.

Example ΒΆ

Example showing LUV color space

package main

import (
	"fmt"

	"github.com/SCKelemen/color"
)

func main() {
	c := color.RGB(0.5, 0.3, 0.7) // Purple

	// Convert to CIELUV
	luv := color.ToLUV(c)

	fmt.Printf("LUV L component: %.1f\n", luv.L)
}
Output:

LUV L component: 42.8

func (*LUV) Alpha ΒΆ added in v1.0.1

func (c *LUV) Alpha() float64

Alpha implements Color.

func (*LUV) RGBA ΒΆ added in v1.0.1

func (c *LUV) RGBA() (r, g, b, a float64)

RGBA converts LUV to RGBA via XYZ.

func (*LUV) WithAlpha ΒΆ added in v1.0.1

func (c *LUV) WithAlpha(alpha float64) Color

WithAlpha implements Color.

type OKLAB ΒΆ

type OKLAB struct {
	L, A, B, A_ float64 // A_ is alpha to avoid conflict with method
}

OKLAB represents a color in the OKLAB color space. L is perceived lightness [0, 1], A and B are color-opponent dimensions.

func NewOKLAB ΒΆ

func NewOKLAB(l, a, b, alpha float64) *OKLAB

NewOKLAB creates a new OKLAB color.

func ToOKLAB ΒΆ

func ToOKLAB(c Color) *OKLAB

ToOKLAB converts an RGBA color to OKLAB.

func (*OKLAB) Alpha ΒΆ

func (c *OKLAB) Alpha() float64

Alpha implements Color.

func (*OKLAB) RGBA ΒΆ

func (c *OKLAB) RGBA() (r, g, b, a float64)

RGBA converts OKLAB to RGBA via linear RGB.

func (*OKLAB) WithAlpha ΒΆ

func (c *OKLAB) WithAlpha(alpha float64) Color

WithAlpha implements Color.

type OKLCH ΒΆ

type OKLCH struct {
	L, C, H, A_ float64 // A_ is alpha to avoid conflict with method
}

OKLCH represents a color in the OKLCH color space (polar representation of OKLAB). L is perceived lightness [0, 1], C is chroma [0, ~0.4], H is hue [0, 360).

func NewOKLCH ΒΆ

func NewOKLCH(l, c, h, alpha float64) *OKLCH

NewOKLCH creates a new OKLCH color.

func ToOKLCH ΒΆ

func ToOKLCH(c Color) *OKLCH

ToOKLCH converts an RGBA color to OKLCH.

Example ΒΆ

Example demonstrating perceptually uniform operations

package main

import (
	"fmt"

	"github.com/SCKelemen/color"
)

func main() {
	c := color.RGB(0.5, 0.3, 0.7)

	// Convert to OKLCH for manipulation
	oklch := color.ToOKLCH(c)

	// Adjust in perceptual space
	oklch.L += 0.1 // 10% lighter
	oklch.C *= 1.2 // 20% more saturated

	// Convert back
	r, _, _, _ := oklch.RGBA()
	fmt.Printf("Adjusted color: R=%.2f\n", r)
}
Output:

Adjusted color: R=0.64

func (*OKLCH) Alpha ΒΆ

func (c *OKLCH) Alpha() float64

Alpha implements Color.

func (*OKLCH) RGBA ΒΆ

func (c *OKLCH) RGBA() (r, g, b, a float64)

RGBA converts OKLCH to RGBA via OKLAB.

func (*OKLCH) String ΒΆ added in v1.0.1

func (c *OKLCH) String() string

String returns a CSS oklch() representation.

func (*OKLCH) WithAlpha ΒΆ

func (c *OKLCH) WithAlpha(alpha float64) Color

WithAlpha implements Color.

type ParseError ΒΆ

type ParseError struct {
	// contains filtered or unexported fields
}

ParseError represents an error parsing a color string.

func (*ParseError) Error ΒΆ

func (e *ParseError) Error() string

type RGBA ΒΆ

type RGBA struct {
	R, G, B, A float64
}

RGBA represents a color in the RGB color space with alpha.

func HexToRGB ΒΆ

func HexToRGB(hex string) (*RGBA, error)

HexToRGB converts a hex color string (with or without #) to RGB. Supports formats: #RGB, #RRGGBB, #RGBA, #RRGGBBAA

Example ΒΆ
package main

import (
	"fmt"
	"github.com/SCKelemen/color"
)

func main() {
	// Parse hex color
	rgb, err := color.HexToRGB("#FF5733")
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}
	r, g, b, _ := rgb.RGBA()
	fmt.Printf("Hex #FF5733: R=%.2f, G=%.2f, B=%.2f\n", r, g, b)
}

func NewRGBA ΒΆ

func NewRGBA(r, g, b, a float64) *RGBA

RGBA creates a new RGBA color with the specified alpha.

Example ΒΆ
package main

import (
	"fmt"
	"github.com/SCKelemen/color"
)

func main() {
	// Create color with transparency
	semiTransparent := color.NewRGBA(1.0, 0.0, 0.0, 0.5)
	fmt.Printf("Alpha: %.2f\n", semiTransparent.Alpha())

	// Change alpha
	moreOpaque := semiTransparent.WithAlpha(0.8)
	fmt.Printf("New alpha: %.2f\n", moreOpaque.Alpha())
}

func RGB ΒΆ

func RGB(r, g, b float64) *RGBA

RGB creates a new RGBA color with full opacity.

Example ΒΆ
package main

import (
	"fmt"
	"github.com/SCKelemen/color"
)

func main() {
	// Create a red color
	red := color.RGB(1.0, 0.0, 0.0)
	r, g, b, a := red.RGBA()
	fmt.Printf("Red: R=%.2f, G=%.2f, B=%.2f, A=%.2f\n", r, g, b, a)
}
Output:

Red: R=1.00, G=0.00, B=0.00, A=1.00

func (*RGBA) Alpha ΒΆ

func (c *RGBA) Alpha() float64

Alpha implements Color.

func (*RGBA) RGBA ΒΆ

func (c *RGBA) RGBA() (r, g, b, a float64)

RGBA implements Color.

func (*RGBA) String ΒΆ added in v1.0.1

func (c *RGBA) String() string

String returns a string representation of the color.

func (*RGBA) WithAlpha ΒΆ

func (c *RGBA) WithAlpha(alpha float64) Color

WithAlpha implements Color.

type RGBColorSpace ΒΆ

type RGBColorSpace struct {
	// Name of the color space
	Name string

	// Matrix to convert from XYZ to linear RGB
	// Format: [rX, rY, rZ, gX, gY, gZ, bX, bY, bZ]
	XYZToRGBMatrix [9]float64

	// Matrix to convert from linear RGB to XYZ
	// Format: [Xr, Xg, Xb, Yr, Yg, Yb, Zr, Zg, Zb]
	RGBToXYZMatrix [9]float64

	// Transfer function: converts linear RGB to encoded RGB
	TransferFunc func(float64) float64

	// Inverse transfer function: converts encoded RGB to linear RGB
	InverseTransferFunc func(float64) float64
}

RGBColorSpace represents a wide-gamut RGB color space with its own conversion matrix and transfer function.

func (*RGBColorSpace) ConvertRGBToXYZ ΒΆ

func (cs *RGBColorSpace) ConvertRGBToXYZ(r, g, b, a float64) *XYZ

ConvertRGBToXYZ converts RGB in this color space to XYZ.

func (*RGBColorSpace) ConvertXYZToRGB ΒΆ

func (cs *RGBColorSpace) ConvertXYZToRGB(xyz *XYZ) *RGBA

ConvertXYZToRGB converts XYZ to this RGB color space.

type Space ΒΆ added in v1.0.1

type Space interface {
	// Name returns the name of the color space (e.g., "sRGB", "Display P3", "OKLCH")
	Name() string

	// ToXYZ converts color values from this space to XYZ (linear, D65 white point).
	// channels: color values in this space's native format
	// Returns: x, y, z in CIE XYZ space
	ToXYZ(channels []float64) (x, y, z float64)

	// FromXYZ converts XYZ values to this color space.
	// x, y, z: CIE XYZ values (linear, D65 white point)
	// Returns: color values in this space's native format
	FromXYZ(x, y, z float64) []float64

	// Channels returns the number of color channels (3 for RGB, 4 for CMYK, etc.)
	Channels() int

	// ChannelNames returns the names of the channels (e.g., ["R", "G", "B"] or ["L", "C", "H"])
	ChannelNames() []string
}

Space defines a color space with conversion to/from XYZ (the reference space). All inter-space conversions go through XYZ to ensure accuracy.

var (
	// CLogSpace represents Canon C-Log color space
	// Uses Canon Cinema Gamut primaries with C-Log transfer
	CLogSpace Space = &rgbSpace{
		name: "c-log",

		xyzToRGBMatrix: [9]float64{
			1.9624274, -0.6105343, -0.3413404,
			-0.9787684, 1.9161415, 0.0334540,
			0.0286869, -0.1406752, 1.3487655,
		},
		rgbToXYZMatrix: [9]float64{
			0.5766690429101305, 0.1855582379065463, 0.1882286462349947,
			0.29734497525053605, 0.6273635662554661, 0.07529145849399788,
			0.02703136138641234, 0.07068885253582723, 0.9913375368376388,
		},
		transferFunc:        cLogTransfer,
		inverseTransferFunc: cLogInverseTransfer,
		whitePoint:          WhiteD65,
	}

	// SLog3Space represents Sony S-Log3 color space
	// Uses Sony S-Gamut3 primaries with S-Log3 transfer
	SLog3Space Space = &rgbSpace{
		name: "s-log3",

		xyzToRGBMatrix: [9]float64{
			1.9624274, -0.6105343, -0.3413404,
			-0.9787684, 1.9161415, 0.0334540,
			0.0286869, -0.1406752, 1.3487655,
		},
		rgbToXYZMatrix: [9]float64{
			0.7064, 0.1288, 0.1213,
			0.2709, 0.7869, -0.0578,
			-0.0096, 0.0045, 1.1156,
		},
		transferFunc:        sLog3Transfer,
		inverseTransferFunc: sLog3InverseTransfer,
		whitePoint:          WhiteD65,
	}

	// VLogSpace represents Panasonic V-Log color space
	// Uses V-Gamut primaries with V-Log transfer
	VLogSpace Space = &rgbSpace{
		name: "v-log",

		xyzToRGBMatrix: [9]float64{
			1.5890, -0.3130, -0.1802,
			-0.5340, 1.3960, 0.0950,
			-0.0110, -0.0640, 1.1570,
		},
		rgbToXYZMatrix: [9]float64{
			0.7790, 0.0780, 0.1020,
			0.3270, 0.7230, -0.0500,
			0.0010, 0.0510, 0.8390,
		},
		transferFunc:        vLogTransfer,
		inverseTransferFunc: vLogInverseTransfer,
		whitePoint:          WhiteD65,
	}

	// ArriLogCSpace represents Arri LogC (V3, EI 800) color space
	// Uses Arri Wide Gamut primaries with LogC transfer
	ArriLogCSpace Space = &rgbSpace{
		name: "arri-logc",

		xyzToRGBMatrix: [9]float64{
			1.789066, -0.482534, -0.200076,
			-0.639849, 1.396400, 0.194432,
			-0.041532, 0.082335, 1.040648,
		},
		rgbToXYZMatrix: [9]float64{
			0.6380, 0.2140, 0.0970,
			0.2910, 0.8240, -0.1150,
			0.0020, -0.0380, 1.0910,
		},
		transferFunc:        arriLogCTransfer,
		inverseTransferFunc: arriLogCInverseTransfer,
		whitePoint:          WhiteD65,
	}

	// RedLog3G10Space represents Red Log3G10 color space
	// Uses RedWideGamutRGB primaries with Log3G10 transfer
	RedLog3G10Space Space = &rgbSpace{
		name: "red-log3g10",

		xyzToRGBMatrix: [9]float64{
			1.7827, -0.4969, -0.1768,
			-0.6702, 1.4985, 0.1323,
			-0.0530, 0.0403, 1.0672,
		},
		rgbToXYZMatrix: [9]float64{
			0.7347, 0.1596, 0.0366,
			0.2653, 0.8404, -0.1057,
			0.0000, -0.0000, 1.0690,
		},
		transferFunc:        redLog3G10Transfer,
		inverseTransferFunc: redLog3G10InverseTransfer,
		whitePoint:          WhiteD65,
	}

	// BMDFilmSpace represents Blackmagic Film color space
	// Uses Blackmagic Wide Gamut primaries with BMDFilm transfer
	BMDFilmSpace Space = &rgbSpace{
		name: "bmd-film",

		xyzToRGBMatrix: [9]float64{
			1.9624274, -0.6105343, -0.3413404,
			-0.9787684, 1.9161415, 0.0334540,
			0.0286869, -0.1406752, 1.3487655,
		},
		rgbToXYZMatrix: [9]float64{
			0.5766690429101305, 0.1855582379065463, 0.1882286462349947,
			0.29734497525053605, 0.6273635662554661, 0.07529145849399788,
			0.02703136138641234, 0.07068885253582723, 0.9913375368376388,
		},
		transferFunc:        bmdFilmTransfer,
		inverseTransferFunc: bmdFilmInverseTransfer,
		whitePoint:          WhiteD65,
	}
)
var A98RGBSpace Space = &rgbSpace{
	name: "a98-rgb",
	xyzToRGBMatrix: [9]float64{
		1.9624274, -0.6105343, -0.3413404,
		-0.9787684, 1.9161415, 0.0334540,
		0.0286869, -0.1406752, 1.3487655,
	},
	rgbToXYZMatrix: [9]float64{
		0.5766690429101305, 0.1855582379065463, 0.1882286462349947,
		0.29734497525053605, 0.6273635662554661, 0.07529145849399788,
		0.02703136138641234, 0.07068885253582723, 0.9913375368376388,
	},
	transferFunc:        gammaTransferFunc(2.2),
	inverseTransferFunc: gammaInverseTransferFunc(2.2),
	whitePoint:          WhiteD65,
}

A98RGBSpace represents Adobe RGB 1998 color space

var DCIP3Space Space = &rgbSpace{
	name: "dci-p3",
	xyzToRGBMatrix: [9]float64{
		2.493496911941425, -0.9313836179191239, -0.40271078445071684,
		-0.8294889695615747, 1.7626640603183463, 0.023624685841943577,
		0.03584583024378447, -0.07617238926804182, 0.9568845240076872,
	},
	rgbToXYZMatrix: [9]float64{
		0.4865709486482162, 0.26566769316909306, 0.1982172852343625,
		0.2289745640697488, 0.6917385218365064, 0.079286914093745,
		0.000000000000000, 0.04511338185890264, 1.043944368900976,
	},
	transferFunc:        gammaTransferFunc(2.6),
	inverseTransferFunc: gammaInverseTransferFunc(2.6),
	whitePoint:          WhiteD65,
}

DCIP3Space represents DCI-P3 color space (Digital Cinema) Similar to Display P3 but uses gamma 2.6 and different white point

var DisplayP3Space Space = &rgbSpace{
	name: "display-p3",
	xyzToRGBMatrix: [9]float64{
		2.493496911941425, -0.9313836179191239, -0.40271078445071684,
		-0.8294889695615747, 1.7626640603183463, 0.023624685841943577,
		0.03584583024378447, -0.07617238926804182, 0.9568845240076872,
	},
	rgbToXYZMatrix: [9]float64{
		0.4865709486482162, 0.26566769316909306, 0.1982172852343625,
		0.2289745640697488, 0.6917385218365064, 0.079286914093745,
		0.000000000000000, 0.04511338185890264, 1.043944368900976,
	},
	transferFunc:        sRGBTransfer,
	inverseTransferFunc: sRGBInverseTransfer,
	whitePoint:          WhiteD65,
}

DisplayP3Space represents Display P3 color space

var OKLCHSpace Space = &oklchSpace{}

OKLCHSpace represents the OKLCH color space (perceptually uniform)

var ProPhotoRGBSpace Space = &rgbSpace{
	name: "prophoto-rgb",
	xyzToRGBMatrix: [9]float64{
		1.3459433, -0.2556075, -0.0511118,
		-0.5445989, 1.5081673, 0.0205351,
		0.0000000, 0.0000000, 1.2118128,
	},
	rgbToXYZMatrix: [9]float64{
		0.7976749, 0.1351917, 0.0313534,
		0.2880402, 0.7118741, 0.0000857,
		0.0000000, 0.0000000, 0.8252100,
	},
	transferFunc:        gammaTransferFunc(1.8),
	inverseTransferFunc: gammaInverseTransferFunc(1.8),
	whitePoint:          WhiteD50,
}

ProPhotoRGBSpace represents ProPhoto RGB color space (D50 white point)

var Rec2020Space Space = &rgbSpace{
	name: "rec2020",
	xyzToRGBMatrix: [9]float64{
		1.7166511, -0.3556708, -0.2533663,
		-0.6666844, 1.6164812, 0.0157685,
		0.0176399, -0.0427706, 0.9421031,
	},
	rgbToXYZMatrix: [9]float64{
		0.6369580483012914, 0.14461690358620832, 0.1688809751641721,
		0.262704531669281, 0.6779980715188708, 0.05930171646986196,
		0.000000000000000, 0.028072693049087428, 1.060985057710791,
	},
	transferFunc:        rec2020Transfer,
	inverseTransferFunc: rec2020InverseTransfer,
	whitePoint:          WhiteD65,
}

Rec2020Space represents Rec. 2020 color space (UHDTV)

var Rec709Space Space = &rgbSpace{
	name: "rec709",
	xyzToRGBMatrix: [9]float64{
		3.2404542, -1.5371385, -0.4985314,
		-0.9692660, 1.8760108, 0.0415560,
		0.0556434, -0.2040259, 1.0572252,
	},
	rgbToXYZMatrix: [9]float64{
		0.4124564, 0.3575761, 0.1804375,
		0.2126729, 0.7151522, 0.0721750,
		0.0193339, 0.1191920, 0.9503041,
	},
	transferFunc:        rec709Transfer,
	inverseTransferFunc: rec709InverseTransfer,
	whitePoint:          WhiteD65,
}

Rec709Space represents Rec. 709 color space (HDTV) Very similar to sRGB but technically has different primaries

var SRGBLinearSpace Space = &rgbSpace{
	name:                "sRGB-linear",
	xyzToRGBMatrix:      [9]float64{3.2404542, -1.5371385, -0.4985314, -0.9692660, 1.8760108, 0.0415560, 0.0556434, -0.2040259, 1.0572252},
	rgbToXYZMatrix:      [9]float64{0.4124564, 0.3575761, 0.1804375, 0.2126729, 0.7151522, 0.0721750, 0.0193339, 0.1191920, 0.9503041},
	transferFunc:        linearTransfer,
	inverseTransferFunc: linearInverseTransfer,
	whitePoint:          WhiteD65,
}

SRGBLinearSpace represents linear sRGB (no gamma encoding)

var SRGBSpace Space = &rgbSpace{
	name:                "sRGB",
	xyzToRGBMatrix:      [9]float64{3.2404542, -1.5371385, -0.4985314, -0.9692660, 1.8760108, 0.0415560, 0.0556434, -0.2040259, 1.0572252},
	rgbToXYZMatrix:      [9]float64{0.4124564, 0.3575761, 0.1804375, 0.2126729, 0.7151522, 0.0721750, 0.0193339, 0.1191920, 0.9503041},
	transferFunc:        sRGBTransfer,
	inverseTransferFunc: sRGBInverseTransfer,
	whitePoint:          WhiteD65,
}

SRGBSpace represents the sRGB color space (D65 white point, sRGB primaries, sRGB transfer function)

func GetSpace ΒΆ added in v1.0.1

func GetSpace(name string) (Space, bool)

GetSpace retrieves a registered color space by name. The name lookup is case-insensitive. Returns nil if the space is not found.

Example:

space, ok := GetSpace("display-p3")
if ok {
    spaceColor := NewSpaceColor(space, []float64{1, 0, 0}, 1.0)
}

type SpaceColor ΒΆ added in v1.0.1

type SpaceColor interface {
	Color // Still implements the base Color interface for compatibility

	// Space returns the color space this color is in
	Space() Space

	// Channels returns the color values in the native space
	Channels() []float64

	// ConvertTo converts this color to a different color space.
	// This is where data loss may occur (gamut clipping, etc.)
	ConvertTo(space Space) SpaceColor

	// ToRGBA converts to sRGB RGBA (explicit conversion, may lose data for wide-gamut colors)
	ToRGBA() *RGBA
}

SpaceColor represents a color in a specific color space. This preserves the color space information and allows lossless operations.

func ConvertToRGBSpace ΒΆ

func ConvertToRGBSpace(c Color, spaceName string) (SpaceColor, error)

ConvertToRGBSpace converts a color to a specific RGB color space using the new Space system. This allows converting colors to wide-gamut RGB spaces like display-p3, a98-rgb, etc. Returns a SpaceColor that preserves the target color space information.

Example:

rgb := color.RGB(1, 0, 0)
displayP3, _ := color.ConvertToRGBSpace(rgb, "display-p3")
// displayP3 is now a SpaceColor in Display P3 space
Example ΒΆ

Example demonstrating wide-gamut workflow

package main

import (
	"fmt"

	"github.com/SCKelemen/color"
)

func main() {
	// Start with an sRGB color
	srgbColor := color.RGB(1, 0, 0)

	// Convert to Display P3 (wider gamut)
	p3Color, _ := color.ConvertToRGBSpace(srgbColor, "display-p3")

	// Manipulate in perceptual space
	lighter := color.Lighten(p3Color, 0.2)

	// Convert back to Display P3
	result, _ := color.ConvertToRGBSpace(lighter, "display-p3")

	fmt.Printf("Result color space: Display P3\n")
	fmt.Printf("Alpha preserved: %.1f\n", result.Alpha())
}
Output:

Result color space: Display P3
Alpha preserved: 1.0

func DarkenSpace ΒΆ added in v1.0.1

func DarkenSpace(c SpaceColor, amount float64) SpaceColor

DarkenSpace decreases the lightness of a color in its native space.

func DesaturateSpace ΒΆ added in v1.0.1

func DesaturateSpace(c SpaceColor, amount float64) SpaceColor

DesaturateSpace decreases the saturation of a color in its native space.

func LightenSpace ΒΆ added in v1.0.1

func LightenSpace(c SpaceColor, amount float64) SpaceColor

LightenSpace increases the lightness of a color in its native space. For perceptually uniform spaces (OKLCH), this works directly. For other spaces, converts to OKLCH, operates, and converts back.

func NewSpaceColor ΒΆ added in v1.0.1

func NewSpaceColor(space Space, channels []float64, alpha float64) SpaceColor

NewSpaceColor creates a new color in a specific color space.

func SaturateSpace ΒΆ added in v1.0.1

func SaturateSpace(c SpaceColor, amount float64) SpaceColor

SaturateSpace increases the saturation of a color in its native space.

type SpaceMetadata ΒΆ added in v1.0.1

type SpaceMetadata struct {
	// Name of the color space
	Name string

	// Family indicates the type of color space (RGB, Lab, LCH, etc.)
	Family string

	// IsRGB indicates if this is an RGB-based color space
	IsRGB bool

	// IsHDR indicates if this space supports High Dynamic Range (values > 1.0)
	IsHDR bool

	// WhitePoint indicates the reference white point (e.g., "D65", "D50")
	WhitePoint string

	// GamutVolumeRelativeToSRGB is the gamut volume relative to sRGB (1.0 = sRGB)
	// Display P3 β‰ˆ 1.26, Rec.2020 β‰ˆ 1.73, ProPhoto RGB β‰ˆ 2.89
	GamutVolumeRelativeToSRGB float64

	// IsPerceptuallyUniform indicates if the space is designed for perceptual uniformity
	IsPerceptuallyUniform bool

	// IsPolar indicates if this is a cylindrical/polar color space (has hue component)
	IsPolar bool
}

SpaceMetadata provides information about a color space's properties.

func Metadata ΒΆ added in v1.0.1

func Metadata(space Space) *SpaceMetadata

Metadata returns metadata about a color space. Returns nil if metadata is not available for this space.

Example ΒΆ

Example showing metadata usage

package main

import (
	"fmt"

	"github.com/SCKelemen/color"
)

func main() {
	meta := color.Metadata(color.DisplayP3Space)

	fmt.Printf("Space: %s\n", meta.Name)
	fmt.Printf("Gamut: %.2fx sRGB\n", meta.GamutVolumeRelativeToSRGB)
	fmt.Printf("Is RGB: %v\n", meta.IsRGB)
}
Output:

Space: display-p3
Gamut: 1.26x sRGB
Is RGB: true

type TextSize ΒΆ added in v1.0.1

type TextSize int

TextSize represents the size category of text for WCAG guidelines.

const (
	// NormalText is regular-sized text (< 18pt or < 14pt bold)
	NormalText TextSize = iota
	// LargeText is large text (β‰₯ 18pt or β‰₯ 14pt bold)
	LargeText
)

type WCAGLevel ΒΆ added in v1.0.1

type WCAGLevel int

WCAGLevel represents WCAG conformance levels.

const (
	// WCAGAA is the minimum WCAG 2.1 Level AA compliance
	WCAGAA WCAGLevel = iota
	// WCAGAAA is the enhanced WCAG 2.1 Level AAA compliance
	WCAGAAA
)

type WhitePoint ΒΆ added in v1.0.1

type WhitePoint int

WhitePoint represents a white point for chromatic adaptation

const (
	// WhiteD65 is the standard white point for most RGB spaces (6500K)
	WhiteD65 WhitePoint = iota
	// WhiteD50 is used by ProPhoto RGB and ICC LAB (5000K)
	WhiteD50
)

type XYZ ΒΆ

type XYZ struct {
	X, Y, Z, A float64
}

XYZ represents a color in the CIE XYZ color space. This is an intermediate color space used for conversions.

func NewXYZ ΒΆ

func NewXYZ(x, y, z, a float64) *XYZ

NewXYZ creates a new XYZ color.

func ToXYZ ΒΆ

func ToXYZ(c Color) *XYZ

ToXYZ converts an RGBA color to XYZ.

func (*XYZ) Alpha ΒΆ

func (c *XYZ) Alpha() float64

Alpha implements Color.

func (*XYZ) RGBA ΒΆ

func (c *XYZ) RGBA() (r, g, b, a float64)

RGBA converts XYZ to RGBA (sRGB).

func (*XYZ) WithAlpha ΒΆ

func (c *XYZ) WithAlpha(alpha float64) Color

WithAlpha implements Color.

Directories ΒΆ

Path Synopsis
cmd
color-gen command
generate_gamuts command
generate_gifs command
generate_models command
generate_stops command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL