package helper import ( "image/color" ) func Model[C color.Color](fromColor func(color.Color) C) color.Model { return color.ModelFunc(func(c color.Color) color.Color { return fromColor(c) }) } // Interface that the colours used in this package are expected to implement. type Color interface { comparable color.Color NRGBA() (r, g, b, a uint32) NLRGBA() (r, g, b, a float64) NXYZA() (x, y, z, a float64) NOkLabA() (lightness, chromaA, chromaB, a float64) } type ConvertTest[C Color] struct { Name string In color.Color Out C } func TestModel[T tester[T], C Color](t T, alpha bool, m color.Model, eq func(c0, c1 C) bool, extra []ConvertTest[C]) { t.Run("legal colours", func(t T) { for wantRGBA := range Enum(alpha, true) { _gotC := m.Convert(wantRGBA) gotC, ok := _gotC.(C) if !ok { t.Errorf("model.Convert(%#+v) returned %T, expected %T", wantRGBA, _gotC, gotC) return } r, g, b, a := gotC.RGBA() gotRGBA := color.RGBA64{uint16(r), uint16(g), uint16(b), uint16(a)} if gotRGBA != wantRGBA { t.Errorf("%#+v.RGBA() = %v, want %v", gotC, gotRGBA, wantRGBA) return } wantNRGBA := color.NRGBA64Model.Convert(wantRGBA) r, g, b, a = gotC.NRGBA() gotNRGBA := color.NRGBA64{uint16(r), uint16(g), uint16(b), uint16(a)} if gotNRGBA != wantNRGBA { t.Errorf("%#+v.NRGBA() = %v, want %v", gotC, gotNRGBA, wantNRGBA) return } wantNLRGBA := collect4(NRGBAtoNLRGBA(r, g, b, a)) if gotNLRGBA := collect4(gotC.NLRGBA()); !EqFloat64SliceFuzzy(gotNLRGBA[:], wantNLRGBA[:]) { t.Errorf("%#+v.NLRGBA() = %v, want %v", gotC, gotNLRGBA, wantNLRGBA) return } var wantNXYZA [4]float64 wantNXYZA[0], wantNXYZA[1], wantNXYZA[2] = LRGBtoXYZ(wantNLRGBA[0], wantNLRGBA[1], wantNLRGBA[2]) wantNXYZA[3] = wantNLRGBA[3] if gotNXYZA := collect4(gotC.NXYZA()); !EqFloat64SliceFuzzy(gotNXYZA[:], wantNXYZA[:]) { t.Errorf("%#+v.NXYZA() = %v want %v", gotC, gotNXYZA, wantNXYZA) return } var wantNOkLabA [4]float64 wantNOkLabA[0], wantNOkLabA[1], wantNOkLabA[2] = LMStoOkLab(LRGBtoLMS(wantNLRGBA[0], wantNLRGBA[1], wantNLRGBA[2])) wantNOkLabA[3] = wantNLRGBA[3] if gotNOkLabA := collect4(gotC.NOkLabA()); !EqFloat64SliceFuzzy(gotNOkLabA[:], wantNOkLabA[:]) { t.Errorf("%#+v.NOkLabA()[:3] = %v want %v", gotC, gotNOkLabA[:], wantNOkLabA[:]) return } } }) for _, tt := range extra { t.Run(tt.Name, func(t T) { gotC := m.Convert(tt.In).(C) if !eq(gotC, tt.Out) { t.Errorf("model.Convert(%#+v) = %#+v, want %#+v", tt.In, gotC, tt.Out) return } }) } }