func FastLinearRgb(r, g, b float64) Color {
    return Color{math.Pow(r, 1.0/2.2), math.Pow(g, 1.0/2.2), math.Pow(b, 1.0/2.2)}
}
FastLinearRgb is much faster than and almost as accurate as LinearRgb.
package colorful
import(
    "fmt"
    "math"
)
type Color struct {
    R, G, B float64
}
func (col Color) RGBA() (r, g, b, a uint32) {
    r = uint32(col.R*65535.0)
    g = uint32(col.G*65535.0)
    b = uint32(col.B*65535.0)
    a = 0xFFFF
    return
}
func (col Color) RGB255() (r, g, b uint8) {
    r = uint8(col.R*255.0)
    g = uint8(col.G*255.0)
    b = uint8(col.B*255.0)
    return
}
const Delta = 1.0/255.0
var D65 = [3]float64{0.95047, 1.00000, 1.08883}
var D50 = [3]float64{0.96422, 1.00000, 0.82521}
func (c Color) IsValid() bool {
    return 0.0 <= c.R && c.R <= 1.0 &&
           0.0 <= c.G && c.G <= 1.0 &&
           0.0 <= c.B && c.B <= 1.0
}
func clamp01(v float64) float64 {
    return math.Max(0.0, math.Min(v, 1.0))
}
func (c Color) Clamped() Color {
    return Color{clamp01(c.R), clamp01(c.G), clamp01(c.B)}
}
func sq(v float64) float64 {
    return v * v;
}
func cub(v float64) float64 {
    return v * v * v;
}
func (c1 Color) DistanceRgb(c2 Color) float64 {
    return math.Sqrt(sq(c1.R-c2.R) + sq(c1.G-c2.G) + sq(c1.B-c2.B))
}
func (c1 Color) AlmostEqualRgb(c2 Color) bool {
    return math.Abs(c1.R - c2.R) +
           math.Abs(c1.G - c2.G) +
           math.Abs(c1.B - c2.B) < 3.0*Delta
}
func (c1 Color) BlendRgb(c2 Color, t float64) Color {
    return Color{c1.R + t*(c2.R - c1.R),
                 c1.G + t*(c2.G - c1.G),
                 c1.B + t*(c2.B - c1.B)}
}
func interp_angle(a0, a1, t float64) float64 {
    delta := math.Mod(math.Mod(a1 - a0, 360.0) + 540, 360.0) - 180.0
    return math.Mod(a0 + t*delta + 360.0, 360.0)
}
func (col Color) Hsv() (h, s, v float64) {
    min := math.Min(math.Min(col.R, col.G), col.B)
    v    = math.Max(math.Max(col.R, col.G), col.B)
    C := v - min
    s = 0.0
    if v != 0.0 {
        s = C / v
    }
    h = 0.0   
    if min != v {
        if v == col.R { h = math.Mod((col.G - col.B) / C, 6.0) }
        if v == col.G { h = (col.B - col.R) / C + 2.0 }
        if v == col.B { h = (col.R - col.G) / C + 4.0 }
        h *= 60.0
        if h < 0.0 { h += 360.0 }
    }
    return
}
func Hsv(H, S, V float64) Color {
    Hp := H/60.0
    C := V*S
    X := C*(1.0-math.Abs(math.Mod(Hp, 2.0)-1.0))
    m := V-C;
    r, g, b := 0.0, 0.0, 0.0
    switch {
    case 0.0 <= Hp && Hp < 1.0: r = C; g = X
    case 1.0 <= Hp && Hp < 2.0: r = X; g = C
    case 2.0 <= Hp && Hp < 3.0: g = C; b = X
    case 3.0 <= Hp && Hp < 4.0: g = X; b = C
    case 4.0 <= Hp && Hp < 5.0: r = X; b = C
    case 5.0 <= Hp && Hp < 6.0: r = C; b = X
    }
    return Color{m+r, m+g, m+b}
}
func (c1 Color) BlendHsv(c2 Color, t float64) Color {
    h1, s1, v1 := c1.Hsv()
    h2, s2, v2 := c2.Hsv()
    return Hsv(interp_angle(h1, h2, t), s1 + t*(s2 - s1), v1 + t*(v2 - v1))
}
func (col Color) Hsl() (h, s, l float64) {
    min := math.Min(math.Min(col.R, col.G), col.B)
    max := math.Max(math.Max(col.R, col.G), col.B)
    l = (max + min) / 2
    if min == max {
        s = 0
        h = 0
    } else {
        if l < 0.5 {
            s = (max - min) / (max + min)
        } else {
            s = (max - min) / (2.0 - max - min)
        }
        if max == col.R {
            h = (col.G - col.B) / (max - min)
        } else if max == col.G {
            h = 2.0 + (col.B-col.R)/(max-min)
        } else {
            h = 4.0 + (col.R-col.G)/(max-min)
        }
        h *= 60
        if h < 0 {
            h += 360
        }
    }
    return
}
func Hsl(h, s, l float64) Color {
    if s == 0 {
        return Color{l, l, l}
    }
    var r, g, b float64
    var t1 float64
    var t2 float64
    var tr float64
    var tg float64
    var tb float64
    if l < 0.5 {
        t1 = l * (1.0 + s)
    } else {
        t1 = l + s - l*s
    }
    t2 = 2*l - t1
    h = h / 360
    tr = h + 1.0/3.0
    tg = h
    tb = h - 1.0/3.0
    if tr < 0 {
        tr += 1
    }
    if tr > 1 {
        tr -= 1
    }
    if tg < 0 {
        tg += 1
    }
    if tg > 1 {
        tg -= 1
    }
    if tb < 0 {
        tb += 1
    }
    if tb > 1 {
        tb -= 1
    }
    if 6*tr < 1 {
        r = t2 + (t1-t2)*6*tr
    } else if 2*tr < 1 {
        r = t1
    } else if 3*tr < 2 {
        r = t2 + (t1-t2)*(2.0/3.0-tr)*6
    } else {
        r = t2
    }
    if 6*tg < 1 {
        g = t2 + (t1-t2)*6*tg
    } else if 2*tg < 1 {
        g = t1
    } else if 3*tg < 2 {
        g = t2 + (t1-t2)*(2.0/3.0-tg)*6
    } else {
        g = t2
    }
    if 6*tb < 1 {
        b = t2 + (t1-t2)*6*tb
    } else if 2*tb < 1 {
        b = t1
    } else if 3*tb < 2 {
        b = t2 + (t1-t2)*(2.0/3.0-tb)*6
    } else {
        b = t2
    }
    return Color{r, g, b}
}
func (col Color) Hex() string {
    return fmt.Sprintf("#%02x%02x%02x", uint8(col.R*255.0+0.5), uint8(col.G*255.0+0.5), uint8(col.B*255.0+0.5))
}
func Hex(scol string) (Color, error) {
    format := "#%02x%02x%02x"
    factor := 1.0/255.0
    if len(scol) == 4 {
        format = "#%1x%1x%1x"
        factor = 1.0/15.0
    }
    var r, g, b uint8
    n, err := fmt.Sscanf(scol, format, &r, &g, &b)
    if err != nil {
        return Color{}, err
    }
    if n != 3 {
        return Color{}, fmt.Errorf("color: %v is not a hex-color", scol)
    }
    return Color{float64(r)*factor, float64(g)*factor, float64(b)*factor}, nil
}
func linearize(v float64) float64 {
    if v <= 0.04045 {
        return v / 12.92
    }
    return math.Pow((v + 0.055)/1.055, 2.4)
}
func (col Color) LinearRgb() (r, g, b float64) {
    r = linearize(col.R)
    g = linearize(col.G)
    b = linearize(col.B)
    return
}
func (col Color) FastLinearRgb() (r, g, b float64) {
    r = math.Pow(col.R, 2.2)
    g = math.Pow(col.G, 2.2)
    b = math.Pow(col.B, 2.2)
    return
}
func delinearize(v float64) float64 {
    if v <= 0.0031308 {
        return 12.92 * v
    }
    return 1.055 * math.Pow(v, 1.0/2.4) - 0.055
}
func LinearRgb(r, g, b float64) Color {
    return Color{delinearize(r), delinearize(g), delinearize(b)}
}