Please bookmark this page to avoid losing your image tool!

Beach Photo Generator

(Free & Supports Bulk Upload)

Drag & drop your images here or

The result will appear here...
You can edit the below JavaScript code to customize the image tool.
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;
}

Free Image Tool Creator

Can't find the image tool you're looking for?
Create one based on your own needs now!

Description

The Beach Photo Generator is a creative tool that transforms your uploaded images into a stylized Polaroid-style photograph set within a scenic beach landscape. Users can choose between different atmospheric settings, such as a bright daytime scene or a warm sunset, and add a custom handwritten-style caption to their photo. The generator automatically places the image onto a beach backdrop featuring elements like palm trees, ocean waves, sailboats, and starfish. This tool is ideal for creating themed social media posts, digital scrapbooking, or personalized summer-themed greeting cards.

Leave a Reply

Your email address will not be published. Required fields are marked *