color/internal/helper/distance_test.go

117 lines
3.1 KiB
Go

package helper
import (
"cmp"
"image/color"
"math"
"testing"
)
func TestTestDistance(t *testing.T) {
mt := mockTester{t: t}
midpoint := func(c0, c1 color.RGBA) color.RGBA {
return color.RGBA{
uint8((uint16(c0.R) + uint16(c1.R)) / 2),
uint8((uint16(c0.G) + uint16(c1.G)) / 2),
uint8((uint16(c0.B) + uint16(c1.B)) / 2),
uint8((uint16(c0.A) + uint16(c1.A)) / 2),
}
}
mt.run("non-zero distance for identical colours", func(t *mockTest) {
TestDistance(t, true, true, midpoint, func(c0, c1 color.RGBA) float64 {
return 1
}, color.RGBAModel)
})
mt.run("NaN distance", func(t *mockTest) {
TestDistance(t, true, true, midpoint, func(c0, c1 color.RGBA) float64 {
if c0 == c1 {
return 0
}
return math.NaN()
}, color.RGBAModel)
})
mt.run("negative distance", func(t *mockTest) {
TestDistance(t, true, true, midpoint, func(c0, c1 color.RGBA) float64 {
if c0 == c1 {
return 0
}
return -1
}, color.RGBAModel)
})
mt.run("asymmetric distance", func(t *mockTest) {
TestDistance(t, true, true, midpoint, func(c0, c1 color.RGBA) float64 {
if c0 == c1 {
return 0
}
if cmp.Or(int(c0.R)-int(c1.R), int(c0.G)-int(c1.G), int(c0.B)-int(c1.B), int(c0.A)-int(c1.A)) > 0 {
return 1
}
return 2
}, color.RGBAModel)
})
mt.run("triangle inequality", func(t *mockTest) {
TestDistance(t, true, true, midpoint, func(c0, c1 color.RGBA) float64 {
dR := int(c0.R) - int(c1.R)
dG := int(c0.G) - int(c1.G)
dB := int(c0.B) - int(c1.B)
dA := int(c0.A) - int(c1.A)
d2 := float64(dR*dR + dG*dG + dB*dB + dA*dA)
return d2
}, color.RGBAModel)
})
mt.run("euclidean distance", func(t *mockTest) {
TestDistance(t, true, true, midpoint, func(c0, c1 color.RGBA) float64 {
dR := int(c0.R) - int(c1.R)
dG := int(c0.G) - int(c1.G)
dB := int(c0.B) - int(c1.B)
dA := int(c0.A) - int(c1.A)
d2 := float64(dR*dR + dG*dG + dB*dB + dA*dA)
return math.Sqrt(d2)
}, color.RGBAModel)
})
mt.expectError(
"non-zero distance for identical colours",
`Distance(color.RGBA{R:0x0, G:0x0, B:0x0, A:0x0}, color.RGBA{R:0x0, G:0x0, B:0x0, A:0x0}) = 1.000000, want 0`,
)
mt.expectError(
"NaN distance",
`Distance(color.RGBA{R:0x0, G:0x0, B:0x0, A:0x0}, color.RGBA{R:0x0, G:0x0, B:0x0, A:0x55}) = NaN, want finite`,
)
mt.expectError(
"negative distance",
`Distance(color.RGBA{R:0x0, G:0x0, B:0x0, A:0x0}, color.RGBA{R:0x0, G:0x0, B:0x0, A:0x55}) = -1.000000, want > 0`,
)
mt.expectError(
"asymmetric distance",
`Distance(color.RGBA{R:0x0, G:0x0, B:0x0, A:0x55}, color.RGBA{R:0x0, G:0x0, B:0x0, A:0x0}) != Distance(color.RGBA{R:0x0, G:0x0, B:0x0, A:0x0}, color.RGBA{R:0x0, G:0x0, B:0x0, A:0x55}), want 2.000000 == 1.000000`,
)
mt.expectError(
"triangle inequality",
`Distance(color.RGBA{R:0x0, G:0x0, B:0x0, A:0x0}, color.RGBA{R:0x0, G:0x0, B:0x0, A:0x2a})+Distance(color.RGBA{R:0x0, G:0x0, B:0x0, A:0x2a}, color.RGBA{R:0x0, G:0x0, B:0x0, A:0x55}) < Distance(color.RGBA{R:0x0, G:0x0, B:0x0, A:0x0}, color.RGBA{R:0x0, G:0x0, B:0x0, A:0x55}), want 3613.000000 >= 7225.000000`,
)
mt.expectSuccess("euclidean distance")
mt.expectAllHandled()
}