package libtgsconverter import "image/color" type colorAxis uint8 // Color axis constants const ( red colorAxis = iota green blue ) type colorPriority struct { p uint32 color.RGBA } func (c colorPriority) axis(span colorAxis) uint8 { switch span { case red: return c.R case green: return c.G default: return c.B } } type colorBucket []colorPriority func (cb colorBucket) partition() (colorBucket, colorBucket) { mean, span := cb.span() left, right := 0, len(cb)-1 for left < right { cb[left], cb[right] = cb[right], cb[left] for cb[left].axis(span) < mean && left < right { left++ } for cb[right].axis(span) >= mean && left < right { right-- } } if left == 0 { return cb[:1], cb[1:] } if left == len(cb)-1 { return cb[:len(cb)-1], cb[len(cb)-1:] } return cb[:left], cb[left:] } func (cb colorBucket) mean() color.RGBA { var r, g, b uint64 var p uint64 for _, c := range cb { p += uint64(c.p) r += uint64(c.R) * uint64(c.p) g += uint64(c.G) * uint64(c.p) b += uint64(c.B) * uint64(c.p) } return color.RGBA{uint8(r / p), uint8(g / p), uint8(b / p), 255} } type constraint struct { min uint8 max uint8 vals [256]uint64 } func (c *constraint) update(index uint8, p uint32) { if index < c.min { c.min = index } if index > c.max { c.max = index } c.vals[index] += uint64(p) } func (c *constraint) span() uint8 { return c.max - c.min } func (cb colorBucket) span() (uint8, colorAxis) { var R, G, B constraint R.min = 255 G.min = 255 B.min = 255 var p uint64 for _, c := range cb { R.update(c.R, c.p) G.update(c.G, c.p) B.update(c.B, c.p) p += uint64(c.p) } var toCount *constraint var span colorAxis if R.span() > G.span() && R.span() > B.span() { span = red toCount = &R } else if G.span() > B.span() { span = green toCount = &G } else { span = blue toCount = &B } var counted uint64 var i int var c uint64 for i, c = range toCount.vals { if counted > p/2 || counted+c == p { break } counted += c } return uint8(i), span }