You can edit the below JavaScript code to customize the image tool.
Apply Changes
async function processImage(originalImg, warmth = 50, caption = 'Пляжный день', style = 'polaroid', addSunFlare = 1, emojiList = '🌴,☀️,🏖️,🐚,🦀,🍹,🐬,🍉') {
// Parameter normalizations
const warmthLevel = Math.max(0, Math.min(100, Number(warmth) || 0));
const styleMode = String(style).toLowerCase().trim();
const hasFlare = Number(addSunFlare) === 1;
const text = String(caption).trim();
const icons = String(emojiList).split(',').map(e => e.trim()).filter(e => e);
// Dynamic Google Fonts injection for stylized text (Caveat supports Cyrillic natively)
const fontId = 'beach-day-generator-font';
const fontName = 'Caveat';
if (!document.getElementById(fontId)) {
const link = document.createElement('link');
link.id = fontId;
link.rel = 'stylesheet';
link.href = `https://fonts.googleapis.com/css2?family=${fontName}:wght@700&display=swap`;
document.head.appendChild(link);
}
// Attempt to wait briefly for font loading to settle
try {
await new Promise(r => setTimeout(r, 200));
await document.fonts.load(`bold 20px "${fontName}"`);
} catch(e) {
console.warn('Font loading delayed, fallback will be used if necessary.');
}
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
if (styleMode === 'polaroid') {
// Calculate dynamic padding based on image dimensions
const padX = originalImg.width * 0.08;
const padY = originalImg.height * 0.08;
const bottomPad = Math.max(originalImg.height * 0.2, 80);
const frameW = originalImg.width + padX * 2;
const frameH = originalImg.height + padY + bottomPad;
canvas.width = frameW * 1.3;
canvas.height = frameH * 1.3;
// 1. Generate Sand Background Pattern
const patCanvas = document.createElement('canvas');
patCanvas.width = 150;
patCanvas.height = 150;
const pCtx = patCanvas.getContext('2d');
pCtx.fillStyle = '#e8d5b5'; // Base sand color
pCtx.fillRect(0, 0, 150, 150);
// Add procedural sand noise
for(let i = 0; i < 3000; i++) {
pCtx.fillStyle = Math.random() > 0.5 ? '#dbbb8c' : '#f5e4c6';
pCtx.globalAlpha = Math.random() * 0.8 + 0.2;
const size = Math.random() * 1.5 + 0.5;
pCtx.fillRect(Math.random() * 150, Math.random() * 150, size, size);
}
ctx.fillStyle = ctx.createPattern(patCanvas, 'repeat');
ctx.fillRect(0, 0, canvas.width, canvas.height);
// 2. Draw Scattered Beach Emojis
if(icons.length > 0) {
ctx.font = `${Math.max(canvas.width, canvas.height) * 0.06}px Arial`;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
const numIcons = 8;
for(let i = 0; i < numIcons; i++) {
const icon = icons[Math.floor(Math.random() * icons.length)];
const x = Math.random() * canvas.width;
const y = Math.random() * canvas.height;
ctx.save();
ctx.translate(x, y);
// Rotate randomly for casual scatter
ctx.rotate((Math.random() - 0.5) * Math.PI / 1.5);
ctx.fillText(icon, 0, 0);
ctx.restore();
}
}
// 3. Draw Polaroid Photo
ctx.save();
ctx.translate(canvas.width / 2, canvas.height / 2);
const rot = (Math.random() - 0.5) * 6 * Math.PI / 180; // +/- 3 degrees random tilt
ctx.rotate(rot);
ctx.translate(-canvas.width / 2, -canvas.height / 2);
const startX = (canvas.width - frameW) / 2;
const startY = (canvas.height - frameH) / 2;
// Polaroid shadow
ctx.shadowColor = 'rgba(0, 0, 0, 0.4)';
ctx.shadowBlur = canvas.width * 0.015;
ctx.shadowOffsetX = 8;
ctx.shadowOffsetY = 15;
ctx.fillStyle = '#fdfdfd';
ctx.fillRect(startX, startY, frameW, frameH);
// Remove outward shadow for inner elements
ctx.shadowColor = 'transparent';
ctx.shadowBlur = 0;
const imgX = startX + padX;
const imgY = startY + padY;
// Warmth Filter (Sun-Kissed / Summer Look)
const sepVal = warmthLevel * 0.5;
const satVal = 100 + (warmthLevel * 0.6);
const briVal = 100 + (warmthLevel * 0.1);
ctx.filter = `sepia(${sepVal}%) saturate(${satVal}%) brightness(${briVal}%) contrast(105%)`;
ctx.drawImage(originalImg, imgX, imgY, originalImg.width, originalImg.height);
ctx.filter = 'none';
// Add Sun Flare (Top Left overlay)
if (hasFlare) {
ctx.save();
ctx.globalCompositeOperation = 'screen';
const flareRadius = originalImg.width * 0.8;
const grad = ctx.createRadialGradient(imgX, imgY, 0, imgX, imgY, flareRadius);
grad.addColorStop(0, 'rgba(255, 240, 180, 0.6)');
grad.addColorStop(0.3, 'rgba(255, 180, 80, 0.25)');
grad.addColorStop(1, 'rgba(255, 150, 50, 0)');
ctx.fillStyle = grad;
ctx.fillRect(imgX, imgY, originalImg.width, originalImg.height);
ctx.restore();
}
// Caption Text at the bottom border
if (text) {
ctx.fillStyle = '#2c2c2c';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
const fontSize = bottomPad * 0.45;
ctx.font = `bold ${fontSize}px "${fontName}", "Comic Sans MS", cursive, sans-serif`;
const textX = startX + frameW / 2;
const textY = startY + frameH - bottomPad / 2;
ctx.fillText(text, textX, textY);
}
ctx.restore();
} else {
// Simple overlay style: No polaroid surrounding, applies directly to the image bounds
canvas.width = originalImg.width;
canvas.height = originalImg.height;
const sepVal = warmthLevel * 0.5;
const satVal = 100 + (warmthLevel * 0.6);
const briVal = 100 + (warmthLevel * 0.1);
ctx.filter = `sepia(${sepVal}%) saturate(${satVal}%) brightness(${briVal}%) contrast(105%)`;
ctx.drawImage(originalImg, 0, 0);
ctx.filter = 'none';
if (hasFlare) {
ctx.save();
ctx.globalCompositeOperation = 'screen';
const flareRadius = originalImg.width * 0.8;
const grad = ctx.createRadialGradient(0, 0, 0, 0, 0, flareRadius);
grad.addColorStop(0, 'rgba(255, 240, 180, 0.7)');
grad.addColorStop(0.3, 'rgba(255, 180, 80, 0.3)');
grad.addColorStop(1, 'rgba(255, 150, 50, 0)');
ctx.fillStyle = grad;
ctx.fillRect(0, 0, originalImg.width, originalImg.height);
ctx.restore();
}
if (text) {
ctx.save();
const fontSize = Math.max(originalImg.width, originalImg.height) * 0.08;
ctx.font = `bold ${fontSize}px "${fontName}", "Comic Sans MS", cursive, sans-serif`;
ctx.textAlign = 'center';
ctx.textBaseline = 'bottom';
// Text Drop Shadow for readability against photo
ctx.shadowColor = 'rgba(0,0,0,0.8)';
ctx.shadowBlur = 10;
ctx.shadowOffsetX = 3;
ctx.shadowOffsetY = 3;
ctx.fillStyle = '#ffffff';
ctx.fillText(text, originalImg.width / 2, originalImg.height - fontSize * 0.5);
ctx.restore();
}
}
return canvas;
}
Apply Changes