color/internal/helper/gamma_test.go
2025-03-06 13:01:21 -05:00

85 lines
2.1 KiB
Go

package helper
import (
"fmt"
"math"
"testing"
)
func TestLinearize(t *testing.T) {
tests := []struct {
value uint32
want float64
}{
// the minimum and maximum legal values should map to 0 and 1, respectively.
{0x0000, 0.0},
{0xffff, 1.0},
// check what would be 0x01 in 8-bit sRGB.
// this is below the point where it the function switches from linear to exponential.
{0x0101, 0x1.3e312a36f1977p-12},
// check the midpoint of the gamma curve.
{0x7fff, 0x1.b6577fc57aa37p-03},
// We do support values beyond the maximum legal value, although you probably shouldn't depend on it
// as the converse function will map these to the maximum legal value, creating an asymmetry.
{0x10000, 0x1.000246626b604p+00},
{math.MaxUint32, 0x1.2912a0c535107p+38},
}
for _, tt := range tests {
t.Run(fmt.Sprintf("0x%04x", tt.value), func(t *testing.T) {
if got := Linearize(tt.value); !EqFloat64Fuzzy(got, tt.want) {
t.Errorf("Linearize(0x%04x) = %x: want %x", tt.value, got, tt.want)
}
})
}
t.Run("monotonically increasing", func(t *testing.T) {
for i, prev := uint32(1), Linearize(0); i < 0x10000; i++ {
got := Linearize(i)
if got <= prev {
t.Errorf("Linearize(0x%04x) = %x; want > %x", i, got, prev)
}
prev = got
}
})
}
func TestDelinearize(t *testing.T) {
tests := []struct {
value float64
want uint32
}{
// make sure clamping to legal values is happening.
{-1, 0x0000},
{2, 0xffff},
// again with the next values below 0 and above 1.
{math.Nextafter(0, math.Inf(-1)), 0},
{math.Nextafter(1, math.Inf(1)), 0xffff},
// and lastly, the non-finites.
{math.Inf(-1), 0x0000},
{math.Inf(1), 0xffff},
{math.NaN(), 0x0000},
}
for _, tt := range tests {
t.Run(fmt.Sprintf("%x", tt.value), func(t *testing.T) {
if got := Delinearize(tt.value); got != tt.want {
t.Errorf("Delinearize(%x) = 0x%04x: want 0x%04x", tt.value, got, tt.want)
}
})
}
t.Run("lossless conversion of legal values", func(t *testing.T) {
for c := uint32(0); c < 0x10000; c++ {
got := Delinearize(Linearize(c))
if got != c {
t.Errorf("Delinearize(Linearize(0x%04x)) != 0x%04x", c, got)
return
}
}
})
}