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!
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.