Skip to content

Commit

Permalink
Step 2: basisGradient, CatmullRomGradient, GradientBuilder
Browse files Browse the repository at this point in the history
  • Loading branch information
mazznoer committed Jul 18, 2024
1 parent 57f0618 commit a3181b2
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 75 deletions.
43 changes: 15 additions & 28 deletions basis.go
Original file line number Diff line number Diff line change
@@ -1,25 +1,22 @@
//go:build ignore
package colorgrad

import (
"math"

"github.com/lucasb-eyer/go-colorful"
)

// https://github.com/d3/d3-interpolate/blob/master/src/basis.js

type basisGradient struct {
colors [][3]float64
colors [][4]float64
pos []float64
dmin float64
dmax float64
mode BlendMode
firstColor colorful.Color
lastColor colorful.Color
firstColor Color
lastColor Color
}

func (lg basisGradient) At(t float64) colorful.Color {
func (lg basisGradient) At(t float64) Color {
if t <= lg.dmin {
return lg.firstColor
}
Expand All @@ -29,7 +26,7 @@ func (lg basisGradient) At(t float64) colorful.Color {
}

if math.IsNaN(t) {
return colorful.Color{R: 0, G: 0, B: 0}
return Color{R: 0, G: 0, B: 0, A: 0}
}

low := 0
Expand Down Expand Up @@ -70,34 +67,24 @@ func (lg basisGradient) At(t float64) colorful.Color {
return basis(t, v0, v1, v2, v3)
}

x := xx(val0[0], val1[0], 0)
y := xx(val0[1], val1[1], 1)
z := xx(val0[2], val1[2], 2)
a := xx(val0[0], val1[0], 0)
b := xx(val0[1], val1[1], 1)
c := xx(val0[2], val1[2], 2)
d := xx(val0[3], val1[3], 3)

switch lg.mode {
case BlendHcl:
hue := interpAngle(lg.colors[low-1][0], lg.colors[low][0], t)
return colorful.Hcl(hue, y, z).Clamped()
case BlendHsv:
hue := interpAngle(lg.colors[low-1][0], lg.colors[low][0], t)
return colorful.Hsv(hue, y, z)
case BlendLab:
return colorful.Lab(x, y, z).Clamped()
case BlendLinearRgb:
return colorful.LinearRgb(x, y, z)
case BlendLuv:
return colorful.Luv(x, y, z).Clamped()
case BlendRgb:
return colorful.Color{R: x, G: y, B: z}
return Color{R: a, G: b, B: c, A: d}
case BlendLinearRgb:
return LinearRgb(a, b, c, d)
case BlendOklab:
a, b, c := oklabToLrgb(x, y, z)
return colorful.LinearRgb(a, b, c).Clamped()
return Oklab(a, b, c, d) //.Clamped()
}

return colorful.Color{R: 0, G: 0, B: 0}
return Color{R: 0, G: 0, B: 0, A: 0}
}

func newBasisGradient(colors []colorful.Color, pos []float64, mode BlendMode) Gradient {
func newBasisGradient(colors []Color, pos []float64, mode BlendMode) Gradient {
gradbase := basisGradient{
colors: convertColors(colors, mode),
pos: pos,
Expand Down
18 changes: 7 additions & 11 deletions builder.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
//go:build ignore
package colorgrad

import (
"fmt"
"image/color"

"github.com/lucasb-eyer/go-colorful"
"github.com/mazznoer/csscolorparser"
)

type GradientBuilder struct {
colors []colorful.Color
colors []Color
pos []float64
mode BlendMode
interpolation Interpolation
Expand All @@ -24,9 +21,8 @@ func NewGradient() *GradientBuilder {
}
}

func (gb *GradientBuilder) Colors(colors ...color.Color) *GradientBuilder {
for _, c := range colors {
col, _ := colorful.MakeColor(c)
func (gb *GradientBuilder) Colors(colors ...Color) *GradientBuilder {
for _, col := range colors {
gb.colors = append(gb.colors, col)
}
return gb
Expand All @@ -39,7 +35,7 @@ func (gb *GradientBuilder) HtmlColors(htmlColors ...string) *GradientBuilder {
gb.invalidHtmlColors = append(gb.invalidHtmlColors, s)
continue
}
gb.colors = append(gb.colors, colorful.Color{R: c.R, G: c.G, B: c.B})
gb.colors = append(gb.colors, c)
}
return gb
}
Expand Down Expand Up @@ -72,9 +68,9 @@ func (gb *GradientBuilder) Build() (Gradient, error) {

if len(gb.colors) == 0 {
// Default colors
gb.colors = []colorful.Color{
{R: 0, G: 0, B: 0}, // black
{R: 1, G: 1, B: 1}, // white
gb.colors = []Color{
{R: 0, G: 0, B: 0, A: 1}, // black
{R: 1, G: 1, B: 1, A: 1}, // white
}
} else if len(gb.colors) == 1 {
gb.colors = append(gb.colors, gb.colors[0])
Expand Down
51 changes: 16 additions & 35 deletions catmull_rom.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
//go:build ignore
package colorgrad

import (
"math"

"github.com/lucasb-eyer/go-colorful"
)

// TODO refactor + alpha

// Adapted from https://qroph.github.io/2018/07/30/smooth-paths-using-catmull-rom-splines.html

type catmullRomInterpolator struct {
Expand Down Expand Up @@ -93,57 +92,39 @@ type catmullRomGradient struct {
mode BlendMode
}

func (s catmullRomGradient) At(t float64) colorful.Color {
func (s catmullRomGradient) At(t float64) Color {
if math.IsNaN(t) {
return colorful.Color{R: 0, G: 0, B: 0}
return Color{R: 0, G: 0, B: 0, A: 0}
}
t = math.Max(s.dmin, math.Min(s.dmax, t))
switch s.mode {
case BlendLinearRgb:
return colorful.LinearRgb(s.a.at(t), s.b.at(t), s.c.at(t))
case BlendLab:
return colorful.Lab(s.a.at(t), s.b.at(t), s.c.at(t)).Clamped()
case BlendLuv:
return colorful.Luv(s.a.at(t), s.b.at(t), s.c.at(t)).Clamped()
case BlendHcl:
return colorful.Hcl(s.a.at(t), s.b.at(t), s.c.at(t)).Clamped()
case BlendHsv:
return colorful.Hsv(s.a.at(t), s.b.at(t), s.c.at(t))
return LinearRgb(s.a.at(t), s.b.at(t), s.c.at(t), 1)
case BlendOklab:
r, g, b := oklabToLrgb(s.a.at(t), s.b.at(t), s.c.at(t))
return colorful.LinearRgb(r, g, b).Clamped()
return Oklab(s.a.at(t), s.b.at(t), s.c.at(t), 1) //.Clamped
default:
return colorful.Color{R: s.a.at(t), G: s.b.at(t), B: s.c.at(t)}
return Color{R: s.a.at(t), G: s.b.at(t), B: s.c.at(t), A: 1}
}
}

func newCatmullRomGradient(colors []colorful.Color, pos []float64, space BlendMode) Gradient {
func newCatmullRomGradient(colors []Color, pos []float64, space BlendMode) Gradient {
n := len(colors)
a := make([]float64, n)
b := make([]float64, n)
c := make([]float64, n)
for i, col := range colors {
var c1, c2, c3 float64
var arr [4]float64
switch space {
case BlendRgb:
arr = [4]float64{col.R, col.G, col.B, col.A}
case BlendLinearRgb:
c1, c2, c3 = col.LinearRgb()
case BlendLab:
c1, c2, c3 = col.Lab()
case BlendLuv:
c1, c2, c3 = col.Luv()
case BlendHcl:
c1, c2, c3 = col.Hcl()
case BlendHsv:
c1, c2, c3 = col.Hsv()
arr = col2linearRgb(col)
case BlendOklab:
lr, lg, lb := col.LinearRgb()
c1, c2, c3 = lrgbToOklab(lr, lg, lb)
case BlendRgb:
c1, c2, c3 = col.R, col.G, col.B
arr = col2oklab(col)
}
a[i] = c1
b[i] = c2
c[i] = c3
a[i] = arr[0]
b[i] = arr[1]
c[i] = arr[2]
}
dmin := pos[0]
dmax := pos[n-1]
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/mazznoer/colorgrad

go 1.12
go 1.17

require (
github.com/lucasb-eyer/go-colorful v1.2.0
Expand Down

0 comments on commit a3181b2

Please sign in to comment.