1package main
2
3import (
4	"image"
5	"image/draw"
6	"image/png"
7	"os"
8	"strconv"
9
10	"github.com/lucasb-eyer/go-colorful"
11)
12
13// This table contains the "keypoints" of the colorgradient you want to generate.
14// The position of each keypoint has to live in the range [0,1]
15type GradientTable []struct {
16	Col colorful.Color
17	Pos float64
18}
19
20// This is the meat of the gradient computation. It returns a HCL-blend between
21// the two colors around `t`.
22// Note: It relies heavily on the fact that the gradient keypoints are sorted.
23func (gt GradientTable) GetInterpolatedColorFor(t float64) colorful.Color {
24	for i := 0; i < len(gt)-1; i++ {
25		c1 := gt[i]
26		c2 := gt[i+1]
27		if c1.Pos <= t && t <= c2.Pos {
28			// We are in between c1 and c2. Go blend them!
29			t := (t - c1.Pos) / (c2.Pos - c1.Pos)
30			return c1.Col.BlendHcl(c2.Col, t).Clamped()
31		}
32	}
33
34	// Nothing found? Means we're at (or past) the last gradient keypoint.
35	return gt[len(gt)-1].Col
36}
37
38// This is a very nice thing Golang forces you to do!
39// It is necessary so that we can write out the literal of the colortable below.
40func MustParseHex(s string) colorful.Color {
41	c, err := colorful.Hex(s)
42	if err != nil {
43		panic("MustParseHex: " + err.Error())
44	}
45	return c
46}
47
48func main() {
49	// The "keypoints" of the gradient.
50	keypoints := GradientTable{
51		{MustParseHex("#9e0142"), 0.0},
52		{MustParseHex("#d53e4f"), 0.1},
53		{MustParseHex("#f46d43"), 0.2},
54		{MustParseHex("#fdae61"), 0.3},
55		{MustParseHex("#fee090"), 0.4},
56		{MustParseHex("#ffffbf"), 0.5},
57		{MustParseHex("#e6f598"), 0.6},
58		{MustParseHex("#abdda4"), 0.7},
59		{MustParseHex("#66c2a5"), 0.8},
60		{MustParseHex("#3288bd"), 0.9},
61		{MustParseHex("#5e4fa2"), 1.0},
62	}
63
64	h := 1024
65	w := 40
66
67	if len(os.Args) == 3 {
68		// Meh, I'm being lazy...
69		w, _ = strconv.Atoi(os.Args[1])
70		h, _ = strconv.Atoi(os.Args[2])
71	}
72
73	img := image.NewRGBA(image.Rect(0, 0, w, h))
74
75	for y := h - 1; y >= 0; y-- {
76		c := keypoints.GetInterpolatedColorFor(float64(y) / float64(h))
77		draw.Draw(img, image.Rect(0, y, w, y+1), &image.Uniform{c}, image.Point{}, draw.Src)
78	}
79
80	outpng, err := os.Create("gradientgen.png")
81	if err != nil {
82		panic("Error storing png: " + err.Error())
83	}
84	defer outpng.Close()
85
86	png.Encode(outpng, img)
87}
88