You can edit the below JavaScript code to customize the image tool.
Apply Changes
/**
* Creates a passport photo page from a single image by cropping and tiling it onto a canvas of a specified size.
* The function center-crops the original image to match the passport photo aspect ratio and then arranges
* multiple copies in a grid on a standard photo paper size, ready for printing.
*
* @param {HTMLImageElement} originalImg The source image object.
* @param {string} [pageSize='4x6'] The size of the output page. Supported values: '4x6', '5x7' (inches), 'A4', 'Letter'.
* @param {number} [photoWidthMM=35] The width of a single passport photo in millimeters.
* @param {number} [photoHeightMM=45] The height of a single passport photo in millimeters.
* @param {number} [dpi=300] The DPI (dots per inch) for printing, used to convert physical units to pixels.
* @param {number} [spacingMM=5] The spacing between each photo in millimeters.
* @param {string} [orientation='portrait'] The orientation of the page. Supported values: 'portrait', 'landscape'.
* @param {string} [pageBgColor='#ffffff'] The background color of the page, specified as a CSS color string.
* @returns {HTMLCanvasElement} A canvas element containing the generated passport photo page.
*/
function processImage(originalImg, pageSize = '4x6', photoWidthMM = 35, photoHeightMM = 45, dpi = 300, spacingMM = 5, orientation = 'portrait', pageBgColor = '#ffffff') {
// 1. Constants and Unit Conversion Helpers
const MM_PER_INCH = 25.4;
const mmToPx = (mm) => (mm / MM_PER_INCH) * dpi;
const inchToPx = (inch) => inch * dpi;
// 2. Determine Page Dimensions in Pixels
const sizeMap = {
'4x6': { w: 4, h: 6, unit: 'in' },
'5x7': { w: 5, h: 7, unit: 'in' },
'A4': { w: 210, h: 297, unit: 'mm' },
'Letter': { w: 8.5, h: 11, unit: 'in' }
};
const dimensions = sizeMap[pageSize] || sizeMap['4x6'];
let pageWidthPx, pageHeightPx;
if (dimensions.unit === 'in') {
pageWidthPx = inchToPx(dimensions.w);
pageHeightPx = inchToPx(dimensions.h);
} else { // 'mm'
pageWidthPx = mmToPx(dimensions.w);
pageHeightPx = mmToPx(dimensions.h);
}
if (orientation.toLowerCase() === 'landscape') {
[pageWidthPx, pageHeightPx] = [pageHeightPx, pageWidthPx];
}
// 3. Create Canvas and Context
const canvas = document.createElement('canvas');
canvas.width = Math.round(pageWidthPx);
canvas.height = Math.round(pageHeightPx);
const ctx = canvas.getContext('2d');
// 4. Fill Page Background
ctx.fillStyle = pageBgColor;
ctx.fillRect(0, 0, canvas.width, canvas.height);
// 5. Calculate Photo and Spacing Dimensions in Pixels
const photoWidthPx = mmToPx(photoWidthMM);
const photoHeightPx = mmToPx(photoHeightMM);
const spacingPx = mmToPx(spacingMM);
// 6. Calculate Source Image Crop (Center-Crop to match aspect ratio)
const sourceWidth = originalImg.naturalWidth || originalImg.width;
const sourceHeight = originalImg.naturalHeight || originalImg.height;
const sourceAspect = sourceWidth / sourceHeight;
const photoAspect = photoWidthPx / photoHeightPx;
let sx = 0, sy = 0, sWidth = sourceWidth, sHeight = sourceHeight;
if (sourceAspect > photoAspect) {
// Source image is wider than the target, so crop the sides
sWidth = sourceHeight * photoAspect;
sx = (sourceWidth - sWidth) / 2;
} else if (sourceAspect < photoAspect) {
// Source image is taller than the target, so crop the top and bottom
sHeight = sourceWidth / photoAspect;
sy = (sourceHeight - sHeight) / 2;
}
// 7. Calculate Grid Layout and Center it on the Page
if (photoWidthPx <= 0 || photoHeightPx <= 0) {
console.error("Photo dimensions must be positive numbers.");
return canvas; // Return blank canvas
}
const totalBlockWidth = photoWidthPx + spacingPx;
const totalBlockHeight = photoHeightPx + spacingPx;
// Calculate how many photos can fit in the grid
const numCols = Math.floor((canvas.width + spacingPx) / totalBlockWidth);
const numRows = Math.floor((canvas.height + spacingPx) / totalBlockHeight);
if (numCols < 1 || numRows < 1) {
console.warn("Photo size is too large to fit on the page.");
// Attempt to draw one centered photo if it fits
if (photoWidthPx <= canvas.width && photoHeightPx <= canvas.height) {
const destX = (canvas.width - photoWidthPx) / 2;
const destY = (canvas.height - photoHeightPx) / 2;
ctx.drawImage(originalImg, sx, sy, sWidth, sHeight, destX, destY, photoWidthPx, photoHeightPx);
}
return canvas;
}
// Calculate total grid dimensions to center the entire block of photos
const totalGridWidth = (numCols * totalBlockWidth) - spacingPx;
const totalGridHeight = (numRows * totalBlockHeight) - spacingPx;
const startX = (canvas.width - totalGridWidth) / 2;
const startY = (canvas.height - totalGridHeight) / 2;
// 8. Draw the Tiled Photos onto the Canvas
for (let row = 0; row < numRows; row++) {
for (let col = 0; col < numCols; col++) {
const destX = startX + col * totalBlockWidth;
const destY = startY + row * totalBlockHeight;
ctx.drawImage(originalImg, sx, sy, sWidth, sHeight, destX, destY, photoWidthPx, photoHeightPx);
}
}
// 9. Return the Final Canvas
return canvas;
}
Apply Changes