package helper import ( _color "image/color" "iter" ) // Enum iterates over a sparse sample of the RGBA colour space. // // If color is true, the colours will have distinct RGB components. // otherwise, the colours will have identical RGB components. // // 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. // // color=true alpha=true slow=true: 87481 samples. // color=true alpha=false slow=true: 140608 samples. // color=true alpha=true slow=false: 649 samples. // color=true alpha=false slow=false: 216 samples. func Enum(color, alpha, slow bool) iter.Seq[_color.RGBA64] { var aStart, aStep, cDiv uint32 switch { case color && alpha && slow: aStart, aStep, cDiv = 0, 0xffff/15, 17 case color && alpha: // color && alpha && !slow aStart, aStep, cDiv = 0, 0xffff/3, 5 case color && slow: // color && !alpha && slow aStart, aStep, cDiv = 0xffff, 1, 51 case color: // color && !alpha && !slow aStart, aStep, cDiv = 0xffff, 1, 5 case alpha && slow: // !color && alpha && slow aStart, aStep, cDiv = 0, 0xffff/15, 4369 case alpha: // !color && alpha && !slow aStart, aStep, cDiv = 0, 0xffff/15, 17 case slow: // !color && !alpha && slow aStart, aStep, cDiv = 0xffff, 1, 65535 default: // !color && !alpha && !slow aStart, aStep, cDiv = 0xffff, 1, 257 } if color { 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 } } } } } } } return func(yield func(_color.RGBA64) bool) { for a := aStart; a <= 0xffff; a += aStep { cStep := max(1, a/cDiv) for c := uint32(0); c <= a; c += cStep { if !yield(_color.RGBA64{uint16(c), uint16(c), uint16(c), uint16(a)}) { return } } } } } // EnumColor is identical to [Enum], but invokes a [color.Model] to return a concrete colour type. func EnumColor[C _color.Color](color, alpha, slow bool, m _color.Model) iter.Seq[C] { return func(yield func(C) bool) { for rgba := range Enum(color, alpha, slow) { if !yield(m.Convert(rgba).(C)) { return } } } }