colorful

package
v0.0.16 Latest Latest
Warning

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

Go to latest
Published: Apr 4, 2022 License: BSD-3-Clause, MIT Imports: 8 Imported by: 0

README

go-colorful

go reportcard

A library for playing with colors in Go. Supports Go 1.13 onwards.

Why?

I love games. I make games. I love detail and I get lost in detail. One such detail popped up during the development of Memory Which Does Not Suck, when we wanted the server to assign the players random colors. Sometimes two players got very similar colors, which bugged me. The very same evening, I want hue was the top post on HackerNews' frontpage and showed me how to Do It Right™. Last but not least, there was no library for handling color spaces available in go. Colorful does just that and implements Go's color.Color interface.

What?

Go-Colorful stores colors in RGB and provides methods from converting these to various color-spaces. Currently supported colorspaces are:

  • RGB: All three of Red, Green and Blue in [0..1].
  • HSL: Hue in [0..360], Saturation and Luminance in [0..1]. For legacy reasons; please forget that it exists.
  • HSV: Hue in [0..360], Saturation and Value in [0..1]. You're better off using LABLCH, see below.
  • Hex RGB: The "internet" color format, as in #FF00FF.
  • Linear RGB: See gamma correct rendering.
  • CIE-XYZ: CIE's standard color space, almost in [0..1].
  • CIE-xyY: encodes chromacity in x and y and luminance in Y, all in [0..1]
  • CIE-L*a*b*: A perceptually uniform color space, i.e. distances are meaningful. L* in [0..1] and a*, b* almost in [-1..1].
  • CIE-L*u*v*: Very similar to CIE-L*a*b*, there is no consensus on which one is "better".
  • CIE-L*C*h° (LABLCH): This is generally the most useful one; CIE-L*a*b* space in polar coordinates, i.e. a better HSV. H° is in [0..360], C* almost in [-1..1] and L* as in CIE-L*a*b*.
  • CIE LCh(uv): Called LuvLCh in code, this is a cylindrical transformation of the CIE-L*u*v* color space. Like LABLCH above: H° is in [0..360], C* almost in [-1..1] and L* as in CIE-L*u*v*.
  • HSLuv: The better alternative to HSL, see here and here. Hue in [0..360], Saturation and Luminance in [0..1].
  • HPLuv: A variant of HSLuv. The color space is smoother, but only pastel colors can be included. Because the valid colors are limited, it's easy to get invalid Saturation values way above 1.0, indicating the color can't be represented in HPLuv beccause it's not pastel.

For the colorspaces where it makes sense (XYZ, Lab, Luv, HCl), the D65 is used as reference white by default but methods for using your own reference white are provided.

A coordinate being almost in a range means that generally it is, but for very bright colors and depending on the reference white, it might overflow this range slightly. For example, C* of #0000ff is 1.338.

Unit-tests are provided.

Nice, but what's it useful for?

  • Converting color spaces. Some people like to do that.
  • Blending (interpolating) between colors in a "natural" look by using the right colorspace.
  • Generating random colors under some constraints (e.g. colors of the same shade, or shades of one color.)
  • Generating gorgeous random palettes with distinct colors of a same temperature.

What not (yet)?

There are a few features which are currently missing and might be useful. I just haven't implemented them yet because I didn't have the need for it. Pull requests welcome.

  • Sorting colors (potentially using above mentioned distances)

So which colorspace should I use?

It depends on what you want to do. I think the folks from I want hue are on-spot when they say that RGB fits to how * screens produce* color, CIE L*a*b* fits how humans perceive color and LABLCH fits how humans think colors.

Whenever you'd use HSV, rather go for CIE-L*C*h°. for fixed lightness L* and chroma C* values, the hue angle h° rotates through colors of the same perceived brightness and intensity.

How?

Installing

Installing the library is as easy as

$ go get github.com/lucasb-eyer/go-colorful

The package can then be used through an

import "github.com/lucasb-eyer/go-colorful"
Basic usage

Create a beautiful blue color using different source space:

// Any of the following should be the same
c := colorful.Color{0.313725, 0.478431, 0.721569}
c, err := colorful.Hex("#517AB8")
if err != nil {
    log.Fatal(err)
}
c = colorful.HSV(216.0, 0.56, 0.722)
c = colorful.XYZ(0.189165, 0.190837, 0.480248)
c = colorful.XYY(0.219895, 0.221839, 0.190837)
c = colorful.Lab(0.507850, 0.040585,-0.370945)
c = colorful.Luv(0.507849,-0.194172,-0.567924)
c = colorful.Hcl(276.2440, 0.373160, 0.507849)
fmt.Printf("RGB values: %v, %v, %v", c.R, c.G, c.B)

And then converting this color back into various color spaces:

hex := c.Hex()
h, s, v := c.HSV()
x, y, z := c.XYZ()
x, y, Y := c.XYY()
l, a, b := c.Lab()
l, u, v := c.Luv()
h, c, l := c.Hcl()

Note that, because of Go's unfortunate choice of requiring an initial uppercase, the name of the functions relating to the xyY space are just off. If you have any good suggestion, please open an issue. (I don't consider XyY good.)

The color.Color interface

Because a colorful.Color implements Go's color.Color interface (found in the image/color package), it can be used anywhere that expects a color.Color.

Furthermore, you can convert anything that implements the color.Color interface into a colorful.Color using the MakeColor function:

c, ok := colorful.MakeColor(color.Gray16{12345})

Caveat: Be aware that this latter conversion (using MakeColor) hits a corner-case when alpha is exactly zero. Because color.Color uses pre-multiplied alpha colors, this means the RGB values are lost (set to 0) and it's impossible to recover them. In such a case MakeColor will return false as its second value.

Comparing colors

In the RGB color space, the Euclidian distance between colors doesn't correspond to visual/perceptual distance. This means that two pairs of colors which have the same distance in RGB space can look much further apart. This is fixed by the CIE-L*a*b*, CIE-L*u*v* and CIE-L*C*h° color spaces. Thus you should only compare colors in any of these space. (Note that the distance in CIE-L*a*b* and CIE-L*C*h° are the same, since it's the same space but in cylindrical coordinates)

Color distance comparison

The two colors shown on the top look much more different than the two shown on the bottom. Still, in RGB space, their distance is the same. Here is a little example program which shows the distances between the top two and bottom two colors in RGB, CIE-L*a*b* and CIE-L*u*v* space. You can find it in doc/colordist/colordist.go.

package main

import "fmt"
import "github.com/lucasb-eyer/go-colorful"

func main() {
	c1a := colorful.Color{150.0 / 255.0, 10.0 / 255.0, 150.0 / 255.0}
	c1b := colorful.Color{53.0 / 255.0, 10.0 / 255.0, 150.0 / 255.0}
	c2a := colorful.Color{10.0 / 255.0, 150.0 / 255.0, 50.0 / 255.0}
	c2b := colorful.Color{99.9 / 255.0, 150.0 / 255.0, 10.0 / 255.0}

	fmt.Printf("DistanceRGB:       c1: %v\tand c2: %v\n", c1a.DistanceRGB(c1b), c2a.DistanceRGB(c2b))
	fmt.Printf("DistanceLab:       c1: %v\tand c2: %v\n", c1a.DistanceLab(c1b), c2a.DistanceLab(c2b))
	fmt.Printf("DistanceLuv:       c1: %v\tand c2: %v\n", c1a.DistanceLuv(c1b), c2a.DistanceLuv(c2b))
	fmt.Printf("DistanceCIE76:     c1: %v\tand c2: %v\n", c1a.DistanceCIE76(c1b), c2a.DistanceCIE76(c2b))
	fmt.Printf("DistanceCIE94:     c1: %v\tand c2: %v\n", c1a.DistanceCIE94(c1b), c2a.DistanceCIE94(c2b))
	fmt.Printf("DistanceCIEDE2000: c1: %v\tand c2: %v\n", c1a.DistanceCIEDE2000(c1b), c2a.DistanceCIEDE2000(c2b))
}

Running the above program shows that you should always prefer any of the CIE distances:

$ go run colordist.go
DistanceRGB:       c1: 0.3803921568627451	and c2: 0.3858713931171159
DistanceLab:       c1: 0.32048458312798056	and c2: 0.24397151758565272
DistanceLuv:       c1: 0.5134369614199698	and c2: 0.2568692839860636
DistanceCIE76:     c1: 0.32048458312798056	and c2: 0.24397151758565272
DistanceCIE94:     c1: 0.19799168128511324	and c2: 0.12207136371167401
DistanceCIEDE2000: c1: 0.17274551120971166	and c2: 0.10665210031428465

It also shows that DistanceLab is more formally known as DistanceCIE76 and has been superseded by the slightly more accurate, but much more expensive DistanceCIE94 and DistanceCIEDE2000.

Note that AlmostEqualRGB is provided mainly for (unit-)testing purposes. Use it only if you really know what you're doing. It will eat your cat.

Blending colors

Blending is highly connected to distance, since it basically "walks through" the colorspace thus, if the colorspace maps distances well, the walk is "smooth".

Colorful comes with blending functions in RGB, HSV and any of the LAB spaces. Of course, you'd rather want to use the blending functions of the LAB spaces since these spaces map distances well but, just in case, here is an example showing you how the blendings (#fdffcc to #242a42) are done in the various spaces:

Blending colors in different spaces.

What you see is that HSV is really bad: it adds some green, which is not present in the original colors at all! RGB is much better, but it stays light a little too long. LUV and LAB both hit the right lightness but LAB has a little more color. LABLCH works in the same vein as HSV (both cylindrical interpolations) but it does it right in that there is no green appearing and the lighthness changes in a linear manner.

While this seems all good, you need to know one thing: When interpolating in any of the CIE color spaces, you might get invalid RGB colors! This is important if the starting and ending colors are user-input or random. An example of where this happens is when blending between #eeef61 and #1e3140:

Invalid RGB colors may crop up when blending in CIE spaces.

You can test whether a color is a valid RGB color by calling the IsValid method and indeed, calling IsValid will return false for the redish colors on the bottom. One way to "fix" this is to get a valid color close to the invalid one by calling Clamped, which always returns a nearby valid color. Doing this, we get the following result, which is satisfactory:

Fixing invalid RGB colors by clamping them to the valid range.

The following is the code creating the above three images; it can be found in doc/colorblend/colorblend.go

package main

import "fmt"
import "github.com/lucasb-eyer/go-colorful"
import "image"
import "image/draw"
import "image/png"
import "os"

func main() {
    blocks := 10
    blockw := 40
    img := image.NewRGBA(image.Rect(0,0,blocks*blockw,200))

    c1, _ := colorful.Hex("#fdffcc")
    c2, _ := colorful.Hex("#242a42")

    // Use these colors to get invalid RGB in the gradient.
    //c1, _ := colorful.Hex("#EEEF61")
    //c2, _ := colorful.Hex("#1E3140")

    for i := 0 ; i < blocks ; i++ {
        draw.Draw(img, image.Rect(i*blockw,  0,(i+1)*blockw, 40), &image.Uniform{c1.BlendHSV(c2, float64(i)/float64(blocks-1))}, image.Point{}, draw.Src)
        draw.Draw(img, image.Rect(i*blockw, 40,(i+1)*blockw, 80), &image.Uniform{c1.BlendLuv(c2, float64(i)/float64(blocks-1))}, image.Point{}, draw.Src)
        draw.Draw(img, image.Rect(i*blockw, 80,(i+1)*blockw,120), &image.Uniform{c1.BlendRGB(c2, float64(i)/float64(blocks-1))}, image.Point{}, draw.Src)
        draw.Draw(img, image.Rect(i*blockw,120,(i+1)*blockw,160), &image.Uniform{c1.BlendLab(c2, float64(i)/float64(blocks-1))}, image.Point{}, draw.Src)
        draw.Draw(img, image.Rect(i*blockw,160,(i+1)*blockw,200), &image.Uniform{c1.BlendHcl(c2, float64(i)/float64(blocks-1))}, image.Point{}, draw.Src)

        // This can be used to "fix" invalid colors in the gradient.
        //draw.Draw(img, image.Rect(i*blockw,160,(i+1)*blockw,200), &image.Uniform{c1.BlendHcl(c2, float64(i)/float64(blocks-1)).Clamped()}, image.Point{}, draw.Src)
    }

    toimg, err := os.Create("colorblend.png")
    if err != nil {
        fmt.Printf("Error: %v", err)
        return
    }
    defer toimg.Close()

    png.Encode(toimg, img)
}
Generating color gradients

A very common reason to blend colors is creating gradients. There is an example program in doc/gradientgen.go; it doesn't use any API which hasn't been used in the previous example code, so I won't bother pasting the code in here. Just look at that gorgeous gradient it generated in LABLCH space:

Getting random colors

It is sometimes necessary to generate random colors. You could simply do this on your own by generating colors with random values. By restricting the random values to a range smaller than [0..1] and using a space such as CIE-H*C*l° or HSV, you can generate both random shades of a color or random colors of a lightness:

random_blue := colorful.Hcl(180.0+rand.Float64()*50.0, 0.2+rand.Float64()*0.8, 0.3+rand.Float64()*0.7)
random_dark := colorful.Hcl(rand.Float64()*360.0, rand.Float64(), rand.Float64()*0.4)
random_light := colorful.Hcl(rand.Float64()*360.0, rand.Float64(), 0.6+rand.Float64()*0.4)

Since getting random "warm" and "happy" colors is quite a common task, there are some helper functions:

colorful.WarmColor()
colorful.HappyColor()
colorful.FastWarmColor()
colorful.FastHappyColor()

The ones prefixed by Fast are faster but less coherent since they use the HSV space as opposed to the regular ones which use CIE-L*C*h° space. The following picture shows the warm colors in the top two rows and happy colors in the bottom two rows. Within these, the first is the regular one and the second is the fast one.

Warm, fast warm, happy and fast happy random colors, respectively.

Don't forget to initialize the random seed! You can see the code used for generating this picture in doc/colorgens/colorgens.go.

Getting random palettes

As soon as you need to generate more than one random color, you probably want them to be distinguishible. Playing against an opponent which has almost the same blue as I do is not fun. This is where random palettes can help.

These palettes are generated using an algorithm which ensures that all colors on the palette are as distinguishible as possible. Again, there is a Fast method which works in HSV and is less perceptually uniform and a non-Fast method which works in CIE spaces. For more theory on SoftPalette, check out I want hue. Yet again, there is a Happy and a Warm version, which do what you expect, but now there is an additional Soft version, which is more configurable: you can give a constraint on the color space in order to get colors within a certain feel.

Let's start with the simple methods first, all they take is the amount of colors to generate, which could, for example, be the player count. They return an array of colorful.Color objects:

pal1, err1 := colorful.WarmPalette(10)
pal2 := colorful.FastWarmPalette(10)
pal3, err3 := colorful.HappyPalette(10)
pal4 := colorful.FastHappyPalette(10)
pal5, err5 := colorful.SoftPalette(10)

Note that the non-fast methods may fail if you ask for way too many colors. Let's move on to the advanced one, namely SoftPaletteEx. Besides the color count, this function takes a SoftPaletteSettings object as argument. The interesting part here is its CheckColor member, which is a boolean function taking three floating points as arguments: l, a and b. This function should return true for colors which lie within the region you want and false otherwise. The other members are Iteration, which should be within [5..100] where higher means slower but more exact palette, and ManySamples which you should set to true in case your CheckColor constraint rejects a large part of the color space.

For example, to create a palette of 10 brownish colors, you'd call it like this:

func isbrowny(l, a, b float64) bool {
    h, c, L := colorful.LabToHcl(l, a, b)
    return 10.0 < h && h < 50.0 && 0.1 < c && c < 0.5 && L < 0.5
}
// Since the above function is pretty restrictive, we set ManySamples to true.
brownies := colorful.SoftPaletteEx(10, colorful.SoftPaletteSettings{isbrowny, 50, true})

The following picture shows the palettes generated by all of these methods (sourcecode in doc/palettegens/palettegens.go), in the order they were presented, i.e. from top to bottom: Warm , FastWarm, Happy, FastHappy, Soft, SoftEx(isbrowny). All of them contain some randomness, so YMMV.

All example palettes

Again, the code used for generating the above image is available as doc/palettegens/palettegens.go .

Sorting colors

TODO: Sort using dist fn.

Using linear RGB for computations

There are two methods for transforming RGB<->Linear RGB: a fast and almost precise one, and a slow and precise one.

r, g, b := colorful.Hex("#FF0000").FastLinearRGB()

TODO: describe some more.

Want to use some other reference point?
c := colorful.LabWhiteRef(0.507850, 0.040585,-0.370945, colorful.D50)
l, a, b := c.LabWhiteRef(colorful.D50)
Reading and writing colors from databases

The type HexColor makes it easy to store colors as strings in a database. It implements the https://godoc.org/database/sql#Scanner and database/sql/driver.Value interfaces which provide automatic type conversion.

Example:

var hc HexColor
_, err := db.QueryRow("SELECT '#ff0000';").Scan(&hc)
// hc == HexColor{R: 1, G: 0, B: 0}; err == nil

FAQ

Q: I get all f!@#ed up values! Your library sucks!

A: You probably provided values in the wrong range. For example, RGB values are expected to reside between 0 and 1, * not* between 0 and 255. Normalize your colors.

Q: Lab/Luv/HCl seem broken! Your library sucks!

They look like this:

A: You're likely trying to generate and display colors that can't be represented by RGB, and thus monitors. When you're trying to convert, say, LABLCH(190.0, 1.0, 1.0).RGB255(), you're asking for RGB values of (-2105.254 300.680 286.185) , which clearly don't exist, and the RGB255 function just casts these numbers to uint8, creating wrap-around and what looks like a completely broken gradient. What you want to do, is either use more reasonable values of colors which actually exist in RGB, or just Clamp() the resulting color to its nearest existing one, living with the consequences: LABLCH(190.0, 1.0, 1.0).Clamp().RGB255(). It will look something like this:

Here's an issue going in-depth about this, as well as my answer, both with code and pretty pictures. Also note that this was somewhat covered above in the "Blending colors" section.

Q: In a tight loop, conversion to Lab/Luv/HCl/... are slooooow!

A: Yes, they are. This library aims for correctness, readability, and modularity; it wasn't written with speed in mind. A large part of the slowness comes from these conversions going through LinearRGB which uses powers. I implemented a fast approximation to LinearRGB called FastLinearRGB by using Taylor approximations. The approximation is roughly 5x faster and precise up to roughly 0.5%, the major caveat being that if the input values are outside the range 0-1, accuracy drops dramatically. You can use these in your conversions as follows:

col := // Get your color somehow
l, a, b := XYZToLab(LinearRGBToXYZ(col.LinearRGB()))

If you need faster versions of Distance* and Blend* that make use of this fast approximation, feel free to implement them and open a pull-request, I'll happily accept.

The derivation of these functions can be followed in [this Jupyter notebook](doc/LinearRGB Approximations.ipynb). Here's the main figure showing the approximation quality:

approximation quality

More speed could be gained by using SIMD instructions in many places. You can also get more speed for specific conversions by approximating the full conversion function, but that is outside the scope of this library. Thanks to @ZirconiumX for starting this investigation, see issue #18 for details.

Q: Why would MakeColor ever fail!?

A: MakeColor fails when the alpha channel is zero. In that case, the conversion is undefined. See issue 21 as well as the short caveat note in the "The color.Color interface" section above.

Who?

This library was developed by Lucas Beyer with contributions from Bastien Dejean (@baskerville), Phil Kulak (@pkulak) and Christian Muehlhaeuser (@muesli).

It is now maintained by makeworld (@makeworld-the-better-one).

License

This repo is under the MIT license, see LICENSE for details.

Documentation

Overview

Package colorful implements functions for working with colors.

colorful is adapted from github.com/lucasb-eyer/go-colorful. colorful has been adapted to favor brevity (e.g. certain functions panic instead of returning errors) and is probably not suited for general usage.

Index

Constants

View Source
const Delta = 1.0 / 255.0

Delta is the tolerance used when comparing colors using AlmostEqualRGB.

Variables

View Source
var (
	D50 = [3]float64{0.96422, 1.00000, 0.82521}
	D65 = [3]float64{0.95047, 1.00000, 1.08883}
)

D65 is the default reference white point.

View Source
var (
	Red   = Hex("#FF0000")
	Green = Hex("#00FF00")
	Blue  = Hex("#0000FF")
	Black = Hex("#000000")
	White = Hex("#FFFFFF")
)

Functions

func HPLuvToLuvLCh

func HPLuvToLuvLCh(h, s, l float64) (float64, float64, float64)

func HSLuvToLuvLCh

func HSLuvToLuvLCh(h, s, l float64) (float64, float64, float64)

func LABLCHToLAB added in v0.0.8

func LABLCHToLAB(h, c, l float64) (L, a, b float64)

func LABToLABLCH added in v0.0.8

func LABToLABLCH(L, a, b float64) (h, c, l float64)

func LABToXYZ added in v0.0.8

func LABToXYZ(l, a, b float64) (x, y, z float64)

func LABToXYZWhiteRef added in v0.0.8

func LABToXYZWhiteRef(l, a, b float64, wref [3]float64) (x, y, z float64)

func LinearRGBToXYZ added in v0.0.8

func LinearRGBToXYZ(r, g, b float64) (x, y, z float64)

func LuvLChToHPLuv

func LuvLChToHPLuv(l, c, h float64) (float64, float64, float64)

func LuvLChToHSLuv

func LuvLChToHSLuv(l, c, h float64) (float64, float64, float64)

func LuvLChToLuv

func LuvLChToLuv(l, c, h float64) (L, u, v float64)

func LuvToLuvLCh

func LuvToLuvLCh(L, u, v float64) (l, c, h float64)

func LuvToXYZ added in v0.0.8

func LuvToXYZ(l, u, v float64) (x, y, z float64)

func LuvToXYZWhiteRef added in v0.0.8

func LuvToXYZWhiteRef(l, u, v float64, wref [3]float64) (x, y, z float64)

func XYYToXYZ added in v0.0.8

func XYYToXYZ(x, y, Y float64) (X, Yout, Z float64)

func XYZToLAB added in v0.0.8

func XYZToLAB(x, y, z float64) (l, a, b float64)

func XYZToLABWhiteRef added in v0.0.8

func XYZToLABWhiteRef(x, y, z float64, wref [3]float64) (l, a, b float64)

func XYZToLinearRGB added in v0.0.8

func XYZToLinearRGB(x, y, z float64) (r, g, b float64)

XYZToLinearRGB converts from CIE XYZ-space to Linear RGB space.

func XYZToLuv added in v0.0.8

func XYZToLuv(x, y, z float64) (l, a, b float64)

func XYZToLuvWhiteRef added in v0.0.8

func XYZToLuvWhiteRef(x, y, z float64, wref [3]float64) (l, u, v float64)

func XYZToXYY added in v0.0.8

func XYZToXYY(X, Y, Z float64) (x, y, Yout float64)

func XYZToXYYWhiteRef added in v0.0.8

func XYZToXYYWhiteRef(X, Y, Z float64, wref [3]float64) (x, y, Yout float64)

Types

type Color

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

Color holds the RGBA values of a color.

func BlendHSV added in v0.0.8

func BlendHSV(c1, c2 Color, t float64) Color

BlendHSV blends c1 with c2 using the HSV color model.

func BlendLAB added in v0.0.8

func BlendLAB(c1, c2 Color, t float64) Color

BlendLAB blends c1 and c2 in the L*a*b* color space.

func BlendLABLCH added in v0.0.8

func BlendLABLCH(col1, col2 Color, t float64) Color

BlendLABLCH blends col1 with col2 in the CIE-L*C*h° color space.

func BlendLUV added in v0.0.8

func BlendLUV(c1, c2 Color, t float64) Color

BlendLUV blends c1 and c2 in the CIE-L*u*v* color space.

func BlendLUVLCh added in v0.0.8

func BlendLUVLCh(col1, col2 Color, t float64) Color

BlendLUVLCh blends col1 and col2 in the cylindrical CIELUV color space.

func BlendLinearRGB added in v0.0.8

func BlendLinearRGB(c1, c2 Color, t float64) Color

BlendLinearRGB blends c1 and c2 in the linear RGB color space.

func BlendOklab added in v0.0.8

func BlendOklab(c1, c2 Color, t float64) Color

BlendOklab blends c1 to c2 in the Oklab colorspace and returns the color at position t.

func BlendRGB added in v0.0.8

func BlendRGB(c1, c2 Color, t float64) Color

BlendRGB blends c1 with c2 in the sRGB color space. Prefer BlendLAB, BlendLUV or BlendLABLCH over this.

func FastLinearRGB added in v0.0.8

func FastLinearRGB(r, g, b float64) Color

FastLinearRGB is a faster LinearRGB that is almost as accurate. FastLinearRGB is only accurate for valid RGB colors, i.e. colors with RGB values in the [0,1] range.

func FromColor

func FromColor(col color.Color) Color

FromColor constructs a colorful.Color from a color.Color

func HPLuv

func HPLuv(h, s, l float64) Color

HPLuv creates a new Color from values in the HPLuv color space. Hue in [0..360], a Saturation [0..1], and a Luminance (lightness) in [0..1].

The returned color values are clamped (using .Clamped), so this will never output an invalid color.

func HSL added in v0.0.8

func HSL(h, s, l float64) Color

HSL creates a color from the provided HSL coordinates.

func HSLuv

func HSLuv(h, s, l float64) Color

HSLuv creates a new Color from the provided HSLuv color space coordinates. Hue in [0..360], a Saturation [0..1], and a Luminance (lightness) in [0..1].

The returned color values are clamped (using .Clamped), so this will never output an invalid color.

func HSV added in v0.0.8

func HSV(H, S, V float64) Color

HSV creates a new Color given a Hue in [0..360], a Saturation and a Value in [0..1]

func Hex

func Hex(s string) Color

Hex parses and returns the Color for a hex triplet or quadruplet from s. The string must begin with a leading '#'. Hex panics if s cannot be parsed.

func LAB added in v0.0.8

func LAB(l, a, b float64) Color

Generates a color by using data given in CIE L*a*b* space using D65 as reference white. WARNING: many combinations of `l`, `a`, and `b` values do not have corresponding valid RGB values, check the FAQ in the README if you're unsure.

func LABLCH added in v0.0.8

func LABLCH(h, c, l float64) Color

Generates a color by using data given in LABLCH space using D65 as reference white. H values are in [0..360], C and L values are in [0..1]

func LABLCHWhiteRef added in v0.0.8

func LABLCHWhiteRef(h, c, l float64, wref [3]float64) Color

Generates a color by using data given in LABLCH space, taking into account a given reference white. (i.e. the monitor's white) H values are in [0..360], C and L values are in [0..1]

func LABWhiteRef added in v0.0.8

func LABWhiteRef(l, a, b float64, wref [3]float64) Color

Generates a color by using data given in CIE L*a*b* space, taking into account a given reference white. (i.e. the monitor's white)

func LinearRGB added in v0.0.8

func LinearRGB(r, g, b float64) Color

LinearRGB creates a Color using the provided linear RGB triplets.

func Luv

func Luv(l, u, v float64) Color

Generates a color by using data given in CIE L*u*v* space using D65 as reference white. L* is in [0..1] and both u* and v* are in about [-1..1] WARNING: many combinations of `l`, `u`, and `v` values do not have corresponding valid RGB values, check the FAQ in the README if you're unsure.

func LuvLCh

func LuvLCh(l, c, h float64) Color

Generates a color by using data given in LuvLCh space using D65 as reference white. h values are in [0..360], C and L values are in [0..1] WARNING: many combinations of `l`, `c`, and `h` values do not have corresponding valid RGB values, check the FAQ in the README if you're unsure.

func LuvLChWhiteRef

func LuvLChWhiteRef(l, c, h float64, wref [3]float64) Color

Generates a color by using data given in LuvLCh space, taking into account a given reference white. (i.e. the monitor's white) h values are in [0..360], C and L values are in [0..1]

func LuvWhiteRef

func LuvWhiteRef(l, u, v float64, wref [3]float64) Color

Generates a color by using data given in CIE L*u*v* space, taking into account a given reference white. (i.e. the monitor's white) L* is in [0..1] and both u* and v* are in about [-1..1]

func MustParseHex deprecated

func MustParseHex(s string) Color

MustParseHex parses and returns the Color for a hex triplet or quadruplet from s. The string must begin with a leading '#'. MustParseHex panics if s cannot be parsed.

Deprecated: use Hex() instead.

func Oklab

func Oklab(L, a, b float64) Color

Oklab returns a Color with the provided Oklab coordinates.

func ParseHex added in v0.0.8

func ParseHex(scol string) (Color, error)

ParseHex parses and returns the Color for a hex triplet or quadruplet from s. The string must begin with a leading '#'.

func XYY added in v0.0.8

func XYY(x, y, Y float64) Color

XYY creates a Color with the provided CIE xyY color space coordinates.

func XYZ added in v0.0.8

func XYZ(x, y, z float64) Color

XYZ creates a Color from the provided CIE XYZ color space coordinates.

func (Color) AlmostEqualRGB added in v0.0.8

func (col Color) AlmostEqualRGB(c2 Color) bool

AlmostEqualRGB returns true if the colors are equal within the tolerance Delta.

func (Color) BlendHSV added in v0.0.8

func (col Color) BlendHSV(c2 Color, t float64) Color

BlendHSV blends the color with c2 using the HSV color model.

func (Color) BlendLAB added in v0.0.8

func (col Color) BlendLAB(c2 Color, t float64) Color

BlendLAB blends the color with c2 in the L*a*b* color space.

func (Color) BlendLABLCH added in v0.0.8

func (col Color) BlendLABLCH(col2 Color, t float64) Color

BlendLABLCH blends the color with col2 in the CIE-L*C*h° color space.

func (Color) BlendLUV added in v0.0.8

func (col Color) BlendLUV(c2 Color, t float64) Color

BlendLUV blends the color with c2 in the CIE-L*u*v* color space.

func (Color) BlendLUVLCh added in v0.0.8

func (col Color) BlendLUVLCh(col2 Color, t float64) Color

BlendLUVLCh blends the color with col2 in the cylindrical CIELUV color space.

func (Color) BlendLinearRGB added in v0.0.8

func (col Color) BlendLinearRGB(c2 Color, t float64) Color

BlendLinearRGB blends the color with c2 in the linear RGB color space.

func (Color) BlendOklab

func (col Color) BlendOklab(c2 Color, t float64) Color

BlendOklab blends col to c2 in the Oklab colorspace and returns the color at position t.

func (Color) BlendOklabPlus

func (col Color) BlendOklabPlus(c2 Color, t float64) Color

https://www.shadertoy.com/view/ttcyRS

func (Color) BlendRGB added in v0.0.8

func (col Color) BlendRGB(c2 Color, t float64) Color

BlendRGB blends the color with c2 in the sRGB color space. Prefer BlendLAB, BlendLUV or BlendLABLCH over this.

func (Color) Boost added in v0.0.6

func (col Color) Boost(m float64) Color

Boost returns a new color with col's RGB values multiplied by m.

func (Color) Clamped

func (col Color) Clamped() Color

Clamped returns a copy of the color with its RGBA values clamped to the range [0,1].

func (Color) DistanceCIE76

func (col Color) DistanceCIE76(c2 Color) float64

DistanceCIE76 is the same as DistanceLAB.

func (Color) DistanceCIE94

func (col Color) DistanceCIE94(cr Color) float64

Uses the CIE94 formula to calculate color distance. More accurate than DistanceLAB, but also more work.

func (Color) DistanceCIEDE2000

func (col Color) DistanceCIEDE2000(cr Color) float64

DistanceCIEDE2000 uses the Delta E 2000 formula to calculate color distance. It is more expensive but more accurate than both DistanceLAB and DistanceCIE94.

func (Color) DistanceCIEDE2000klch

func (col Color) DistanceCIEDE2000klch(cr Color, kl, kc, kh float64) float64

DistanceCIEDE2000klch uses the Delta E 2000 formula with custom values for the weighting factors kL, kC, and kH.

func (Color) DistanceHPLuv

func (col Color) DistanceHPLuv(c2 Color) float64

DistanceHPLuv calculates Euclidean distance in the HPLuv colorspace. No idea how useful this is.

The Hue value is divided by 100 before the calculation, so that H, S, and L have the same relative ranges.

func (Color) DistanceHSLuv

func (col Color) DistanceHSLuv(c2 Color) float64

DistanceHSLuv calculates Euclidan distance in the HSLuv colorspace. No idea how useful this is.

The Hue value is divided by 100 before the calculation, so that H, S, and L have the same relative ranges.

func (Color) DistanceLAB added in v0.0.8

func (col Color) DistanceLAB(c2 Color) float64

DistanceLAB is a good measure of visual similarity between two colors! A result of 0 would mean identical colors, while a result of 1 or higher means the colors differ a lot.

func (Color) DistanceLinearRGB

func (col Color) DistanceLinearRGB(c2 Color) float64

DistanceLinearRGB computes the distance between the color and c2 in the linear RGB color space. This is not useful for measuring how humans perceive color, but might be useful for other things, like dithering.

func (Color) DistanceLuv

func (col Color) DistanceLuv(c2 Color) float64

DistanceLuv is a good measure of visual similarity between two colors! A result of 0 would mean identical colors, while a result of 1 or higher means the colors differ a lot.

func (Color) DistanceRGB added in v0.0.8

func (col Color) DistanceRGB(c2 Color) float64

DistanceRGB computes the distance between two colors in RGB space. This is not a good measure! Rather do it in LAB space.

func (Color) DistanceRiemersma

func (col Color) DistanceRiemersma(c2 Color) float64

DistanceRiemersma is a color distance algorithm developed by Thiadmer Riemersma. It uses RGB coordinates, but he claims it has similar results to CIELUV. This makes it both fast and accurate.

Sources:

https://www.compuphase.com/cmetric.htm
https://github.com/lucasb-eyer/go-colorful/issues/52

func (Color) FastLinearRGB added in v0.0.8

func (col Color) FastLinearRGB() (r, g, b float64)

FastLinearRGB is a faster LinearRGB that is almost as accurate. FastLinearRGB is only accurate for valid RGB colors, i.e. colors with RGB values in the [0,1] range.

func (Color) HPLuv

func (col Color) HPLuv() (h, s, l float64)

HPLuv returns the Hue, Saturation and Luminance of the color in the HSLuv color space. Hue in [0..360], a Saturation [0..1], and a Luminance (lightness) in [0..1].

Note that HPLuv can only represent pastel colors, and so the Saturation value could be much larger than 1 for colors it can't represent.

func (Color) HSL added in v0.0.8

func (col Color) HSL() (h, s, l float64)

HSL returns the coordinates of the color in the HSL color model. The coordinates returned will fall in the following ranges. Hue - [0,360] Saturation - [0,1] Luminance - [0,1]

func (Color) HSLuv

func (col Color) HSLuv() (h, s, l float64)

HSLuv returns the Hue, Saturation and Luminance of the color in the HSLuv color space. Hue in [0..360], a Saturation [0..1], and a Luminance (lightness) in [0..1].

func (Color) HSV added in v0.0.8

func (col Color) HSV() (h, s, v float64)

HSV returns the Hue [0..360], Saturation and Value [0..1] of the color.

func (Color) Hex

func (col Color) Hex() string

Hex returns the hex "html" representation of the color, as in #ff0080.

func (Color) IsValid

func (col Color) IsValid() bool

IsValid returns true if the color exists in RGB space, i.e. all values lie in the range [0,1].

func (Color) LAB added in v0.0.8

func (col Color) LAB() (l, a, b float64)

Converts the given color to CIE L*a*b* space using D65 as reference white.

func (Color) LABLCH added in v0.0.8

func (col Color) LABLCH() (h, c, l float64)

LABLCH returns the coordinates of the color in the CIE LABLCh color space using D65 as the white reference. H values are in [0..360], C and L values are in [0..1] although C can overshoot 1.0

func (Color) LABLCHWhiteRef added in v0.0.8

func (col Color) LABLCHWhiteRef(wref [3]float64) (h, c, l float64)

LABLCHWhiteRef returns the coordinates of the color in the CIE LABLCh color space using wref as the white reference. H values are in [0..360], C and L values are in [0..1]

func (Color) LABWhiteRef added in v0.0.8

func (col Color) LABWhiteRef(wref [3]float64) (l, a, b float64)

Converts the given color to CIE L*a*b* space, taking into account a given reference white. (i.e. the monitor's white)

func (Color) LinearRGB added in v0.0.8

func (col Color) LinearRGB() (r, g, b float64)

LinearRGB returns the color's RGB triplet in the linear RGB color space.

func (Color) Luv

func (col Color) Luv() (l, u, v float64)

Converts the given color to CIE L*u*v* space using D65 as reference white. L* is in [0..1] and both u* and v* are in about [-1..1]

func (Color) LuvLCh

func (col Color) LuvLCh() (l, c, h float64)

Converts the given color to LuvLCh space using D65 as reference white. h values are in [0..360], C and L values are in [0..1] although C can overshoot 1.0

func (Color) LuvLChWhiteRef

func (col Color) LuvLChWhiteRef(wref [3]float64) (l, c, h float64)

Converts the given color to LuvLCh space, taking into account a given reference white. (i.e. the monitor's white) h values are in [0..360], c and l values are in [0..1]

func (Color) LuvWhiteRef

func (col Color) LuvWhiteRef(wref [3]float64) (l, u, v float64)

Converts the given color to CIE L*u*v* space, taking into account a given reference white. (i.e. the monitor's white) L* is in [0..1] and both u* and v* are in about [-1..1]

func (Color) Oklab

func (col Color) Oklab() (l, a, b float64)

Oklab returns the Oklab coordinates of color.

func (Color) RGB255

func (col Color) RGB255() (r, g, b uint8)

RGB255 returns the RGB values of the color as uint8s.

func (Color) RGBA

func (col Color) RGBA() (r, g, b, a uint32)

RGBA implements color.Color.

func (Color) XYY added in v0.0.8

func (col Color) XYY() (x, y, Y float64)

XYY returns the coordinates of the color in the CIE xyY color space.

func (Color) XYYWhiteRef added in v0.0.8

func (col Color) XYYWhiteRef(wRef [3]float64) (x, y, Y float64)

XYYWhiteRef returns the coordinates of the color in the CIE xyY color space, calculated using the white reference wref.

func (Color) XYZ added in v0.0.8

func (col Color) XYZ() (x, y, z float64)

XYZ returns the color's coordinates in the CIE XYZ color space.

type HexColor

type HexColor Color

A HexColor is a Color that marshels to a hex triple of the form "#rrggbb". It implements the database/sql.Scanner, database/sql/driver.Value, encoding/json.Unmarshaler and encoding/json.Marshaler interfaces.

func (HexColor) MarshalJSON

func (hc HexColor) MarshalJSON() ([]byte, error)

func (*HexColor) Scan

func (hc *HexColor) Scan(value interface{}) error

func (*HexColor) UnmarshalJSON

func (hc *HexColor) UnmarshalJSON(data []byte) error

func (*HexColor) Value

func (hc *HexColor) Value() (driver.Value, error)

type Set

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

A Set is an ordered set of Colors. Set provides convenience methods when working with colors such returning a random color (Set.Rand()) and returning successive colors from a Set (Set.Next()).

func NewSet

func NewSet(colors ...Color) Set

NewSet creates a Set containing colors.

func (Set) Colors

func (s Set) Colors() []Color

Colors returns a slice of the colors in the Set.

func (Set) Idx

func (s Set) Idx(i int) Color

Idx returns the ith color. Idx is syntax sugar for Index.

func (Set) Index added in v0.0.8

func (s Set) Index(i int) Color

Index returns the ith color. If i is out of range, i is "wrapped around" to bring it back in range.

func (Set) Next

func (s Set) Next() Color

Next returns successive colors from Set, starting with the first color and wrapping back to the first color after the last color.

func (Set) Rand

func (s Set) Rand() Color

Rand returns as random color from Set.

Directories

Path Synopsis
Package gradient implements gradients that can be used with Ilysa.
Package gradient implements gradients that can be used with Ilysa.

Jump to

Keyboard shortcuts

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