Explicitly declare the NRGBA color interface.
This commit is contained in:
parent
556d94e4ed
commit
0414ffd8b9
20
oklab.go
20
oklab.go
@ -149,6 +149,14 @@ func Distance(a, b Color) float64 {
|
||||
return math.Sqrt(max(sqr(dL), sqr(dL+dA)) + max(sqr(da), sqr(da+dA)) + max(sqr(db), sqr(db+dA)))
|
||||
}
|
||||
|
||||
// NRGBAColor represent a color that can give us non pre-multiplied RGBA components.
|
||||
//
|
||||
// This isn't a standard interface, but we implement it and check for it regardless.
|
||||
type NRGBAColor interface {
|
||||
color.Color
|
||||
NRGBA() (r, g, b, a uint32)
|
||||
}
|
||||
|
||||
func okLabModel(c color.Color) color.Color {
|
||||
switch c := c.(type) {
|
||||
case Color:
|
||||
@ -161,8 +169,7 @@ func okLabModel(c color.Color) color.Color {
|
||||
case color.NRGBA64:
|
||||
return FromNRGBA(uint32(c.R), uint32(c.G), uint32(c.B), uint32(c.A))
|
||||
|
||||
// This isn't a standard interface, but I'm going to check for it regardless.
|
||||
case interface{ NRGBA() (r, g, b, a uint32) }:
|
||||
case NRGBAColor:
|
||||
return FromNRGBA(c.NRGBA())
|
||||
|
||||
default:
|
||||
@ -170,5 +177,10 @@ func okLabModel(c color.Color) color.Color {
|
||||
}
|
||||
}
|
||||
|
||||
// Implements a color model for converting arbitrary colors to OKLab.
|
||||
var Model = color.ModelFunc(okLabModel)
|
||||
var (
|
||||
// A color model for converting arbitrary colors to OKLab.
|
||||
Model = color.ModelFunc(okLabModel)
|
||||
|
||||
// Type assertions.
|
||||
_ NRGBAColor = Color{}
|
||||
)
|
||||
|
@ -59,7 +59,7 @@ func Test_delinearize(t *testing.T) {
|
||||
// The NRGBA and NRGBA64 models don't have sensible ways to recover transparent colors from types it
|
||||
// doesn't know about, so I'm going to help them out.
|
||||
func fixedNRGBAModel(c color.Color) color.Color {
|
||||
if c, ok := c.(interface{ NRGBA() (r, g, b, a uint32) }); ok {
|
||||
if c, ok := c.(NRGBAColor); ok {
|
||||
r, g, b, a := c.NRGBA()
|
||||
return color.NRGBA{R: uint8(r >> 8), G: uint8(g >> 8), B: uint8(b >> 8), A: uint8(a >> 8)}
|
||||
}
|
||||
@ -68,7 +68,7 @@ func fixedNRGBAModel(c color.Color) color.Color {
|
||||
}
|
||||
|
||||
func fixedNRGBA64Model(c color.Color) color.Color {
|
||||
if c, ok := c.(interface{ NRGBA() (r, g, b, a uint32) }); ok {
|
||||
if c, ok := c.(NRGBAColor); ok {
|
||||
r, g, b, a := c.NRGBA()
|
||||
return color.NRGBA64{R: uint16(r), G: uint16(g), B: uint16(b), A: uint16(a)}
|
||||
}
|
||||
@ -149,31 +149,38 @@ func Test_Model(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestDistance(t *testing.T) {
|
||||
colours := []Color{
|
||||
FromNRGBA(0xffff, 0xffff, 0xffff, 0xffff),
|
||||
FromNRGBA(0xffff, 0xffff, 0xffff, 0x7fff),
|
||||
FromNRGBA(0xffff, 0xffff, 0xffff, 0x0000),
|
||||
FromNRGBA(0x0000, 0x0000, 0x0000, 0xffff),
|
||||
FromNRGBA(0x0000, 0x0000, 0x0000, 0x7fff),
|
||||
FromNRGBA(0x0000, 0x0000, 0x0000, 0x0000),
|
||||
}
|
||||
func testDistance(t *testing.T, c0, c1 Color) {
|
||||
|
||||
for i, c0 := range colours {
|
||||
for j, c1 := range colours {
|
||||
d := Distance(c0, c1)
|
||||
|
||||
if i == j || (c0.A == 0 && c1.A == 0) {
|
||||
if math.IsNaN(d) || math.IsInf(d, 0) {
|
||||
t.Errorf("Distance(%v, %v) = %f, want finite", c0, c1, d)
|
||||
return
|
||||
}
|
||||
|
||||
if d < 0 {
|
||||
t.Errorf("Distance(%v, %v) = %f, want %f >= 0", c0, c1, d, d)
|
||||
return
|
||||
}
|
||||
|
||||
if d2 := Distance(c1, c0); d2 != d {
|
||||
t.Errorf("Distance(%v, %v) != Distance(%v, %v), want %f == %f", c1, c0, c0, c1, d, d2)
|
||||
return
|
||||
}
|
||||
|
||||
if c0 == c1 || (c0.A == 0 && c1.A == 0) {
|
||||
// if they're the same color, or both are completely transparent,
|
||||
// they should be perceived as identical.
|
||||
|
||||
if d != 0 {
|
||||
t.Errorf("Distance(%v, %v) = %v, want 0", c0, c1, d)
|
||||
t.Errorf("Distance(%v, %v) = %f, want %f == 0", c0, c1, d, d)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
// otherwise, there should be some kind of difference between them.
|
||||
if d <= 0 {
|
||||
t.Errorf("Distance(%v, %v) = %v, want > 0", c0, c1, d)
|
||||
t.Errorf("Distance(%v, %v) = %f, want %f > 0", c0, c1, d, d)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@ -189,7 +196,23 @@ func TestDistance(t *testing.T) {
|
||||
d2 := Distance(c0, mid) + Distance(mid, c1)
|
||||
if d2 < d {
|
||||
t.Errorf("Distance(%v, %v)+Distance(%v, %v) < Distance(%v, %v), want %f >= %f", c0, mid, mid, c1, c0, c1, d2, d)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func TestDistance(t *testing.T) {
|
||||
colours := []Color{
|
||||
FromNRGBA(0xffff, 0xffff, 0xffff, 0xffff),
|
||||
FromNRGBA(0xffff, 0xffff, 0xffff, 0x7fff),
|
||||
FromNRGBA(0xffff, 0xffff, 0xffff, 0x0000),
|
||||
FromNRGBA(0x0000, 0x0000, 0x0000, 0xffff),
|
||||
FromNRGBA(0x0000, 0x0000, 0x0000, 0x7fff),
|
||||
FromNRGBA(0x0000, 0x0000, 0x0000, 0x0000),
|
||||
}
|
||||
|
||||
for _, c0 := range colours {
|
||||
for _, c1 := range colours {
|
||||
testDistance(t, c0, c1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user