You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, theme = "light", padding = 40, canvasBgColor = "#e5e7eb", url = "www.example.com") {
// Parse padding in case it comes as a string parameter
const pad = parseInt(padding, 10) || 0;
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
// Website mock-up configuration
const headerHeight = 40;
const cornerRadius = 10;
const isDark = theme.toLowerCase() === "dark";
const imgWidth = originalImg.width;
const imgHeight = originalImg.height;
// Ensure a minimum width so the browser controls and address bar render decently
const winWidth = Math.max(imgWidth, 150);
const winHeight = imgHeight + headerHeight;
canvas.width = winWidth + pad * 2;
canvas.height = winHeight + pad * 2;
// 1. Draw outmost background
ctx.fillStyle = canvasBgColor;
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Helper function to create a rounded rectangle path (for max compatibility)
function buildRoundRectPath(x, y, w, h, r) {
ctx.beginPath();
ctx.moveTo(x + r, y);
ctx.arcTo(x + w, y, x + w, y + h, r);
ctx.arcTo(x + w, y + h, x, y + h, r);
ctx.arcTo(x, y + h, x, y, r);
ctx.arcTo(x, y, x + w, y, r);
ctx.closePath();
}
// 2. Draw mock window shadow
if (pad > 0) {
ctx.shadowColor = "rgba(0, 0, 0, 0.25)";
ctx.shadowBlur = Math.min(20, pad);
ctx.shadowOffsetY = Math.min(10, pad / 2);
ctx.shadowOffsetX = 0;
}
buildRoundRectPath(pad, pad, winWidth, winHeight, cornerRadius);
ctx.fillStyle = isDark ? "#1e1e1e" : "#ffffff";
ctx.fill();
// Reset shadow before drawing contents
ctx.shadowColor = "transparent";
ctx.shadowBlur = 0;
ctx.shadowOffsetY = 0;
// 3. Clip all inner contents to within the rounded corners of our window
ctx.save();
buildRoundRectPath(pad, pad, winWidth, winHeight, cornerRadius);
ctx.clip();
// 4. Draw Header/Top bar
ctx.fillStyle = isDark ? "#2d2d2d" : "#f1f1f1";
ctx.fillRect(pad, pad, winWidth, headerHeight);
// 5. Draw Mac-style Window Controls (the three dots)
const dotRadius = 6;
const dotY = pad + headerHeight / 2;
const btnColors = ["#ff5f56", "#ffbd2e", "#27c93f"];
btnColors.forEach((color, idx) => {
ctx.beginPath();
ctx.arc(pad + 20 + idx * 20, dotY, dotRadius, 0, Math.PI * 2);
ctx.fillStyle = color;
ctx.fill();
});
// 6. Draw Address Bar (only if there's enough horizontal room)
if (winWidth > 350) {
const urlWidth = winWidth * 0.6;
const urlHeight = 24;
const urlX = pad + (winWidth - urlWidth) / 2;
const urlY = pad + (headerHeight - urlHeight) / 2;
buildRoundRectPath(urlX, urlY, urlWidth, urlHeight, 6);
ctx.fillStyle = isDark ? "#1e1e1e" : "#ffffff";
ctx.fill();
// Add URL Text
if (url) {
ctx.fillStyle = isDark ? "#aaaaaa" : "#666666";
ctx.font = "12px -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillText(url, urlX + urlWidth / 2, urlY + urlHeight / 2 + 1);
}
}
// 7. Draw the original image centered within the mock window space
const imgX = pad + (winWidth - imgWidth) / 2;
ctx.drawImage(originalImg, imgX, pad + headerHeight);
// Restore context to unclip
ctx.restore();
// 8. Add a subtle border around the window for crispness
buildRoundRectPath(pad, pad, winWidth, winHeight, cornerRadius);
ctx.strokeStyle = isDark ? "rgba(255, 255, 255, 0.15)" : "rgba(0, 0, 0, 0.15)";
ctx.lineWidth = 1;
ctx.stroke();
return canvas;
}
Apply Changes