Published
Edited
Sep 13, 2019
1 fork
Importers
20 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
palette = Array.from(new Set(paletteMap.values()))
Insert cell
paletteMap = getColorPalette(input.data.data, depth)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function getColorPalette(imageData, maxDepth) {
const colors = [];
for (let i = 0; i < imageData.length; i += 4) {
colors.push(d3.rgb(imageData[i], imageData[i + 1], imageData[i + 2]));
}
return quantizeMedianCut(colors, maxDepth, 0);
}
Insert cell
Insert cell
function quantizeMedianCut(colors, maxDepth, currentDepth) {
if (currentDepth === maxDepth) {
// Find the average of the colors in this partition and return a map from each color to that average.
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 {
// Dimensions in RGB space; put "g" first, to prioritize the green dimension in case of ties.
const dimensions = ["g", "r", "b"];
// Find out which of these dimensions has the highest variance, among the given colors.
const variances = dimensions.map(dimension =>
d3.variance(colors, d => d[dimension])
);
const largestDimension = dimensions[d3.maxIndex(variances)];
// Sort the colors by this dimension and then split them in half.
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]);
// Recursively call this function for each half, then merge the results.
return new Map([
...quantizeMedianCut(
colors.slice(0, medianIndex),
maxDepth,
currentDepth + 1
),
...quantizeMedianCut(
colors.slice(medianIndex + 1),
maxDepth,
currentDepth + 1
)
]);
}
}
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more