| 55 | } |
| 56 | |
| 57 | class ColorBox { |
| 58 | constructor(px) { |
| 59 | this.pixels = px; |
| 60 | let minR = 255, maxR = 0, minG = 255, maxG = 0, minB = 255, maxB = 0; |
| 61 | for (const [r, g, b] of px) { |
| 62 | if (r < minR) minR = r; if (r > maxR) maxR = r; |
| 63 | if (g < minG) minG = g; if (g > maxG) maxG = g; |
| 64 | if (b < minB) minB = b; if (b > maxB) maxB = b; |
| 65 | } |
| 66 | const rRange = maxR - minR, gRange = maxG - minG, bRange = maxB - minB; |
| 67 | this.largestRange = Math.max(rRange, gRange, bRange); |
| 68 | this.splitChannel = rRange >= gRange && rRange >= bRange ? 0 : gRange >= bRange ? 1 : 2; |
| 69 | } |
| 70 | getAvg() { |
| 71 | const n = this.pixels.length; |
| 72 | let r = 0, g = 0, b = 0; |
| 73 | for (const p of this.pixels) { r += p[0]; g += p[1]; b += p[2]; } |
| 74 | return [Math.round(r / n), Math.round(g / n), Math.round(b / n)]; |
| 75 | } |
| 76 | split() { |
| 77 | if (this.pixels.length < 2) return null; |
| 78 | const ch = this.splitChannel; |
| 79 | this.pixels.sort((a, b) => a[ch] - b[ch]); |
| 80 | const mid = Math.floor(this.pixels.length / 2); |
| 81 | return [new ColorBox(this.pixels.slice(0, mid)), new ColorBox(this.pixels.slice(mid))]; |
| 82 | } |
| 83 | } |
| 84 | |
| 85 | let boxes = [new ColorBox(pixels)]; |
| 86 | while (boxes.length < colorCount) { |
nothing calls this directly
no outgoing calls
no test coverage detected