# .toRGB()

Read a color's red, green and blue channels, even past sRGB, to hand to other graphics code.

Hand a color to Core Graphics, Metal, a chart library or a server with `toRGB()`. It takes nothing and returns an `RGBColor`: red, green, blue and alpha from 0 to 1, or past 0 and 1 for a color beyond sRGB:

```swift
Color(hex: "#00B386").toRGB()   // RGBColor(r: 0, g: 0.702, b: 0.525, alpha: 1)
brand._600.toRGB()              // RGBColor(r: -0.178, g: 0.527, b: 0.372, alpha: 1)
```

## Reading a stop beyond sRGB

A palette stop beyond sRGB has a channel below 0 or above 1. That's [extended sRGB](https://colortokenskit.com/reference/glossary/index.md#extended-srgb): sRGB's channels, allowed past their ends for wider colors, and SwiftUI, UIKit and AppKit keep them that way. Hex can't, so [`getHexString()`](https://colortokenskit.com/api/get-hex-string/index.md) clamps each channel:

```swift
let fill = brand._600                 // a stop of the travel app's brand, beyond sRGB
fill.toRGB()                          // RGBColor(r: -0.178, g: 0.527, b: 0.372)
fill.toColor().getHexString()         // "00865F", with red clamped to 0
```

To pass such a color on without losing it, keep its name or its `toRGB()` value, not its hex.

## Back to a Color

`RGBColor` has no `toColor()`. Make a `Color` with SwiftUI's own initializer, which keeps channels past 0 and 1:

```swift
let rgb = brand._600.toRGB()
let fill = Color(red: rgb.r, green: rgb.g, blue: rgb.b, opacity: rgb.alpha)
```

Where UIKit is available, `rgb.color()` gives a `UIColor` instead.

## Changing one channel

`with(r:g:b:alpha:)` returns a copy with the values you pass and keeps the rest:

```swift
let rgb = Color(hex: "#00B386").toRGB()
let faded = rgb.with(alpha: 0.5)   // RGBColor(r: 0, g: 0.702, b: 0.525, alpha: 0.5)
```

## How it behaves

`toRGB()` reads the color as extended sRGB, so a Display P3 color comes through unchanged and every other conversion starts from these numbers. A token has two values, and `toRGB()` reads one: on iOS 17, macOS 14 and later, the light-mode value.

`relativeLuminance` gives the color's WCAG relative luminance, from 0 for black to 1 for white, and [`contrastRatio(to:method:)`](https://colortokenskit.com/api/contrast-ratio/index.md) compares two colors with it. `lerp(_:t:)` mixes two `RGBColor` values in a straight line; [`.lerp(_:t:)`](https://colortokenskit.com/api/lerp/index.md) compares the spaces to mix in.

From an `RGBColor` you can go to every other type: `toXYZ()`, `toLAB()`, `toLCH()`, `toOKLab()` and `toOKLCH()`.

## API

```swift
public extension Color {
    func toRGB() -> RGBColor
}

public struct RGBColor: Hashable, Sendable {
    public let r: CGFloat       // 0 to 1 inside sRGB, past them beyond it
    public let g: CGFloat
    public let b: CGFloat
    public let alpha: CGFloat   // 0 to 1

    public init(r: CGFloat, g: CGFloat, b: CGFloat, alpha: CGFloat)
    public init(color: Color)

    public func with(
        r: CGFloat? = nil, g: CGFloat? = nil, b: CGFloat? = nil, alpha: CGFloat? = nil
    ) -> RGBColor
    public var relativeLuminance: CGFloat { get }
    public func lerp(_ other: RGBColor, t: CGFloat) -> RGBColor

    public func toXYZ() -> XYZColor
    public func toLAB() -> LABColor
    public func toLCH() -> LCHColor
    public func toOKLab() -> OKLabColor
    public func toOKLCH() -> OKLCHColor
    public func color() -> UIColor   // where UIKit is available
}
```

`toRGB()` takes no parameters. `ProTheme` has it too, so a stop converts directly, as in `brand._600.toRGB()`.

## Sources

- [Color+ColorSpaces.swift](https://github.com/metasidd/ColorTokensKit-Swift/blob/main/Sources/ColorTokensKit/Platform/SwiftUI/Color+ColorSpaces.swift), which defines `toRGB()` on `Color`.
- The [RGB](https://github.com/metasidd/ColorTokensKit-Swift/tree/main/Sources/ColorTokensKit/ColorSpace/RGB) folder, which defines `RGBColor`, and [ContrastRatio.swift](https://github.com/metasidd/ColorTokensKit-Swift/blob/main/Sources/ColorTokensKit/Accessibility/ContrastRatio.swift), which adds `relativeLuminance`.

## See also

- [.getHexString()](https://colortokenskit.com/api/get-hex-string/index.md): Log a color or hand it to a design tool as an sRGB hex string, with alpha when it's translucent.
- [.toOKLCH()](https://colortokenskit.com/api/to-oklch/index.md): Read a color's lightness, chroma and hue the way the palette sees them, to compare or adjust it.
- [.contrastRatio(to:method:)](https://colortokenskit.com/api/contrast-ratio/index.md): Check WCAG 2 and APCA contrast in Swift, and keep your color pairs passing with a unit test.
- [Fitting colors into Display P3](https://colortokenskit.com/under-the-hood/gamut-mapping/index.md): Stay inside Display P3 without losing contrast: chroma drops, lightness holds.

---

From ColorTokensKit, by Penguin Design Ventures: https://colortokenskit.com/api/to-rgb/ (updated September 26, 2026).
