A library for playing with colors in go (golang).

Overview

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 HCL, 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° (HCL): 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 HCL 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 HCL 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. HCL 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 HCL space:

"Spectral" colorbrewer gradient in HCL 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 [email protected]#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, HCL(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: HCL(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.

Issues
  • colorful and lightbulbs

    colorful and lightbulbs

    This is more of a request for help than an issue.

    I'm working on some home automation that involves light bulbs! These light bulbs are documented to support CIE xy and a brightness value. Their x and y values range from 0-65535 and brightness goes from 1 to 254. This seems a lot like CIE-xyY assuming I can just convert the numbers to be in the 0..1 range? But maybe it's XYZ? Not sure what the difference is here. I'm mostly confused about the brightness aspect b/c helpfully no explanation is ever given about how that one fits in.

    Due to $reasons I also need to get a hue saturation brightness representation of this. Hue in this case is documented as degrees 0-360, so that sounds like a color wheel, whereas saturation is documented as a percentage 0-100 and brightness is equally a 0-100 percentage. This sounds like CIE-LCh° to me, at least the h lines up, but unsure how L* and C* would map in this case?

    I'm rather confused at this point, so any pointers as to what I'm misunderstanding, or what to read, would be greatly appreciated.

    opened by daenney 20
  • Performance

    Performance

    While I can tell that this code focuses on accuracy, or something like it, it uses float64 throughout, which is very slow.

    I wrote a micro-benchmark to demonstrate:

    $ go test -bench=.
    BenchmarkColourDiffRgb-4                2000000000               0.84 ns/op
    BenchmarkColourDiffLab-4                 1000000              1349 ns/op
    BenchmarkColourDiffLabNoConversion-4     1000000              1318 ns/op
    

    where ColourDiffRgb is this, ColourDiffLab is this and ColourDiffLabNoConversion is calling DistanceLab() between two colorful.Colors without converting from color.NRGBA.

    Perhaps either use some approximations, or do math in either float32, or possibly a fixed-point format.

    opened by Ravenslofty 15
  • Remove dependency on DATA-DOG/go-sqlmock

    Remove dependency on DATA-DOG/go-sqlmock

    Hi @lucasb-eyer, thanks for this module! I'm using it indirectly via gdamore/tcell. I noticed this library depends on DATA-DOG/go-sqlmock, but only for the runnable example in hexcolor_test.go.

    I propose we remove the dependency on this unrelated library (it seems odd that a color library depends on a Datadog SQL mocking library). In addition to pulling an unnecessary dependency, it causes a lot of noise commits, eg: https://github.com/lucasb-eyer/go-colorful/commit/30298f24079860c4dee452fdef6519b362a4a026, https://github.com/lucasb-eyer/go-colorful/commit/4de7d682992e4105e105acd8ec5deb03a5bc542a, https://github.com/lucasb-eyer/go-colorful/commit/41bd1f4f1990ddbf36e4927bea4fa80173b33905, https://github.com/lucasb-eyer/go-colorful/commit/2341e02c5a001f748cbc6f3adc4a586e64365bd0.

    Per your comment on April 6, it looks like you're not a big fan of it in any case:

    This is unfortunate, especially as sqlmock is only barely used for testing. I'm not up-to-date anymore and have to rely on PRs, so thanks a lot for fixing this!

    Somebody else already created a PR to comment this code out, but I think we can do better than simply commenting it out and saying "this breaks everything". :-)

    My suggestion is that we simply remove this example/test and get rid of the dependency (it's not even included in the godoc output, though I'm not entirely sure why). You have an example of usage in the README here, so I don't think it'll make it any harder to figure out.

    I'm happy to whip up a PR removing this and tidying up the dependencies. Thoughts?

    opened by benhoyt 7
  • gofmt all sources

    gofmt all sources

    Since I've started working on improving the MakeColor situation, I noticed that some source files weren't formatted by gofmt, which resulted in huge parts of the existing code being automatically rewritten by my IDE every time I save.

    Seeing how this became an absolute convention in the Go world, and to make it easier for me and others to contribute to the project, I hope you're cool with this one, big format patch.

    opened by muesli 7
  • Doc:

    Doc: "main redeclared" error message

    When I build your examples, I have these error messages:

    .go/src/github.com/lucasb-eyer/go-colorful/doc/colordist.go:6: main redeclared in this block
        previous declaration at .go/src/github.com/lucasb-eyer/go-colorful/doc/colorblend.go:10
    .go/src/github.com/lucasb-eyer/go-colorful/doc/colorgens.go:12: main redeclared in this block
        previous declaration at .go/src/github.com/lucasb-eyer/go-colorful/doc/colordist.go:6
    .go/src/github.com/lucasb-eyer/go-colorful/doc/gradientgen.go:45: main redeclared in this block
        previous declaration at .go/src/github.com/lucasb-eyer/go-colorful/doc/colorgens.go:12
    .go/src/github.com/lucasb-eyer/go-colorful/doc/palettegens.go:12: main redeclared in this block
        previous declaration at .go/src/github.com/lucasb-eyer/go-colorful/doc/gradientgen.go:45
    

    You should put your examples in different directories (1 per main() function).

    opened by pierrre 7
  • Introduce a function for sorting colors

    Introduce a function for sorting colors

    I figured I'd take a stab at addressing the README.md's call for a sort function:

    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)

    This pull request introduces a new Sorted function that sorts colors using the CIEDE2000 distance. Inspired by "The incredibly challenging task of sorting colours", the implementation sorts by taking a traveling salesman tour around the provided colors, starting (and therefore ending) with the color closest to black. Because the traveling salesman problem is NP-hard, Sorted uses an approximation based on a minimum spanning tree, whose output is within 2x of optimal.

    In addition to the Sorted function itself (defined in a new sort.go file), the pull request provides

    • a simple test case (sort_test.go),
    • documentation (within the README.md file),
    • an image for the documentation illustrating the effect of Sorted, and
    • the code that produced that image.

    I hope this is what you had in mind for a sorting function for Go-Colorful. Enjoy!

    opened by spakin 6
  • MakeColor now indicates conversion errors by returning a second value

    MakeColor now indicates conversion errors by returning a second value

    MakeColor now returns a bool as its secondary return value, indicating whether the conversion failed because the source color's alpha channel was set to 0. In such cases, the returned color will have R, G and B set to 0, too.

    Note: this will break the API. I'm not sure how many projects depend on go-colorful, but it might be a good idea to package the current state as a proper release before merging this.

    Fixes #21.

    opened by muesli 6
  • would be nice to sponsor you

    would be nice to sponsor you

    I've received sponsorships for work that I developed using go-colorful, and it would be nice to share the love, even just a bit. If you set up a go sponsorship, I'll arrange to pass a portion of my sponsorship proceeds to you.

    opened by gdamore 5
  • Update sqlmock dependency

    Update sqlmock dependency

    go-sqlmock have switched from gopkg.in to Go modules. This repository uses the new github.com import path, however the go.mod file still uses the old gopkg.in import path. This confuses go mod when importing this package:

    go: gopkg.in/DATA-DOG/[email protected]: go.mod has non-....v1 module path "github.com/DATA-DOG/go-sqlmock" at revision v1.3.3
    

    This commit updates the go.mod import path.

    (Please tag a new minor version after merging this)

    opened by emersion 4
  • Does SoftPaletteEx also ensure uniquiness of the colors in the palette?

    Does SoftPaletteEx also ensure uniquiness of the colors in the palette?

    Hi, I found this package while searching how to generate palettes, however, I need to ensure that the colors in a palette are all unique.

    It is unclear to me whether the method takes care of this or not.

    opened by maxiride 4
  • Correct syntax example for multiple color types.

    Correct syntax example for multiple color types.

    I noticed that when I copied the Hex example from the README, go gave me a multiple-value colorful.Hex() in single-value context error, and the source reveals that colorful.Hex() will return an error if the string provided is invalid. Also present if you were to copy paste that whole chunk of code are multiple no new variables on left side of := errors, so I adjusted that as well.

    opened by verygoodsoftwarenotvirus 4
  • swift-colorful - port of the `go-colorful` library in Swift

    swift-colorful - port of the `go-colorful` library in Swift

    Hey guys!

    Not really an issue, but rather info about the work I've done to port this library to Swift: https://github.com/mojzesh/swift-colorful

    It's also available in Swift Package Index: https://swiftpackageindex.com/mojzesh/swift-colorful

    Have fun!

    And you are welcome to comment or open PR's.

    opened by mojzesh 0
  • [wip] oklab

    [wip] oklab

    xyz -> oklab for draft to fix #54

    oklab->xyz failing due to fp inaccuracy (I think?) with calculated matrix inverse. Might have to go through linear rgb for now. Port should be easy. Ref: https://bottosson.github.io/posts/oklab/#converting-from-linear-srgb-to-oklab.

    opened by flowchartsman 1
  • Update hsluv coefficients

    Update hsluv coefficients

    https://github.com/hsluv/hsluv/issues/54 https://github.com/hsluv/hsluv/pull/82

    Probably will need updating the hsluv D65 and of course the test files.

    opened by makeworld-the-better-one 0
  • YIQ colorspace and YIQ distance

    YIQ colorspace and YIQ distance

    The YIQ colorspace can be useful for quickly measuring the perceived difference between two colors. This is what odiff uses to measure the difference between images. The README references this paper.

    The YIQ conversion and special YIQ distance algorithm have already been implemented in Go here, but should be compared with the paper just in case.

    opened by makeworld-the-better-one 0
  • "HCL" can refer to different things

    I'm writing code to bring HSLuv to go-colorful (see #41), and I noticed that term "HCL" is used to refer to the cylindrical transformation of CIELAB. But as Wikipedia notes, the term "HCL" is very ambiguous. Furthermore, the use of cylindical CIELUV is much more common, and go-colorful does not have support for this.

    I am going to be implementing cylindrical CIELUV (aka CIE LCh(uv)) as it's required for HSLuv. But I'd like to recommend that all functions using the term "HCL" be deprecated, and new ones be created that use a more accurate term - perhaps LabLCh is good? Or LabCylinder?

    opened by makeworld-the-better-one 0
Releases(v1.2.0)
  • v1.2.0(Jan 28, 2021)

    Please note the v1.1.0 and v1.2.0 tags have the same code, this new update. The next release of this library will be v1.2.1 or v1.3.0, not anything else.

    Hello! I'm the new maintainer of go-colorful. This is the first release its had in a while, adding some new color spaces and fixing some small bugs. Rest assured it's in good hands, and I hope to support all your wonderful work with it for long time.

    If you'd like to support go-colorful's development you can support me or Lucas (the original developer) through GitHub Sponsors, check out the Sponsor button up top. I also have a Ko-Fi for one-time donations.

    The rest of this message is copied from the CHANGELOG.md file in this repo.

    Added

    • HSLuv and HPLuv color spaces (#41, #51)
    • CIE LCh(uv) color space, called LuvLCh in code (#51)
    • JSON and envconfig serialization support for HexColor (#42)
    • DistanceLinearRGB (#53)

    Fixed

    • RGB to/from XYZ conversion is more accurate (#51)
    • A bug in XYZToLuvWhiteRef that only applied to very small values was fixed (#51)
    • BlendHCL output is clamped so that it's not invalid (#46)
    • Properly documented DistanceCIE76 (#40)
    • Some small godoc fixes
    Source code(tar.gz)
    Source code(zip)
  • v1.0.3(Nov 11, 2019)

  • v1.0.2(Apr 7, 2019)

  • v1.0.1(Mar 24, 2019)

  • v1.0(May 26, 2018)

  • v0.9(May 26, 2018)

Owner
Lucas Beyer
Just some dude.
Lucas Beyer
Palette: Just colors with Golang

palette Just colors. Go. Contributing I welcome palettes of all kinds but just to be sure file an issue with the palette(s) you wish to add. Add your

Patricio Whittingslow 0 Dec 18, 2021
Cgo bindings to PulseAudio's Simple API, for easily playing or capturing raw audio.

pulse-simple Cgo bindings to PulseAudio's Simple API, for easily playing or capturing raw audio. The full Simple API is supported, including channel m

Tommy 20 Jun 17, 2022
Dominantcolor - Display the dominant colors of an image

dominantcolor Display the dominant colors of an image - https://convey.earth/con

Stuart Scott 21 Mar 23, 2022
Pure Golang Library that allows simple LSB steganography on images

Steganography Lib Steganography is a library written in Pure go to allow simple LSB steganography on images. It is capable of both encoding and decodi

Rafael Passos 150 Aug 10, 2022
A captcha library written in golang

gocaptcha 一个简单的Go语言实现的验证码 图片实例 简介 基于Golang实现的图片验证码生成库,可以实现随机字母个数,随机直线,随机噪点等。可以设置任意多字体,每个验证码随机选一种字体展示。 实例 使用: go get github.com/lifei6671/gocaptcha/

Minho 170 Jun 28, 2022
go chart is a basic charting library in native golang.

go-chart Package chart is a very simple golang native charting library that supports timeseries and continuous line charts. Master should now be on th

Will Charczuk 3.6k Aug 3, 2022
ColorX is a library to determine the most prominent color in an image written in golang

ColorX is a library to determine the most prominent color in an image. ColorX doesn't use any sort of complex algorithms to calculate the prominent color, it simply loops over the image pixels and returns the color that occurs the most.

Hesham Abourgheba 1 Nov 11, 2021
A festive Christmas tree GIF generator implemented using only Golang standard library code

Christmas Tree GIF Generator A festive Christmas tree GIF generator implemented

Golang Dorset 0 Feb 4, 2022
geoserver is a Go library for manipulating a GeoServer instance via the GeoServer REST API.

Geoserver geoserver Is a Go Package For Manipulating a GeoServer Instance via the GeoServer REST API. How to install: go get -v gopkg.in/hishamkaram/g

Hisham waleed karam 73 Jul 29, 2022
General purpose library for reading, writing and working with OpenStreetMap data

osm This package is a general purpose library for reading, writing and working with OpenStreetMap data in Go (golang). It has the ability to read OSM

Paul Mach 223 Aug 13, 2022
S2 geometry library in Go

Overview S2 is a library for spherical geometry that aims to have the same robustness, flexibility, and performance as the best planar geometry librar

Go 1.4k Aug 11, 2022
Go package for fast high-level image processing powered by libvips C library

bimg Small Go package for fast high-level image processing using libvips via C bindings, providing a simple programmatic API. bimg was designed to be

Tom 2k Aug 2, 2022
Image processing library and rendering toolkit for Go.

blend Image processing library and rendering toolkit for Go. (WIP) Installation: This library is compatible with Go1. go get github.com/phrozen/blend

Guillermo Estrada 59 Dec 24, 2021
Go bindings to OpenGL Utility Library

GLU This package offers minimal bindings for GLU functions. Usage go get github.com/go-gl-legacy/glu License Copyright 2012 The go-gl Authors. All ri

go-gl legacy 21 Aug 18, 2018
Go binding for the cairo graphics library

go-cairo Go binding for the cairo graphics library Based on Dethe Elza's version https://bitbucket.org/dethe/gocairo but significantly extended and up

Erik Unger 121 Aug 14, 2022
A lightning fast image processing and resizing library for Go

govips A lightning fast image processing and resizing library for Go This package wraps the core functionality of libvips image processing library by

David Byttow 731 Aug 8, 2022
This is old and unmaintained code, ignore it. starfish is a simple, SDL based, 2D graphics and user input library for Go. If you intend to work on it, please fork from the 'devel' branch, not 'master'. Current release: 0.12.0

What is starfish? What starfish is: starfish is a simple 2D graphics and user input library for Go built on SDL. What starfish is not: While it is bui

Gary Talent 12 Jun 4, 2019
A library to read, write, and transform Stereolithography (.stl) files in Go.

stl A library to read, write, and transform Stereolithography (.stl) files in Go. It is used in the command line STL manipulation tool stltool. Featur

Hagen Schendel 62 Jun 19, 2022
Go Language Library for SVG generation

SVGo: A Go library for SVG generation The library generates SVG as defined by the Scalable Vector Graphics 1.1 Specification (http://www.w3.org/TR/SVG

Anthony Starks 1.9k Aug 8, 2022