You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, vintageLevel = "1.0", proverbText = "Кто рано встаёт, тому Бог даёт") {
const intensity = parseFloat(vintageLevel) || 1.0;
// Create a container for our experiment viewer
const container = document.createElement('div');
container.style.position = 'relative';
container.style.display = 'inline-block';
container.style.maxWidth = '100%';
container.style.lineHeight = '0';
container.style.overflow = 'hidden';
// Base canvas for the processed image
const baseCanvas = document.createElement('canvas');
baseCanvas.width = originalImg.width;
baseCanvas.height = originalImg.height;
baseCanvas.style.display = 'block';
baseCanvas.style.width = '100%';
baseCanvas.style.height = 'auto';
container.appendChild(baseCanvas);
const ctx = baseCanvas.getContext('2d');
ctx.drawImage(originalImg, 0, 0);
// Filter 1: Anna Pavlova Vintage Sepia Style
const imgData = ctx.getImageData(0, 0, baseCanvas.width, baseCanvas.height);
const data = imgData.data;
for (let i = 0; i < data.length; i += 4) {
let r = data[i];
let g = data[i + 1];
let b = data[i + 2];
// Sepia algorithm
let tr = (r * 0.393) + (g * 0.769) + (b * 0.189);
let tg = (r * 0.349) + (g * 0.686) + (b * 0.168);
let tb = (r * 0.272) + (g * 0.534) + (b * 0.131);
data[i] = Math.min(255, r + (tr - r) * intensity);
data[i + 1] = Math.min(255, g + (tg - g) * intensity);
data[i + 2] = Math.min(255, b + (tb - b) * intensity);
}
ctx.putImageData(imgData, 0, 0);
// Filter 2: Dreamy Soft Glow (Ballet Esthetic)
ctx.globalAlpha = 0.4 * intensity;
ctx.filter = 'blur(12px) contrast(1.5)';
ctx.globalCompositeOperation = 'screen';
ctx.drawImage(baseCanvas, 0, 0);
// Filter 3: Dark Atmospheric Vignette
ctx.filter = 'none';
ctx.globalAlpha = 1.0;
ctx.globalCompositeOperation = 'multiply';
const gradient = ctx.createRadialGradient(
baseCanvas.width / 2, baseCanvas.height / 2, baseCanvas.width * 0.25,
baseCanvas.width / 2, baseCanvas.height / 2, baseCanvas.width * 0.75
);
gradient.addColorStop(0, 'rgba(255,255,255,1)');
gradient.addColorStop(1, 'rgba(20,15,10,1)');
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, baseCanvas.width, baseCanvas.height);
ctx.globalCompositeOperation = 'source-over';
// Add Proverb / Thematic Text
if (proverbText) {
ctx.fillStyle = 'rgba(240, 230, 220, 0.85)';
ctx.font = `italic ${Math.max(20, baseCanvas.height * 0.05)}px "Times New Roman", serif`;
ctx.textAlign = 'center';
ctx.textBaseline = 'bottom';
ctx.shadowColor = 'rgba(0, 0, 0, 0.9)';
ctx.shadowBlur = 8;
ctx.fillText(proverbText, baseCanvas.width / 2, baseCanvas.height - (baseCanvas.height * 0.05));
}
// Interactive "Experiment" Phase:
// 'Кто рано встаёт' implies shedding morning light onto the dark canvas.
const overlayCanvas = document.createElement('canvas');
overlayCanvas.width = baseCanvas.width;
overlayCanvas.height = baseCanvas.height;
overlayCanvas.style.position = 'absolute';
overlayCanvas.style.top = '0';
overlayCanvas.style.left = '0';
overlayCanvas.style.width = '100%';
overlayCanvas.style.height = '100%';
overlayCanvas.style.cursor = 'crosshair';
overlayCanvas.style.touchAction = 'none';
container.appendChild(overlayCanvas);
const oCtx = overlayCanvas.getContext('2d');
// Solid "Night Fog" Cover
oCtx.fillStyle = '#0a0a0f';
oCtx.fillRect(0, 0, overlayCanvas.width, overlayCanvas.height);
// Initial Intro Text
oCtx.fillStyle = 'rgba(255, 255, 255, 0.5)';
oCtx.font = `${Math.max(16, overlayCanvas.height * 0.03)}px sans-serif`;
oCtx.textAlign = 'center';
oCtx.textBaseline = 'middle';
oCtx.fillText("Наведите курсор, чтобы пробудить", overlayCanvas.width / 2, overlayCanvas.height / 2);
let isRevealed = false;
const revealEffect = (e) => {
// Clear intro text on first interaction
if(!isRevealed) {
oCtx.globalCompositeOperation = 'source-over';
oCtx.fillStyle = '#0a0a0f';
oCtx.fillRect(0, 0, overlayCanvas.width, overlayCanvas.height);
isRevealed = true;
}
const rect = overlayCanvas.getBoundingClientRect();
const scaleX = overlayCanvas.width / rect.width;
const scaleY = overlayCanvas.height / rect.height;
let clientX = e.clientX;
let clientY = e.clientY;
if (e.touches && e.touches.length > 0) {
clientX = e.touches[0].clientX;
clientY = e.touches[0].clientY;
}
const canvasX = (clientX - rect.left) * scaleX;
const canvasY = (clientY - rect.top) * scaleY;
// Cut through the darkness revealing the Pavlova experiment underneath
oCtx.globalCompositeOperation = 'destination-out';
const light = oCtx.createRadialGradient(
canvasX, canvasY, 0,
canvasX, canvasY, overlayCanvas.width * 0.12
);
light.addColorStop(0, 'rgba(255, 255, 255, 1)');
light.addColorStop(0.5, 'rgba(255, 255, 255, 0.5)');
light.addColorStop(1, 'rgba(255, 255, 255, 0)');
oCtx.fillStyle = light;
oCtx.beginPath();
oCtx.arc(canvasX, canvasY, overlayCanvas.width * 0.12, 0, Math.PI * 2);
oCtx.fill();
oCtx.globalCompositeOperation = 'source-over';
};
overlayCanvas.addEventListener('mousemove', revealEffect);
overlayCanvas.addEventListener('touchmove', (e) => {
e.preventDefault();
revealEffect(e);
}, { passive: false });
return container;
}
Apply Changes