@allmaps/stdlib
Version:
Allmaps Standard Library
73 lines (72 loc) • 2.4 kB
JavaScript
const DEFAULT_BIN_SIZE = 5;
const DEFAULT_RESOLUTION = 2;
export function getImageData(imageBitmap, mask) {
const canvas = new OffscreenCanvas(imageBitmap.width, imageBitmap.height);
const context = canvas.getContext('2d');
if (!context) {
throw new Error('Could not create OffscreenCanvas context');
}
if (mask) {
context.fillStyle = 'rgba(0, 0, 0, 0)';
context.fillRect(0, 0, imageBitmap.width, imageBitmap.height);
context.beginPath();
context.moveTo(mask[0][0], mask[0][1]);
mask.slice(1).forEach((point) => context.lineTo(point[0], point[1]));
context.closePath();
context.clip();
}
context.drawImage(imageBitmap, 0, 0);
return context.getImageData(0, 0, imageBitmap.width, imageBitmap.height);
}
export function getColorsArray(imageData, resolution = DEFAULT_RESOLUTION) {
const colors = [];
for (let x = 0; x < imageData.width; x += resolution) {
for (let y = 0; y < imageData.height; y += resolution) {
const startIndex = (x + y * imageData.width) * 4;
const opacity = imageData.data[startIndex + 3];
if (opacity > 0) {
const color = [
imageData.data[startIndex],
imageData.data[startIndex + 1],
imageData.data[startIndex + 2]
];
colors.push(color);
}
}
}
return colors;
}
export function getColorHistogram(colors, binSize = DEFAULT_BIN_SIZE) {
const histogram = {};
for (const color of colors) {
const bin = createColorBin(color, binSize);
if (!histogram[bin]) {
histogram[bin] = {
count: 0,
color
};
}
histogram[bin].count += 1;
}
return histogram;
}
export function getMaxOccurringColor(histogram) {
let max = Number.NEGATIVE_INFINITY;
let maxOccurringColor;
for (const { count, color } of Object.values(histogram)) {
if (count > max) {
max = count;
maxOccurringColor = color;
}
}
if (!maxOccurringColor) {
throw new Error('Histogram is empty');
}
return {
count: max,
color: maxOccurringColor
};
}
function createColorBin(color, binSize) {
return color.map((c) => Math.round(c / binSize)).toString();
}