Please bookmark this page to avoid losing your image tool!

Image To Movie Creator

(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, movieTitle = "MY EPIC MOVIE", directorName = "AI VISIONARY", durationSec = 10, style = "cinematic") {
    // 1. Load Cinematic Fonts from Google Fonts
    const fontId = "movie-creator-fonts";
    if (!document.getElementById(fontId)) {
        const fontLink = document.createElement("link");
        fontLink.id = fontId;
        fontLink.rel = "stylesheet";
        fontLink.href = "https://fonts.googleapis.com/css2?family=Cinzel:wght@600&family=Bebas+Neue&display=swap";
        document.head.appendChild(fontLink);
    }

    // 2. Setup Canvas Frame
    const canvas = document.createElement('canvas');
    canvas.width = 1280;
    canvas.height = 720; // Classic 16:9 HD resolution
    const ctx = canvas.getContext('2d');
    
    const parsedDuration = parseFloat(durationSec) || 10;
    const isOldFilm = style.toLowerCase() === "oldfilm";

    // 3. Generate Static Noise Map (Offscreen for performance)
    const noiseCanvas = document.createElement('canvas');
    noiseCanvas.width = 1600; 
    noiseCanvas.height = 1000;
    const nctx = noiseCanvas.getContext('2d');
    const imgData = nctx.createImageData(noiseCanvas.width, noiseCanvas.height);
    for (let i = 0; i < imgData.data.length; i += 4) {
        const val = Math.random() * 255;
        imgData.data[i] = val;
        imgData.data[i + 1] = val;
        imgData.data[i + 2] = val;
        imgData.data[i + 3] = Math.random() * (isOldFilm ? 40 : 15);
    }
    nctx.putImageData(imgData, 0, 0);

    // 4. Calculate best-fit dimensions (Object-fit: cover logic)
    const canvasRatio = canvas.width / canvas.height;
    const imgRatio = originalImg.naturalWidth / originalImg.naturalHeight;
    let sw = originalImg.naturalWidth, sh = originalImg.naturalHeight, sx = 0, sy = 0;
    
    if (imgRatio > canvasRatio) {
        sh = originalImg.naturalHeight;
        sw = sh * canvasRatio;
        sx = (originalImg.naturalWidth - sw) / 2;
    } else {
        sw = originalImg.naturalWidth;
        sh = sw / canvasRatio;
        sy = (originalImg.naturalHeight - sh) / 2;
    }

    // 5. Animation Engine
    const startTime = performance.now();
    let framesDetached = 0;

    function renderText(text, font, yOff, fadeInSt, fadeInEn, fadeOutSt, fadeOutEn, t) {
        if (t >= fadeInSt && t <= fadeOutEn) {
            let alpha = 1;
            if (t < fadeInEn) alpha = (t - fadeInSt) / (fadeInEn - fadeInSt);
            else if (t > fadeOutSt) alpha = 1 - (t - fadeOutSt) / (fadeOutEn - fadeOutSt);
            
            ctx.save();
            ctx.globalAlpha = Math.max(0, Math.min(1, alpha));
            ctx.fillStyle = "white";
            ctx.textAlign = "center";
            ctx.textBaseline = "middle";
            ctx.font = font;
            ctx.shadowColor = "rgba(0,0,0,0.9)";
            ctx.shadowBlur = 15;
            ctx.shadowOffsetX = 3;
            ctx.shadowOffsetY = 3;
            ctx.fillText(text.toUpperCase(), canvas.width / 2, canvas.height / 2 + yOff);
            ctx.restore();
        }
    }

    function render(time) {
        // Stop rendering if canvas is removed from DOM (memory leak prevention)
        if (!document.body.contains(canvas) && framesDetached++ > 120) return;
        else if (document.body.contains(canvas)) framesDetached = 0;

        const elapsed = (time - startTime) / 1000;
        const t = (elapsed % parsedDuration) / parsedDuration; // 0.0 to 1.0 (Timeline)

        ctx.clearRect(0, 0, canvas.width, canvas.height);

        // -- Layer 1: Image with Ken Burns Effect --
        ctx.save();
        ctx.translate(canvas.width / 2, canvas.height / 2);
        
        // Slow pan and zoom
        const scale = 1.0 + (0.3 * t); // Zoom from 1.0x to 1.3x
        const panX = -30 + (60 * t); // Pan left to right
        ctx.scale(scale, scale);
        ctx.translate(panX, 0);

        // Apply cinematic filters
        if (isOldFilm) {
            const flicker = 0.8 + Math.random() * 0.2;
            ctx.filter = `sepia(0.9) grayscale(0.2) contrast(1.5) brightness(${flicker})`;
        } else {
            ctx.filter = `saturate(1.2) contrast(1.15) brightness(0.95)`;
        }

        ctx.drawImage(originalImg, sx, sy, sw, sh, -canvas.width / 2, -canvas.height / 2, canvas.width, canvas.height);
        ctx.restore();

        // -- Layer 2: Film Grain Overlay --
        ctx.save();
        ctx.globalCompositeOperation = "overlay";
        const rx = - (Math.random() * 320) | 0;
        const ry = - (Math.random() * 280) | 0;
        ctx.drawImage(noiseCanvas, rx, ry);
        ctx.restore();

        // -- Layer 3: Old Film Scratches --
        if (isOldFilm) {
            ctx.save();
            ctx.lineWidth = Math.random() * 2 + 1;
            if (Math.random() > 0.4) {
                const x = Math.random() * canvas.width;
                ctx.strokeStyle = "rgba(255,255,255,0.3)";
                ctx.beginPath(); ctx.moveTo(x, 0); ctx.lineTo(x, canvas.height); ctx.stroke();
            }
            if (Math.random() > 0.6) {
                const x = Math.random() * canvas.width;
                ctx.strokeStyle = "rgba(0,0,0,0.4)";
                ctx.beginPath(); ctx.moveTo(x, 0); ctx.lineTo(x, canvas.height); ctx.stroke();
            }
            ctx.restore();
        }

        // -- Layer 4: Vignette --
        ctx.save();
        const grad = ctx.createRadialGradient(canvas.width/2, canvas.height/2, canvas.height/2.5, canvas.width/2, canvas.height/2, canvas.width/1.2);
        grad.addColorStop(0, "rgba(0,0,0,0)");
        grad.addColorStop(1, "rgba(0,0,0,0.8)");
        ctx.fillStyle = grad;
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        ctx.restore();

        // -- Layer 5: Letterboxing (Cinematic Aspect Ratio 2.39:1) --
        ctx.fillStyle = "#000";
        const cinematicHeight = canvas.width / 2.39;
        const barHeight = (canvas.height - cinematicHeight) / 2;
        ctx.fillRect(0, 0, canvas.width, barHeight);
        ctx.fillRect(0, canvas.height - barHeight, canvas.width, barHeight);

        // -- Layer 6: Animated Titles --
        if (!isOldFilm || movieTitle) {
            // Main Title
            renderText(movieTitle, "90px 'Cinzel', serif", -20, 0.05, 0.15, 0.40, 0.45, t);
            // Director Subtitle
            renderText("A FILM BY", "30px 'Bebas Neue', sans-serif", -20, 0.50, 0.55, 0.85, 0.90, t);
            renderText(directorName, "60px 'Bebas Neue', sans-serif", 35, 0.52, 0.57, 0.85, 0.90, t);
        } else {
            // Classic silent film title card emulation
            renderText(movieTitle, "60px 'Georgia', serif", 0, 0.1, 0.2, 0.8, 0.9, t);
        }

        // -- Layer 7: Cinematic Fade-In / Fade-Out Black Transition --
        let fadeAlpha = 0;
        if (t < 0.05) fadeAlpha = 1 - (t / 0.05);
        else if (t > 0.95) fadeAlpha = (t - 0.95) / 0.05;
        
        if (fadeAlpha > 0) {
            ctx.fillStyle = `rgba(0, 0, 0, ${fadeAlpha})`;
            ctx.fillRect(0, 0, canvas.width, canvas.height);
        }

        requestAnimationFrame(render);
    }

    // Mount canvas loop & styles
    canvas.style.maxWidth = "100%";
    canvas.style.boxShadow = "0 25px 50px -12px rgba(0,0,0,0.5)";
    canvas.style.borderRadius = "8px";
    canvas.style.backgroundColor = "#000";
    
    requestAnimationFrame(render);
    
    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 Image To Movie Creator transforms static images into cinematic video sequences. The tool applies a Ken Burns effect (slow panning and zooming) to your image, adds professional overlays such as film grain, vignettes, and letterboxing, and overlays animated movie titles including custom titles and director names. Users can choose between a modern cinematic style or a vintage ‘old film’ aesthetic complete with scratches and sepia tones. This tool is ideal for creating dramatic social media intros, personalized digital greeting cards, or stylized visual storytelling for presentations.

Leave a Reply

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