You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, layout = 'polaroid', itemCount = 6, backgroundColor = '#e2e8f0') {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
// Seeded random function to ensure consistent layout across rerenders
let seed = 98765;
function random() {
let x = Math.sin(seed++) * 10000;
return x - Math.floor(x);
}
const safeCount = Math.max(1, parseInt(itemCount) || 6);
const layoutMode = ['polaroid', 'grid', 'popart'].includes(layout) ? layout : 'polaroid';
if (layoutMode === 'polaroid') {
// Setup canvas size relative to a spacious gallery pinboard
const width = Math.max(1400, originalImg.width + 400);
const height = Math.max(900, originalImg.height + 400);
canvas.width = width;
canvas.height = height;
// Draw pinboard background
ctx.fillStyle = backgroundColor;
ctx.fillRect(0, 0, width, height);
// Calculate polaroid frame dimensions dynamically
const pWidth = Math.min(width, height) * 0.22;
const pHeight = pWidth * 1.25;
const imgSize = pWidth * 0.88;
const padding = (pWidth - imgSize) / 2;
for (let i = 0; i < safeCount; i++) {
ctx.save();
// Generate a random center position, keeping it away from absolute edges
const x = pWidth + random() * (width - pWidth * 1.8);
const y = pHeight + random() * (height - pHeight * 1.8);
const angle = (random() - 0.5) * 0.6; // random rotation ~ +/- 17 degrees
ctx.translate(x, y);
ctx.rotate(angle);
// Polaroid Drop Shadow
ctx.shadowColor = 'rgba(0, 0, 0, 0.25)';
ctx.shadowBlur = 12;
ctx.shadowOffsetX = 6;
ctx.shadowOffsetY = 8;
// Polaroid White Frame
ctx.fillStyle = '#ffffff';
ctx.fillRect(-pWidth / 2, -pHeight / 2, pWidth, pHeight);
// Reset shadow so the image itself doesn't drop a shadow inside the frame
ctx.shadowColor = 'transparent';
// Pick a random cropped area from the original image to showcase
const minImgDim = Math.min(originalImg.width, originalImg.height);
const cropSize = minImgDim * (0.4 + random() * 0.6);
const maxSx = originalImg.width - cropSize;
const maxSy = originalImg.height - cropSize;
const sx = random() * maxSx;
const sy = random() * maxSy;
// Draw cropped image (shifted up to leave the classic bottom margin)
const imgYOffset = -pHeight / 2 + padding;
ctx.drawImage(originalImg, sx, sy, cropSize, cropSize, -imgSize / 2, imgYOffset, imgSize, imgSize);
// Draw Washi Tape at the top to give a 'Gallery Wall' pinboard feel
ctx.save();
ctx.translate(0, -pHeight / 2);
ctx.rotate((random() - 0.5) * 0.2); // tape is slightly crooked
ctx.fillStyle = 'rgba(245, 245, 230, 0.85)'; // translucent yellowish tape
ctx.shadowColor = 'rgba(0, 0, 0, 0.15)';
ctx.shadowBlur = 4;
ctx.shadowOffsetX = 1;
ctx.shadowOffsetY = 2;
ctx.fillRect(-pWidth * 0.2, -padding, pWidth * 0.4, padding * 1.8);
ctx.restore();
ctx.restore();
}
}
else if (layoutMode === 'grid') {
// Grid Gallery (Mosaic Style)
const cols = Math.ceil(Math.sqrt(safeCount));
const rows = Math.ceil(safeCount / cols);
const gap = 15;
const margin = 30;
const canvasW = originalImg.width;
const canvasH = originalImg.height;
canvas.width = canvasW + margin * 2;
canvas.height = canvasH + margin * 2;
ctx.fillStyle = backgroundColor;
ctx.fillRect(0, 0, canvas.width, canvas.height);
const cellW = (canvasW - (cols - 1) * gap) / cols;
const cellH = (canvasH - (rows - 1) * gap) / rows;
for (let r = 0; r < rows; r++) {
for (let c = 0; c < cols; c++) {
if (r * cols + c >= safeCount) break;
const dx = margin + c * (cellW + gap);
const dy = margin + r * (cellH + gap);
const sx = c * (originalImg.width / cols);
const sy = r * (originalImg.height / rows);
const sWidth = originalImg.width / cols;
const sHeight = originalImg.height / rows;
ctx.shadowColor = 'rgba(0, 0, 0, 0.2)';
ctx.shadowBlur = 8;
ctx.shadowOffsetX = 4;
ctx.shadowOffsetY = 4;
ctx.drawImage(originalImg, sx, sy, sWidth, sHeight, dx, dy, cellW, cellH);
}
}
}
else if (layoutMode === 'popart') {
// Pop-Art Collection (Warhol Style 2x2 Grid)
const margin = 20;
const totalW = originalImg.width + margin * 2;
const totalH = originalImg.height + margin * 2;
canvas.width = totalW;
canvas.height = totalH;
ctx.fillStyle = backgroundColor;
ctx.fillRect(0, 0, totalW, totalH);
const w = originalImg.width / 2;
const h = originalImg.height / 2;
// Vivid color filters to simulate pop-art
const filters = [
'sepia(80%) hue-rotate(330deg) saturate(300%) contrast(120%)',
'sepia(100%) hue-rotate(90deg) saturate(250%) contrast(120%)',
'sepia(50%) hue-rotate(180deg) saturate(300%) contrast(110%)',
'hue-rotate(240deg) saturate(200%) contrast(130%)'
];
for (let i = 0; i < 4; i++) {
const c = i % 2;
const r = Math.floor(i / 2);
const dx = margin + c * w;
const dy = margin + r * h;
ctx.save();
ctx.filter = filters[i];
ctx.drawImage(originalImg, 0, 0, originalImg.width, originalImg.height, dx, dy, w, h);
ctx.restore();
// Draw an overlay border for each quad
ctx.strokeStyle = '#000000';
ctx.lineWidth = 4;
ctx.strokeRect(dx, dy, w, h);
}
}
return canvas;
}
Apply Changes