Skip to content

Commit

Permalink
First step to add support for transparency
Browse files Browse the repository at this point in the history
  • Loading branch information
mazznoer committed Jul 17, 2024
1 parent b0c6383 commit 57f0618
Show file tree
Hide file tree
Showing 19 changed files with 122 additions and 97 deletions.
1 change: 1 addition & 0 deletions basis.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//go:build ignore
package colorgrad

import (
Expand Down
1 change: 1 addition & 0 deletions bench_test.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//go:build ignore
package colorgrad

import (
Expand Down
1 change: 1 addition & 0 deletions builder.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//go:build ignore
package colorgrad

import (
Expand Down
1 change: 1 addition & 0 deletions builder_test.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//go:build ignore
package colorgrad

import (
Expand Down
1 change: 1 addition & 0 deletions catmull_rom.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//go:build ignore
package colorgrad

import (
Expand Down
1 change: 1 addition & 0 deletions example_test.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//go:build ignore
package colorgrad_test

import (
Expand Down
1 change: 1 addition & 0 deletions gimp.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//go:build ignore
package colorgrad

import (
Expand Down
1 change: 1 addition & 0 deletions gimp_test.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//go:build ignore
package colorgrad

import (
Expand Down
45 changes: 19 additions & 26 deletions gradient.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,23 @@ import (
"image/color"
"math"

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

type BlendMode int

const (
BlendHcl BlendMode = iota
BlendHsv
BlendLab
BlendRgb BlendMode = iota
BlendLinearRgb
BlendLuv
BlendRgb
BlendOklab
)

func (b BlendMode) String() string {
switch b {
case BlendHcl:
return "BlendHcl"
case BlendHsv:
return "BlendHsv"
case BlendLab:
return "BlendLab"
case BlendLinearRgb:
return "BlendLinearRgb"
case BlendLuv:
return "BlendLuv"
case BlendRgb:
return "BlendRgb"
case BlendLinearRgb:
return "BlendLinearRgb"
case BlendOklab:
return "BlendOklab"
}
Expand All @@ -59,9 +47,14 @@ func (i Interpolation) String() string {
return ""
}

type Color = csscolorparser.Color

var LinearRgb = csscolorparser.FromLinearRGB
var Oklab = csscolorparser.FromOklab

type gradientBase interface {
// Get color at certain position
At(float64) colorful.Color
At(float64) Color
}

type Gradient struct {
Expand All @@ -71,29 +64,29 @@ type Gradient struct {
}

// Get color at certain position
func (g Gradient) At(t float64) colorful.Color {
func (g Gradient) At(t float64) Color {
return g.grad.At(t)
}

// Get color at certain position
func (g Gradient) RepeatAt(t float64) colorful.Color {
func (g Gradient) RepeatAt(t float64) Color {
t = norm(t, g.dmin, g.dmax)
return g.grad.At(g.dmin + modulo(t, 1)*(g.dmax-g.dmin))
}

// Get color at certain position
func (g Gradient) ReflectAt(t float64) colorful.Color {
func (g Gradient) ReflectAt(t float64) Color {
t = norm(t, g.dmin, g.dmax)
return g.grad.At(g.dmin + math.Abs(modulo(1+t, 2)-1)*(g.dmax-g.dmin))
}

// Get n colors evenly spaced across gradient
func (g Gradient) ColorfulColors(count uint) []colorful.Color {
func (g Gradient) ColorfulColors(count uint) []Color {
d := g.dmax - g.dmin
l := float64(count) - 1
colors := make([]colorful.Color, count)
colors := make([]Color, count)
for i := range colors {
colors[i] = g.grad.At(g.dmin + (float64(i)*d)/l).Clamped()
colors[i] = g.grad.At(g.dmin + (float64(i)*d)/l) //.Clamped()
}
return colors
}
Expand All @@ -114,7 +107,7 @@ func (g Gradient) Domain() (float64, float64) {

// Return a new hard-edge gradient
func (g Gradient) Sharp(segment uint, smoothness float64) Gradient {
colors := []colorful.Color{}
colors := []Color{}
if segment >= 2 {
colors = g.ColorfulColors(segment)
} else {
Expand All @@ -125,9 +118,9 @@ func (g Gradient) Sharp(segment uint, smoothness float64) Gradient {
}

type zeroGradient struct {
color colorful.Color
color Color
}

func (zg zeroGradient) At(t float64) colorful.Color {
func (zg zeroGradient) At(t float64) Color {
return zg.color
}
1 change: 1 addition & 0 deletions gradient_test.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//go:build ignore
package colorgrad

import (
Expand Down
75 changes: 12 additions & 63 deletions linear.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,19 @@ package colorgrad

import (
"math"

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

type linearGradient 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 linearGradient) At(t float64) colorful.Color {
func (lg linearGradient) At(t float64) Color {
if t <= lg.dmin {
return lg.firstColor
}
Expand All @@ -26,7 +24,7 @@ func (lg linearGradient) 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 All @@ -48,32 +46,21 @@ func (lg linearGradient) At(t float64) colorful.Color {
p1 := lg.pos[low-1]
p2 := lg.pos[low]
t = (t - p1) / (p2 - p1)
x, y, z := linearInterpolate(lg.colors[low-1], lg.colors[low], t)
a, b, c, d := linearInterpolate(lg.colors[low-1], lg.colors[low], t)

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 newLinearGradient(colors []colorful.Color, pos []float64, mode BlendMode) Gradient {
func newLinearGradient(colors []Color, pos []float64, mode BlendMode) Gradient {
gradbase := linearGradient{
colors: convertColors(colors, mode),
pos: pos,
Expand All @@ -90,41 +77,3 @@ func newLinearGradient(colors []colorful.Color, pos []float64, mode BlendMode) G
dmax: pos[len(pos)-1],
}
}

func convertColors(colorsIn []colorful.Color, mode BlendMode) [][3]float64 {
colors := make([][3]float64, len(colorsIn))
for i, col := range colorsIn {
var c1, c2, c3 float64
switch mode {
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()
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
}
colors[i] = [3]float64{c1, c2, c3}
}
return colors
}

func linearInterpolate(a, b [3]float64, t float64) (x, y, z float64) {
x = a[0] + t*(b[0]-a[0])
y = a[1] + t*(b[1]-a[1])
z = a[2] + t*(b[2]-a[2])
return
}

func interpAngle(a, b, t float64) float64 {
delta := math.Mod(((math.Mod(b-a, 360))+540), 360) - 180
return math.Mod((a + t*delta + 360), 360)
}
1 change: 1 addition & 0 deletions preset.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//go:build ignore
package colorgrad

import (
Expand Down
1 change: 1 addition & 0 deletions preset_fn.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//go:build ignore
package colorgrad

import (
Expand Down
1 change: 1 addition & 0 deletions preset_fn_test.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//go:build ignore
package colorgrad

import (
Expand Down
1 change: 1 addition & 0 deletions preset_test.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//go:build ignore
package colorgrad

import (
Expand Down
14 changes: 6 additions & 8 deletions sharp.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,17 @@ package colorgrad

import (
"math"

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

type sharpGradient struct {
colors []colorful.Color
colors []Color
pos []float64
last int
dmin float64
dmax float64
}

func (sg sharpGradient) At(t float64) colorful.Color {
func (sg sharpGradient) At(t float64) Color {
if t <= sg.dmin {
return sg.colors[0]
}
Expand All @@ -24,7 +22,7 @@ func (sg sharpGradient) 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 @@ -54,12 +52,12 @@ func (sg sharpGradient) At(t float64) colorful.Color {
t = (t - p1) / (p2 - p1)
a := sg.colors[i]
b := sg.colors[low]
return a.BlendRgb(b, t)
return blendRgb(a, b, t)
}

func newSharpGradient(colorsIn []colorful.Color, dmin, dmax float64, smoothness float64) Gradient {
func newSharpGradient(colorsIn []Color, dmin, dmax float64, smoothness float64) Gradient {
n := len(colorsIn)
colors := make([]colorful.Color, n*2)
colors := make([]Color, n*2)
i := 0
for _, c := range colorsIn {
colors[i] = c
Expand Down
1 change: 1 addition & 0 deletions sharp_test.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//go:build ignore
package colorgrad

import (
Expand Down
1 change: 1 addition & 0 deletions spline_test.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//go:build ignore
package colorgrad

import (
Expand Down
Loading

0 comments on commit 57f0618

Please sign in to comment.