You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, numColorsParam = "4") {
// Determine number of colors to extract
let k = parseInt(numColorsParam);
if (isNaN(k) || k < 2) k = 3;
if (k > 10) k = 10;
// Create a small canvas for fast pixel processing
const analysisCanvas = document.createElement('canvas');
const maxSize = 64;
const scale = maxSize / Math.max(originalImg.width, originalImg.height);
analysisCanvas.width = Math.max(1, Math.floor(originalImg.width * scale));
analysisCanvas.height = Math.max(1, Math.floor(originalImg.height * scale));
const ctx = analysisCanvas.getContext('2d', { willReadFrequently: true });
ctx.drawImage(originalImg, 0, 0, analysisCanvas.width, analysisCanvas.height);
const imgData = ctx.getImageData(0, 0, analysisCanvas.width, analysisCanvas.height);
// Extract non-transparent pixels
let pixels = [];
for(let i = 0; i < imgData.data.length; i += 4) {
if(imgData.data[i + 3] > 64) {
pixels.push([imgData.data[i], imgData.data[i + 1], imgData.data[i + 2]]);
}
}
if (pixels.length === 0) {
pixels.push([0, 0, 0]);
}
// Simplified K-means clustering to find dominant colors
let centroids = [];
for(let i = 0; i < k; i++) {
centroids.push(pixels[Math.floor(Math.random() * pixels.length) % pixels.length]);
}
for(let iter = 0; iter < 10; iter++) {
let clusters = Array.from({ length: k }, () => []);
for(let p of pixels) {
let minDist = Infinity;
let minIndex = 0;
for(let i = 0; i < k; i++) {
let d = Math.pow(p[0] - centroids[i][0], 2) + Math.pow(p[1] - centroids[i][1], 2) + Math.pow(p[2] - centroids[i][2], 2);
if(d < minDist) {
minDist = d;
minIndex = i;
}
}
clusters[minIndex].push(p);
}
for(let i = 0; i < k; i++) {
if(clusters[i].length > 0) {
let sum = [0, 0, 0];
for(let p of clusters[i]) {
sum[0] += p[0];
sum[1] += p[1];
sum[2] += p[2];
}
centroids[i] = [
Math.round(sum[0] / clusters[i].length),
Math.round(sum[1] / clusters[i].length),
Math.round(sum[2] / clusters[i].length)
];
}
}
}
// Sort colors by luminance to generate a smooth gradient
const getLuminance = (c) => 0.299 * c[0] + 0.587 * c[1] + 0.114 * c[2];
centroids.sort((a, b) => getLuminance(a) - getLuminance(b));
const toHex = (c) => "#" + c.map(x => x.toString(16).padStart(2, '0')).join('').toUpperCase();
const hexColors = centroids.map(toHex);
// Helper functionality for determining color names
const rgbToHsl = (r, g, b) => {
r /= 255; g /= 255; b /= 255;
const max = Math.max(r, g, b), min = Math.min(r, g, b);
let h, s, l = (max + min) / 2;
if (max === min) {
h = s = 0;
} else {
const d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
switch (max) {
case r: h = (g - b) / d + (g < b ? 6 : 0); break;
case g: h = (b - r) / d + 2; break;
case b: h = (r - g) / d + 4; break;
}
h /= 6;
}
return [h * 360, s * 100, l * 100];
};
const approximateColorName = (r, g, b) => {
const hsl = rgbToHsl(r, g, b);
const h = hsl[0];
const s = hsl[1];
const l = hsl[2];
if (l < 15) return "Black";
if (l > 85) return "White";
if (s < 15) return "Gray";
if (h < 15 || h >= 345) return "Red";
if (h < 45) return "Orange";
if (h < 75) return "Yellow";
if (h < 165) return "Green";
if (h < 195) return "Cyan";
if (h < 255) return "Blue";
if (h < 285) return "Purple";
if (h < 345) return "Magenta";
return "Colorful";
};
// Construct the overall gradient name
let gradientLabelText = "Solid Color";
if(centroids.length > 1) {
gradientLabelText = `${approximateColorName(...centroids[0])} to ${approximateColorName(...centroids[centroids.length-1])} Gradient`;
} else if (centroids.length === 1) {
gradientLabelText = approximateColorName(...centroids[0]);
}
// Build the visual container DOM Output
const container = document.createElement("div");
container.style.display = "flex";
container.style.flexDirection = "column";
container.style.alignItems = "center";
container.style.fontFamily = "system-ui, -apple-system, sans-serif";
container.style.width = "100%";
container.style.maxWidth = "800px";
container.style.boxSizing = "border-box";
container.style.padding = "24px";
container.style.backgroundColor = "#1e1e24";
container.style.color = "#f4f4f6";
container.style.borderRadius = "12px";
container.style.boxShadow = "0 8px 24px rgba(0,0,0,0.5)";
container.style.margin = "0 auto";
const title = document.createElement("h2");
title.textContent = "Image Color Gradient Analyzer";
title.style.marginTop = "0";
title.style.marginBottom = "8px";
const subtitle = document.createElement("p");
subtitle.textContent = "Extracted Name: " + gradientLabelText;
subtitle.style.fontSize = "18px";
subtitle.style.fontWeight = "bold";
subtitle.style.color = "#a1c4fd";
subtitle.style.margin = "0 0 24px 0";
const imgClone = new Image();
imgClone.src = originalImg.src;
imgClone.style.maxWidth = "100%";
imgClone.style.maxHeight = "350px";
imgClone.style.borderRadius = "8px";
imgClone.style.marginBottom = "24px";
imgClone.style.boxShadow = "0 4px 12px rgba(0,0,0,0.5)";
// Gradient preview box
const gradientBox = document.createElement("div");
gradientBox.style.width = "100%";
gradientBox.style.height = "120px";
gradientBox.style.borderRadius = "8px";
gradientBox.style.marginBottom = "24px";
gradientBox.style.boxShadow = "0 4px 12px rgba(0,0,0,0.5)";
if (hexColors.length === 1) {
gradientBox.style.backgroundColor = hexColors[0];
} else {
gradientBox.style.background = `linear-gradient(to right, ${hexColors.join(', ')})`;
}
// Label cluster underneath
const labelsContainer = document.createElement("div");
labelsContainer.style.display = "flex";
labelsContainer.style.justifyContent = "center";
labelsContainer.style.flexWrap = "wrap";
labelsContainer.style.width = "100%";
labelsContainer.style.gap = "16px";
centroids.forEach((color, idx) => {
const hex = hexColors[idx];
const colorName = approximateColorName(...color);
const hexBlock = document.createElement("div");
hexBlock.style.display = "flex";
hexBlock.style.flexDirection = "column";
hexBlock.style.alignItems = "center";
hexBlock.style.gap = "8px";
hexBlock.style.padding = "12px";
hexBlock.style.backgroundColor = "#2b2b36";
hexBlock.style.borderRadius = "8px";
hexBlock.style.boxShadow = "0 2px 5px rgba(0,0,0,0.3)";
hexBlock.style.minWidth = "100px";
const colorCircle = document.createElement("div");
colorCircle.style.width = "48px";
colorCircle.style.height = "48px";
colorCircle.style.borderRadius = "50%";
colorCircle.style.backgroundColor = hex;
colorCircle.style.border = "2px solid #555";
const hexSpan = document.createElement("span");
hexSpan.textContent = hex;
hexSpan.style.fontFamily = "monospace";
hexSpan.style.fontSize = "15px";
hexSpan.style.fontWeight = "bold";
hexSpan.style.color = "#ddd";
const nameSpan = document.createElement("span");
nameSpan.textContent = colorName;
nameSpan.style.fontSize = "13px";
nameSpan.style.color = "#aaa";
hexBlock.appendChild(colorCircle);
hexBlock.appendChild(hexSpan);
hexBlock.appendChild(nameSpan);
labelsContainer.appendChild(hexBlock);
});
container.appendChild(title);
container.appendChild(subtitle);
container.appendChild(imgClone);
container.appendChild(gradientBox);
container.appendChild(labelsContainer);
return container;
}
Apply Changes