colors
Parse CSS colors, convert between RGB, hex and HSL, and lighten, darken and mix them.
import "std:colors"std:colors reads colors in many shapes (#ff8800, rgb(255, 136, 0), tomato, hsl(32, 100%, 50%)), changes them the way people think about them (lighter, darker, a blend of two) and writes them back out as hex text.
A color here is one of three things, and the functions accept any of them where they take a color:
- a CSS color string such as
"#336699"or"tomato", - an object with
r,g,bandafrom 0 to 255, which is whatcolors.parsereturns, - an
img.Colormade withimg.rgb.
Parsing#
colors.parse(text) returns a result holding {r, g, b, a}:
import "std:colors"
auto orange = colors.parse("#ff8800").unwrap()
log orange
log orange.r orange.g orange.b orange.aAlpha a is opacity: 255 is solid. It reads the common CSS forms:
import "std:colors"
string[] inputs = [
"#f80", "#ff8800", "#ff880080", "rgb(10, 20, 30)", "hsl(120, 100%, 50%)", "red"
]
for text in inputs (
auto c = colors.parse(text).unwrap()
log text colors.stringify(c)
)Text that is not a color is a ParseError:
import "std:colors"
auto bad = colors.parse("not a color")
log bad.isErr()
log bad.unwrapErr().kindWriting colors out#
colors.stringify gives #rrggbb, or #rrggbbaa when the color isn't fully opaque. It accepts any of the color forms:
import "std:colors"
log colors.stringify({r: 255, g: 99, b: 71, a: 255})
log colors.stringify({r: 1, g: 2, b: 3, a: 128})
log colors.stringify("tomato")Lighter, darker, mixed#
lighten and darken move the lightness by an amount from 0 to 1. mix(a, b, amount) blends two colors, where 0 is all a and 1 is all b. All three return hex text:
import "std:colors"
string base = "#336699"
log colors.lighten(base, 0.2)
log colors.darken(base, 0.2)
log colors.mix("#ff0000", "#0000ff", 0.5)
log colors.mix("black", "white", 0.25)These work on lightness in HSL, which is how people judge "lighter", rather than adding to the RGB channels.
HSL#
Hue, saturation and lightness make some changes easy that are awkward in RGB, such as rotating the hue to find a related color. toHSL gives {h, s, l, a} with hue in degrees (0 to 360) and the others from 0 to 1. fromHSL goes back:
import "std:colors"
auto hsl = colors.toHSL("#ff8800")
log hsl
log hsl.h
auto shifted = colors.fromHSL({h: hsl.h + 120, s: hsl.s, l: hsl.l})
log shiftedHue 152 is a green, 120 degrees around the wheel from orange.
Example: a palette from one color#
Starting from a brand color, build a scale for a UI: three tints, the base, and two shades.
import "std:colors"
string brand = "#336699"
string[] steps = []
for amount in [0.3, 0.15] (
steps.append(colors.lighten(brand, amount))
)
steps.append(brand)
for amount in [0.1, 0.2] (
steps.append(colors.darken(brand, amount))
)
log stepsColors in images#
The three color shapes convert freely, so img.rgb(255, 0, 0) can go into colors.lighten, and a hex string or the object from colors.parse can go into image.fill. Use whichever is handy and let colors.stringify normalise to text.
colors.parse("not a color") is called. What happens?
The opposite color
Finish complement so it returns the color opposite on the wheel: the same saturation and lightness with the hue turned 180 degrees (wrap past 360 with % 360).
#0077ff #00ffff
API reference#
12 members, generated from the std:colors source of OSL 9.3.0.
Functions
colors.darken(any color, number amount) stringdarken lowers color's HSL lightness by amount (0 to 1, where 1 is the whole range, so darken(c, 1) is black). Returns "#rrggbb" or "#rrggbbaa". Throws ValueError for an invalid color or amount.
colors.fromHSL(object hsl) stringfromHSL converts {h, s, l, a} (as toHSL returns it; a is optional and defaults to 255) to a "#rrggbb" or "#rrggbbaa" color. The hue wraps around 360 degrees. Throws ValueError for a missing key, saturation or lightness outside 0 to 1, or alpha outside 0-255.
colors.gray(any v) objectDeprecated. Deprecated: use {r: v, g: v, b: v} instead.
gray builds a grayscale {Y} from a channel that wraps modulo 256.
colors.hex(any hex) objectDeprecated. Deprecated: use colors.parse(text) instead, which reports invalid input.
hex parses "#rrggbb" or "#rrggbbaa" into {R, G, B, A}, giving opaque black for anything else.
colors.lighten(any color, number amount) stringlighten raises color's HSL lightness by amount (0 to 1, where 1 is the whole range, so lighten(c, 1) is white). Returns "#rrggbb" or "#rrggbbaa". Throws ValueError for an invalid color or amount.
colors.mix(any a, any b, number amount) stringmix blends two colors channel by channel, alpha included: amount 0 gives a, 1 gives b and 0.5 the midpoint. Returns "#rrggbb" or "#rrggbbaa". Throws ValueError for an invalid color or an amount outside 0 to 1.
colors.nrgba(any r, any g, any b, any a) objectDeprecated. Deprecated: use {r: r, g: g, b: b, a: a} instead.
nrgba builds {R, G, B, A} from four channels, which wrap modulo 256.
colors.parse(string text) result<{a: int, b: int, g: int, r: int}, error>parse reads a CSS color and returns it as {r, g, b, a} with 0-255 channels, which every OSL color argument accepts. It understands "#rgb", "#rgba", "#rrggbb", "#rrggbbaa", the CSS color names (such as "red" and "rebeccapurple"), "transparent", rgb()/rgba() and hsl()/hsla() with commas or spaces, percentages and an optional "/ alpha", in any case. Fails with ParseError for anything else.
colors.rgb(any r, any g, any b) objectDeprecated. Deprecated: use {r: r, g: g, b: b} or colors.stringify instead.
rgb builds an opaque {R, G, B, A} from three channels, which wrap modulo 256.
colors.rgba(any r, any g, any b, any a) objectDeprecated. Deprecated: use {r: r, g: g, b: b, a: a} or colors.stringify instead.
rgba builds {R, G, B, A} from four channels, which wrap modulo 256.
colors.stringify(any color) stringstringify returns color as "#rrggbb", or "#rrggbbaa" when it isn't fully opaque. color is a CSS color string or {r, g, b, a}. Throws ValueError for an invalid color.
colors.toHSL(any color) {a: int, h: number, l: number, s: number}toHSL converts color to {h, s, l, a}: hue in degrees from 0 to 360, saturation and lightness from 0 to 1, and alpha 0-255. Throws ValueError for an invalid color.