2025-03-06 13:01:21 -05:00

61 lines
1.5 KiB
Go

package helper
import (
"image/color"
"iter"
)
// Enum iterates over a sparse sample of the RGBA colour space.
//
// If alpha is true, the colours will include transparency,
// otherwise the returned colours will be fully opaque.
//
// If slow is false, an even smaller number of samples will be returned
// making this suitable for use in a nested loop.
//
// alpha=true slow=true: 87481 samples.
// alpha=false slow=true: 140608 samples.
// alpha=true slow=false: 649 samples.
// alpha=false slow=false: 216 samples.
func Enum(alpha, slow bool) iter.Seq[color.RGBA64] {
var aStart, aStep, cDiv uint32
switch {
case alpha && slow:
aStart, aStep, cDiv = 0, 0xffff/15, 17
case alpha: // alpha && !slow
aStart, aStep, cDiv = 0, 0xffff/3, 5
case slow: // !alpha && slow
aStart, aStep, cDiv = 0xffff, 1, 51
default: // !alpha && !slow
aStart, aStep, cDiv = 0xffff, 1, 5
}
return func(yield func(color.RGBA64) bool) {
for a := aStart; a <= 0xffff; a += aStep {
cStep := max(1, a/cDiv)
for b := uint32(0); b <= a; b += cStep {
for g := uint32(0); g <= a; g += cStep {
for r := uint32(0); r <= a; r += cStep {
if !yield(color.RGBA64{uint16(r), uint16(g), uint16(b), uint16(a)}) {
return
}
}
}
}
}
}
}
// EnumColor is identical to [Enum], but invokes a [color.Model] to return a concrete colour type.
func EnumColor[C color.Color](alpha, slow bool, m color.Model) iter.Seq[C] {
return func(yield func(C) bool) {
for rgba := range Enum(alpha, slow) {
if !yield(m.Convert(rgba).(C)) {
return
}
}
}
}