From a3181b2979b14834b1027c146acb1f534d13c761 Mon Sep 17 00:00:00 2001 From: Nor Khasyatillah Date: Thu, 18 Jul 2024 08:48:43 +0700 Subject: [PATCH] Step 2: basisGradient, CatmullRomGradient, GradientBuilder --- basis.go | 43 +++++++++++++++--------------------------- builder.go | 18 +++++++----------- catmull_rom.go | 51 ++++++++++++++++---------------------------------- go.mod | 2 +- 4 files changed, 39 insertions(+), 75 deletions(-) diff --git a/basis.go b/basis.go index 88b6d0a..cfcb4b1 100644 --- a/basis.go +++ b/basis.go @@ -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 } @@ -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 @@ -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, diff --git a/builder.go b/builder.go index 35dd756..b51a92d 100644 --- a/builder.go +++ b/builder.go @@ -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 @@ -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 @@ -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 } @@ -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]) diff --git a/catmull_rom.go b/catmull_rom.go index 740d122..b7e1089 100644 --- a/catmull_rom.go +++ b/catmull_rom.go @@ -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 { @@ -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] diff --git a/go.mod b/go.mod index 406b414..fc0968b 100644 --- a/go.mod +++ b/go.mod @@ -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