You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, sceneType = 'day', caption = 'Beach Vibes') {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
// Set a consistent high-res layout
const width = 1024;
const height = 768;
canvas.width = width;
canvas.height = height;
const horizonY = height * 0.55;
// Define Color Palettes
const isSunset = sceneType.toLowerCase() === 'sunset';
const palette = isSunset ? {
skyTop: '#2b2165',
skyBottom: '#fa716b',
sun: '#fd9c38',
sunGlow: 'rgba(253, 156, 56, 0.6)',
sunX: width * 0.5,
sunY: horizonY,
oceanTop: '#2b2165',
oceanBottom: '#c85e65',
sandTop: '#cda27f',
sandBottom: '#8f6140'
} : {
skyTop: '#4facfe',
skyBottom: '#00f2fe',
sun: '#ffea00',
sunGlow: 'rgba(255, 234, 0, 0.5)',
sunX: width * 0.8,
sunY: height * 0.25,
oceanTop: '#005c97',
oceanBottom: '#36d1dc',
sandTop: '#e8dhb8',
sandBottom: '#d1b46a'
};
// 1. Draw Sky
const skyGrad = ctx.createLinearGradient(0, 0, 0, horizonY);
skyGrad.addColorStop(0, palette.skyTop);
skyGrad.addColorStop(1, palette.skyBottom);
ctx.fillStyle = skyGrad;
ctx.fillRect(0, 0, width, horizonY);
// 2. Draw Sun
ctx.beginPath();
ctx.arc(palette.sunX, palette.sunY, isSunset ? 60 : 50, 0, Math.PI * 2);
ctx.fillStyle = palette.sun;
ctx.shadowBlur = 50;
ctx.shadowColor = palette.sunGlow;
ctx.fill();
ctx.shadowBlur = 0; // reset
// 3. Draw Ocean
const oceanGrad = ctx.createLinearGradient(0, horizonY, 0, height * 0.85);
oceanGrad.addColorStop(0, palette.oceanTop);
oceanGrad.addColorStop(1, palette.oceanBottom);
ctx.fillStyle = oceanGrad;
ctx.fillRect(0, horizonY, width, height - horizonY);
// 4. Draw Sun Reflection on Ocean
ctx.fillStyle = 'rgba(255, 255, 255, 0.3)';
for (let i = 0; i < 25; i++) {
let y = horizonY + 2 + i * i * 0.4;
if (y > height * 0.8) break;
let lineWidth = isSunset ? (180 - i * 6 + Math.random() * 30) : (120 - i * 4 + Math.random() * 20);
ctx.fillRect(palette.sunX - lineWidth / 2, y, lineWidth, 2 + Math.random() * 2);
}
// 5. Draw Sky Elements: Clouds & Birds
const drawCloud = (x, y, scale) => {
ctx.save();
ctx.translate(x, y);
ctx.scale(scale, isSunset ? scale * 0.6 : scale);
ctx.beginPath();
ctx.arc(0, 0, 25, 0, Math.PI * 2);
ctx.arc(30, -15, 30, 0, Math.PI * 2);
ctx.arc(65, -5, 25, 0, Math.PI * 2);
ctx.arc(90, 5, 20, 0, Math.PI * 2);
ctx.arc(45, 10, 25, 0, Math.PI * 2);
ctx.fillStyle = isSunset ? 'rgba(255, 180, 180, 0.4)' : 'rgba(255, 255, 255, 0.7)';
ctx.fill();
ctx.restore();
};
drawCloud(width * 0.1, height * 0.15, 1.2);
drawCloud(width * 0.4, height * 0.1, 0.8);
drawCloud(width * 0.75, height * 0.18, 1.1);
ctx.strokeStyle = isSunset ? 'rgba(0,0,0,0.8)' : 'rgba(0,0,0,0.5)';
ctx.lineWidth = 2;
const drawBird = (x, y) => {
ctx.beginPath();
ctx.moveTo(x, y);
ctx.quadraticCurveTo(x + 10, y - 10, x + 20, y);
ctx.quadraticCurveTo(x + 30, y - 10, x + 40, y);
ctx.stroke();
};
drawBird(150, 100);
drawBird(200, 80);
drawBird(130, 130);
if(isSunset) drawBird(width / 2 + 50, height * 0.3);
// 6. Draw Sailboats on Horizon
const drawSailboat = (x, y, scale = 1) => {
ctx.save();
ctx.translate(x, y);
ctx.scale(scale, scale);
ctx.fillStyle = isSunset ? '#222' : '#fff';
ctx.beginPath(); ctx.moveTo(-15, 0); ctx.lineTo(15, 0); ctx.lineTo(10, 8); ctx.lineTo(-10, 8); ctx.fill();
ctx.strokeStyle = isSunset ? '#222' : '#ccc';
ctx.lineWidth = 2;
ctx.beginPath(); ctx.moveTo(2, 0); ctx.lineTo(2, -25); ctx.stroke();
ctx.fillStyle = isSunset ? '#444' : '#f9f9f9';
ctx.beginPath(); ctx.moveTo(3, -23); ctx.lineTo(3, -3); ctx.lineTo(15, -3); ctx.fill();
ctx.beginPath(); ctx.moveTo(0, -20); ctx.lineTo(0, -3); ctx.lineTo(-10, -3); ctx.fill();
ctx.restore();
};
drawSailboat(width * 0.72, horizonY + 3, 0.4);
drawSailboat(width * 0.77, horizonY + 6, 0.6);
// 7. Draw Sand & Shoreline
const sandGrad = ctx.createLinearGradient(0, height * 0.7, 0, height);
sandGrad.addColorStop(0, palette.sandTop);
sandGrad.addColorStop(1, '#c2a573');
if (isSunset) sandGrad.addColorStop(1, '#8f6140');
ctx.beginPath();
ctx.moveTo(0, height * 0.75);
ctx.bezierCurveTo(width * 0.33, height * 0.7, width * 0.66, height * 0.85, width, height * 0.75);
ctx.lineTo(width, height);
ctx.lineTo(0, height);
ctx.closePath();
ctx.fillStyle = sandGrad;
ctx.fill();
// Sea Foam
ctx.beginPath();
ctx.moveTo(0, height * 0.75);
ctx.bezierCurveTo(width * 0.33, height * 0.7, width * 0.66, height * 0.85, width, height * 0.75);
ctx.lineWidth = 15;
ctx.strokeStyle = isSunset ? 'rgba(255,200,200,0.6)' : 'rgba(255,255,255,0.7)';
ctx.lineCap = 'round';
ctx.stroke();
ctx.beginPath();
ctx.moveTo(0, height * 0.76);
ctx.bezierCurveTo(width * 0.33, height * 0.71, width * 0.66, height * 0.86, width, height * 0.76);
ctx.lineWidth = 8;
ctx.strokeStyle = isSunset ? 'rgba(255,200,200,0.3)' : 'rgba(255,255,255,0.4)';
ctx.stroke();
// 8. Draw Palm Tree
ctx.save();
ctx.translate(width * 0.05, height * 0.9);
// Trunk
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.quadraticCurveTo(width * 0.1, -height * 0.2, width * 0.15, -height * 0.45);
ctx.lineWidth = 18;
ctx.strokeStyle = isSunset ? '#2a1a12' : '#5a3d2b';
ctx.lineCap = 'round';
ctx.stroke();
ctx.translate(width * 0.15, -height * 0.45);
// Leaves
const drawLeaf = (angle, scaleX) => {
ctx.save();
ctx.rotate(angle);
ctx.scale(scaleX, 1);
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.quadraticCurveTo(80, -40, 160, -10);
ctx.quadraticCurveTo(100, 20, 0, 0);
ctx.fillStyle = isSunset ? '#1a2a16' : '#2d5a27';
ctx.fill();
ctx.strokeStyle = isSunset ? '#0a1a06' : '#1a3616';
ctx.lineWidth = 2;
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.quadraticCurveTo(80, -20, 155, -12);
ctx.stroke();
ctx.restore();
};
drawLeaf(0, 1); drawLeaf(Math.PI / 4, 1.1); drawLeaf(Math.PI / 2, 0.8);
drawLeaf(Math.PI * 3 / 4, 1.2); drawLeaf(Math.PI, 1);
drawLeaf(-Math.PI / 4, 1.3); drawLeaf(-Math.PI / 2, 0.9);
// Coconuts
ctx.fillStyle = isSunset ? '#221105' : '#442d1c';
ctx.beginPath(); ctx.arc(10, 10, 16, 0, Math.PI * 2); ctx.fill();
ctx.beginPath(); ctx.arc(-10, 20, 14, 0, Math.PI * 2); ctx.fill();
ctx.beginPath(); ctx.arc(20, -5, 15, 0, Math.PI * 2); ctx.fill();
ctx.restore();
// 9. Process and Draw OrigImage as Polaroid on the Sand
ctx.save();
const maxImgSize = 300;
const ratio = Math.min(maxImgSize / originalImg.width, maxImgSize / originalImg.height);
const imgWidth = originalImg.width * ratio;
const imgHeight = originalImg.height * ratio;
const padding = 15;
const bottomPadding = 75;
const polWidth = imgWidth + padding * 2;
const polHeight = imgHeight + padding + bottomPadding;
// Anchor the polaroid in the foreground sand
const polX = width * 0.5;
const polY = height - polHeight / 2 - 20;
ctx.translate(polX, polY);
ctx.rotate(-6 * Math.PI / 180);
// Drop Shadow
ctx.shadowBlur = 12;
ctx.shadowColor = 'rgba(0,0,0,0.4)';
ctx.shadowOffsetX = 8;
ctx.shadowOffsetY = 12;
// Paper Base
ctx.fillStyle = '#FAFAFA';
ctx.fillRect(-polWidth / 2, -polHeight / 2, polWidth, polHeight);
ctx.shadowBlur = 0; ctx.shadowOffsetX = 0; ctx.shadowOffsetY = 0;
// Photo Area
ctx.drawImage(originalImg, -imgWidth / 2, -polHeight / 2 + padding, imgWidth, imgHeight);
ctx.strokeStyle = 'rgba(0,0,0,0.1)';
ctx.lineWidth = 1;
ctx.strokeRect(-imgWidth / 2, -polHeight / 2 + padding, imgWidth, imgHeight);
// Caption Hand-written Text
if (caption) {
ctx.font = '28px "Comic Sans MS", "Marker Felt", "Caveat", "Bradley Hand", cursive';
ctx.fillStyle = '#222';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
// Place text exactly at the vertical center of the bottom padding space
ctx.fillText(caption, 0, imgHeight / 2 + padding / 2 - bottomPadding / 2 + 5, polWidth - 20);
}
ctx.restore();
// 10. Draw Starfish Element in Foreground
const drawStarfish = (cx, cy, rotation, scale) => {
ctx.save();
ctx.translate(cx, cy);
ctx.rotate(rotation);
ctx.scale(scale, scale);
ctx.beginPath();
for (let i = 0; i < 10; i++) {
const radius = i % 2 === 0 ? 22 : 9;
const angle = (i * Math.PI) / 5;
if (i === 0) ctx.moveTo(Math.cos(angle) * radius, Math.sin(angle) * radius);
else ctx.lineTo(Math.cos(angle) * radius, Math.sin(angle) * radius);
}
ctx.closePath();
ctx.shadowBlur = 5; ctx.shadowColor = 'rgba(0,0,0,0.3)'; ctx.shadowOffsetY = 3;
ctx.fillStyle = isSunset ? '#d67568' : '#f08080';
ctx.fill();
ctx.shadowBlur = 0; ctx.shadowOffsetY = 0;
ctx.strokeStyle = isSunset ? '#ad4949' : '#c45a5a';
ctx.lineWidth = 1.5;
ctx.stroke();
ctx.fillStyle = isSunset ? '#ffcccc' : '#fff';
for(let i=0; i<5; i++) {
ctx.beginPath();
ctx.arc(Math.cos(i*Math.PI*2/5)*10, Math.sin(i*Math.PI*2/5)*10, 1.5, 0, Math.PI*2);
ctx.fill();
}
ctx.restore();
};
drawStarfish(width * 0.82, height * 0.88, -0.3, 1.2);
return canvas;
}
Apply Changes