function quantizeMedianCut(colors, maxDepth, currentDepth) {
if (currentDepth === maxDepth) {
const averageColor = d3
.rgb(
...["r", "g", "b"].map(dimension => d3.mean(colors, d => d[dimension]))
)
.toString();
return new Map(colors.map(c => [c.toString(), averageColor]));
} else {
const dimensions = ["g", "r", "b"];
const variances = dimensions.map(dimension =>
d3.variance(colors, d => d[dimension])
);
const largestDimension = dimensions[d3.maxIndex(variances)];
colors.sort((a, b) =>
d3.ascending(a[largestDimension], b[largestDimension])
);
const medianColor = colors[Math.floor(colors.length / 2)];
const bisectColors = d3.bisector(d => d[largestDimension]).left;
const medianIndex = bisectColors(colors, medianColor[largestDimension]);
return new Map([
...quantizeMedianCut(
colors.slice(0, medianIndex),
maxDepth,
currentDepth + 1
),
...quantizeMedianCut(
colors.slice(medianIndex + 1),
maxDepth,
currentDepth + 1
)
]);
}
}