Please bookmark this page to avoid losing your image tool!

Image Film Frame Filter

(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,
    frameColor = 'black',           // Color of the film strip material
    imageBorderPadding = 10,      // Padding around the image area, in pixels
    imageCornerRadius = 5,        // Corner radius for the image display area
    sprocketStripHeight = 50,     // Height of the top/bottom strips for sprocket holes
    drawSprockets = 'true',       // Toggle drawing of sprocket strips and holes ('true' or 'false')
    sprocketColor = 'white',      // Color of the sprocket holes themselves
    sprocketHoleHeight = 30,      // Height of individual sprocket holes
    sprocketHoleWidth = 20,       // Width of individual sprocket holes
    sprocketHoleCornerRadius = 3, // Corner radius for sprocket holes
    sprocketHoleSpacing = 10,     // Horizontal spacing between sprocket holes
    sprocketStripMarginX = 15     // Horizontal margin from canvas edge to the start/end of sprocket pattern
) {

    const drawSprocketsBool = String(drawSprockets).toLowerCase() === 'true';
    const effectiveSprocketStripHeight = (drawSprocketsBool && sprocketStripHeight > 0) ? sprocketStripHeight : 0;

    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');

    // Determine image dimensions to use. Use naturalWidth/Height if available and img width/height is 0.
    const imgRenderWidth = originalImg.width || originalImg.naturalWidth;
    const imgRenderHeight = originalImg.height || originalImg.naturalHeight;

    if (imgRenderWidth === 0 || imgRenderHeight === 0) {
        console.error("Image has zero dimensions. Ensure the image is loaded and has valid dimensions.");
        // Return an empty or minimal canvas as an error indicator
        canvas.width = 1;
        canvas.height = 1;
        return canvas;
    }

    // Calculate canvas dimensions
    canvas.width = imgRenderWidth + 2 * imageBorderPadding;
    canvas.height = imgRenderHeight + 2 * imageBorderPadding + 2 * effectiveSprocketStripHeight;

    // Helper function to create a rounded rectangle path (or regular if radius is 0)
    function _createShapePath(x, y, width, height, radius) {
        ctx.beginPath();
        
        if (width <= 0 || height <= 0) {
            ctx.closePath(); // Empty path
            return; 
        }

        let effRadius = Math.max(0, radius); // Ensure radius is not negative
        // Cap radius if it's too large for the dimensions, ensuring it doesn't exceed half of width/height
        effRadius = Math.min(effRadius, width / 2, height / 2);

        if (effRadius > 0) {
            ctx.moveTo(x + effRadius, y);
            ctx.lineTo(x + width - effRadius, y);
            ctx.quadraticCurveTo(x + width, y, x + width, y + effRadius);
            ctx.lineTo(x + width, y + height - effRadius);
            ctx.quadraticCurveTo(x + width, y + height, x + width - effRadius, y + height);
            ctx.lineTo(x + effRadius, y + height);
            ctx.quadraticCurveTo(x, y + height, x, y + height - effRadius);
            ctx.lineTo(x, y + effRadius);
            ctx.quadraticCurveTo(x, y, x + effRadius, y);
        } else { 
            // Regular rectangle for radius 0, or if capped to 0 due to small dimensions
            ctx.rect(x, y, width, height);
        }
        ctx.closePath();
    }

    // 1. Fill canvas background with frameColor
    ctx.fillStyle = frameColor;
    ctx.fillRect(0, 0, canvas.width, canvas.height);

    // 2. Draw the image onto the canvas
    // Position for the image itself (top-left corner of the image)
    const imgActualDrawX = imageBorderPadding;
    const imgActualDrawY = imageBorderPadding + effectiveSprocketStripHeight;

    ctx.save();
    // Create path for the image area (possibly with rounded corners)
    _createShapePath(imgActualDrawX, imgActualDrawY, imgRenderWidth, imgRenderHeight, imageCornerRadius);
    ctx.clip(); // Clip to this path
    ctx.drawImage(originalImg, imgActualDrawX, imgActualDrawY, imgRenderWidth, imgRenderHeight);
    ctx.restore(); // Remove clipping

    // 3. Draw sprocket holes if enabled and dimensions are valid
    if (drawSprocketsBool && sprocketStripHeight > 0 && sprocketHoleWidth > 0 && sprocketHoleHeight > 0) {
        ctx.fillStyle = sprocketColor;

        // Vertical position of sprocket holes within their strips (centered)
        // Ensure sprocketHoleHeight is not greater than the strip itself for sensible centering
        const actualSprocketHoleHeight = Math.min(sprocketHoleHeight, sprocketStripHeight);
        const sprocketHoleYOffsetInStrip = (sprocketStripHeight - actualSprocketHoleHeight) / 2;
        
        // Y position for top sprocket holes
        const sprocketDrawYTop = sprocketHoleYOffsetInStrip;
        // Y position for bottom sprocket holes
        const sprocketDrawYBottom = canvas.height - sprocketStripHeight + sprocketHoleYOffsetInStrip;
        
        let currentX = sprocketStripMarginX;
        // Loop to draw sprocket holes across the width
        while (currentX + sprocketHoleWidth <= canvas.width - sprocketStripMarginX) {
            // Top sprocket hole
            _createShapePath(currentX, sprocketDrawYTop, sprocketHoleWidth, actualSprocketHoleHeight, sprocketHoleCornerRadius);
            ctx.fill();

            // Bottom sprocket hole
            _createShapePath(currentX, sprocketDrawYBottom, sprocketHoleWidth, actualSprocketHoleHeight, sprocketHoleCornerRadius);
            ctx.fill();
            
            currentX += sprocketHoleWidth + sprocketHoleSpacing; // Move to next hole position
        }
    }

    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 Film Frame Filter tool allows users to apply a decorative film strip effect to their images. This tool can enhance photos by adding a customizable frame, complete with optional sprocket holes, reminiscent of traditional film photography. Users can adjust parameters such as frame color, padding, corner radius, and the appearance of sprocket holes, tailoring the look of the final result to fit their artistic vision. This can be particularly useful for creating themed visuals for social media, enhancing photo albums, or producing unique art pieces that celebrate vintage film aesthetics.

Leave a Reply

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