You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg) {
// Helper function to convert RGB to HSL
function rgbToHsl(r, g, b) {
r /= 255;
g /= 255;
b /= 255;
let 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; // achromatic
} else {
let 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, l];
}
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
// Scale down image for significantly faster processing
const MAX_DIM = 150;
let scale = 1;
if (originalImg.width > MAX_DIM || originalImg.height > MAX_DIM) {
scale = Math.min(MAX_DIM / originalImg.width, MAX_DIM / originalImg.height);
}
canvas.width = Math.max(1, Math.round(originalImg.width * scale));
canvas.height = Math.max(1, Math.round(originalImg.height * scale));
// Fill background with white just in case the original has transparent parts
ctx.fillStyle = '#ffffff';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(originalImg, 0, 0, canvas.width, canvas.height);
let imageData;
try {
imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
} catch (e) {
// Fallback mainly to catch CORS security restrictions
const errorDiv = document.createElement('div');
errorDiv.textContent = "Ошибка: Изображение заблокировано политикой CORS и не может быть обработано.";
errorDiv.style.color = "red";
errorDiv.style.fontFamily = "sans-serif";
return errorDiv;
}
const data = imageData.data;
let totalL = 0;
let totalS = 0;
let hueBins = {
red: 0,
orangeYellow: 0,
green: 0,
blue: 0,
purple: 0
};
let avgR = 0, avgG = 0, avgB = 0;
let pixelCount = data.length / 4;
// Loop through each pixel, convert colors, and gather metrics
for (let i = 0; i < data.length; i += 4) {
let r = data[i], g = data[i+1], b = data[i+2];
avgR += r;
avgG += g;
avgB += b;
let [h, s, l] = rgbToHsl(r, g, b);
totalL += l;
totalS += s;
// Analyze vibrant mid-tones to determine dominant mood via hue bins
if (s > 0.05 && l > 0.05 && l < 0.95) {
let weight = s * (1 - Math.abs(l - 0.5));
if (h < 20 || h >= 340) hueBins.red += weight;
else if (h >= 20 && h < 70) hueBins.orangeYellow += weight;
else if (h >= 70 && h < 165) hueBins.green += weight;
else if (h >= 165 && h < 260) hueBins.blue += weight;
else if (h >= 260 && h < 340) hueBins.purple += weight;
}
}
totalL /= pixelCount;
totalS /= pixelCount;
avgR = Math.round(avgR / pixelCount);
avgG = Math.round(avgG / pixelCount);
avgB = Math.round(avgB / pixelCount);
// Find the most dominant hue
let dominantHue = Object.keys(hueBins).reduce((a, b) => hueBins[a] > hueBins[b] ? a : b);
// Baseline texts & emojis
let mood = "Нейтральное";
let emoji = "😐";
let description = "Изображение имеет сбалансированный и умеренный характер без ярко выраженного эмоционального окраса.";
// Determine the overall mood using lightness, saturation, and hue combinations
if (totalL < 0.25) {
mood = "Мрачное / Таинственное";
emoji = "🌑";
description = "Изображение довольно темное, что создает мрачную, таинственную или строгую атмосферу.";
} else if (totalL > 0.75 && totalS < 0.2) {
mood = "Мирное / Воздушное";
emoji = "☁️";
description = "Сочетание высокой яркости и низкой насыщенности придает изображению легкость, спокойствие и чистоту.";
} else if (totalS < 0.15) {
mood = "Меланхоличное / Сдержанное";
emoji = "🌫️";
description = "Отсутствие ярких цветов придает изображению приглушенный, ностальгический или сдержанный тон.";
} else {
switch(dominantHue) {
case 'red':
mood = "Страстное / Энергичное";
emoji = "🔥";
description = "Насыщенные красные оттенки говорят об интенсивности, страсти, тепле или энергии в движении.";
break;
case 'orangeYellow':
mood = "Радостное / Теплое";
emoji = "☀️";
description = "Яркие оранжевые и желтые тона излучают счастье, оптимизм, дружелюбие и согревающий комфорт.";
break;
case 'green':
mood = "Спокойное / Природное";
emoji = "🌿";
description = "Зеленые оттенки вызывают плотное ощущение связи с природой, свежести, спокойствия и гармонии.";
break;
case 'blue':
mood = "Безмятежное / Холодное";
emoji = "🌊";
description = "Синие оттенки приносят успокаивающее, безмятежное чувство, иногда указывая на легкую грусть или прохладу.";
break;
case 'purple':
mood = "Таинственное / Чарующее";
emoji = "✨";
description = "Пурпурные тона создают роскошное, чарующее и немного волшебное или мистическое настроение.";
break;
}
}
// Creating beautiful presentation UI
const container = document.createElement('div');
container.style.cssText = `
font-family: 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
width: 100%;
max-width: 450px;
margin: 0 auto;
border-radius: 16px;
overflow: hidden;
box-shadow: 0 10px 30px rgba(0,0,0,0.1);
background-color: #ffffff;
display: flex;
flex-direction: column;
border: 1px solid #eef0f2;
`;
const imgContainer = document.createElement('div');
imgContainer.style.cssText = `
width: 100%;
height: 220px;
position: relative;
overflow: hidden;
background-color: #f8f9fa;
display: flex;
align-items: center;
justify-content: center;
`;
const imgEl = document.createElement('img');
imgEl.src = originalImg.src;
imgEl.style.cssText = `
width: 100%;
height: 100%;
object-fit: cover;
`;
imgContainer.appendChild(imgEl);
const content = document.createElement('div');
content.style.cssText = `
padding: 24px;
text-align: center;
`;
const moodTitle = document.createElement('h2');
moodTitle.textContent = `${emoji} ${mood}`;
moodTitle.style.cssText = `
margin: 0 0 12px 0;
font-size: 22px;
color: #1a1a1a;
font-weight: 700;
line-height: 1.3;
`;
const moodDesc = document.createElement('p');
moodDesc.textContent = description;
moodDesc.style.cssText = `
margin: 0;
font-size: 15px;
color: #4a5568;
line-height: 1.6;
`;
const colorSwatch = document.createElement('div');
colorSwatch.style.cssText = `
margin-top: 20px;
display: inline-flex;
align-items: center;
gap: 10px;
padding: 6px 14px;
border-radius: 50px;
background-color: #f7fafc;
border: 1px solid #e2e8f0;
`;
const swatchColor = document.createElement('div');
swatchColor.style.cssText = `
width: 20px;
height: 20px;
border-radius: 50%;
background-color: rgb(${avgR}, ${avgG}, ${avgB});
box-shadow: inset 0 2px 4px rgba(0,0,0,0.1);
border: 1px solid rgba(0,0,0,0.05);
`;
const swatchText = document.createElement('span');
swatchText.textContent = "Средний фон";
swatchText.style.cssText = `
font-size: 14px;
color: #2d3748;
font-weight: 500;
`;
const metricsDiv = document.createElement('div');
metricsDiv.style.cssText = `
display: flex;
justify-content: space-around;
margin-top: 24px;
padding-top: 16px;
border-top: 1px solid #edf2f7;
`;
function createMetric(label, value) {
const d = document.createElement('div');
d.style.cssText = "display: flex; flex-direction: column; align-items: center;";
d.innerHTML = `
<div style="font-size: 18px; font-weight: 700; color: #2d3748;">${value}</div>
<div style="font-size: 11px; color: #718096; text-transform: uppercase; letter-spacing: 0.5px; margin-top: 4px; font-weight: 600;">${label}</div>
`;
return d;
}
metricsDiv.appendChild(createMetric("Яркость", Math.round(totalL * 100) + "%"));
metricsDiv.appendChild(createMetric("Насыщенность", Math.round(totalS * 100) + "%"));
colorSwatch.appendChild(swatchColor);
colorSwatch.appendChild(swatchText);
content.appendChild(moodTitle);
content.appendChild(moodDesc);
content.appendChild(colorSwatch);
content.appendChild(metricsDiv);
container.appendChild(imgContainer);
container.appendChild(content);
return container;
}
Apply Changes