You can edit the below JavaScript code to customize the image tool.
Apply Changes
async function processImage(originalImg, spiralColor = 'rgba(255, 255, 255, 0.8)', lineWidth = 2, startCorner = 'top-left') {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const A4_RATIO = Math.sqrt(2); // ~1.414
const MAX_DIM = 1024;
let canvasWidth, canvasHeight;
// Determine canvas dimensions based on original image orientation, but enforcing A4 ratio
if (originalImg.naturalWidth > originalImg.naturalHeight) { // Landscape image
canvasWidth = Math.min(originalImg.naturalWidth, MAX_DIM);
canvasHeight = canvasWidth / A4_RATIO;
} else { // Portrait or square image
canvasHeight = Math.min(originalImg.naturalHeight, MAX_DIM);
canvasWidth = canvasHeight / A4_RATIO;
}
canvas.width = canvasWidth;
canvas.height = canvasHeight;
ctx.fillStyle = 'black';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Draw the image centered and scaled to fit (letterboxed)
const imgRatio = originalImg.naturalWidth / originalImg.naturalHeight;
let drawWidth = canvas.width;
let drawHeight = canvas.height;
let dx = 0;
let dy = 0;
if (imgRatio > canvas.width / canvas.height) {
drawHeight = canvas.width / imgRatio;
dy = (canvas.height - drawHeight) / 2;
} else {
drawWidth = canvas.height * imgRatio;
dx = (canvas.width - drawWidth) / 2;
}
ctx.drawImage(originalImg, dx, dy, drawWidth, drawHeight);
// --- Spiral Drawing Logic ---
ctx.strokeStyle = spiralColor;
ctx.lineWidth = lineWidth;
ctx.lineCap = 'round';
let rect = {
x: 0,
y: 0,
w: canvas.width,
h: canvas.height
};
ctx.beginPath();
// Each corner has a different sequence of placing the squares to create a clockwise spiral converging on that corner.
const sequences = {
'top-left': ['right', 'bottom', 'left', 'top'],
'top-right': ['left', 'bottom', 'right', 'top'],
'bottom-right': ['left', 'top', 'right', 'bottom'],
'bottom-left': ['right', 'top', 'left', 'bottom']
};
const sequence = sequences[startCorner] || sequences['top-left'];
for (let i = 0; i < 16; i++) {
const placement = sequence[i % 4];
let radius;
if (placement === 'left' || placement === 'right') {
// These placements require a landscape-oriented rectangle
if (rect.w <= rect.h) break;
radius = rect.h;
if (placement === 'left') {
// Place square on the left, arc center is square's bottom-right
ctx.moveTo(rect.x + radius, rect.y);
ctx.arc(rect.x + radius, rect.y + radius, radius, 1.5 * Math.PI, 2 * Math.PI);
rect.x += radius;
rect.w -= radius;
} else { // right
// Place square on the right, arc center is square's bottom-left
ctx.moveTo(rect.x + rect.w, rect.y + radius);
ctx.arc(rect.x + rect.w - radius, rect.y + radius, radius, 0, 0.5 * Math.PI);
rect.w -= radius;
}
} else { // top or bottom
// These placements require a portrait-oriented rectangle
if (rect.h <= rect.w) break;
radius = rect.w;
if (placement === 'top') {
// Place square on the top, arc center is square's bottom-right
ctx.moveTo(rect.x, rect.y + radius);
ctx.arc(rect.x + radius, rect.y + radius, radius, Math.PI, 1.5 * Math.PI);
rect.y += radius;
rect.h -= radius;
} else { // bottom
// Place square on the bottom, arc center is square's top-right
ctx.moveTo(rect.x + radius, rect.y + rect.h);
ctx.arc(rect.x + radius, rect.y + rect.h - radius, radius, 0.5 * Math.PI, Math.PI);
rect.h -= radius;
}
}
if (radius < 1) break;
}
ctx.stroke();
return canvas;
}
Apply Changes