You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(
originalImg,
windowWidth = 1024,
padding = 64,
addressText = "https://www.company-studio.com",
theme = "light",
canvasBgColor = "#e0e5ec",
showShadow = "true",
cornerRadius = 12
) {
// Parse and validate numeric parameters to prevent bugs from falsy values like "0"
windowWidth = Number(windowWidth);
if (isNaN(windowWidth) || windowWidth <= 0) windowWidth = 1024;
padding = Number(padding);
if (isNaN(padding) || padding < 0) padding = 64;
cornerRadius = Number(cornerRadius);
if (isNaN(cornerRadius) || cornerRadius < 0) cornerRadius = 12;
const doShadow = (String(showShadow).trim().toLowerCase() === "true");
const isDark = (String(theme).trim().toLowerCase() === "dark");
// Theme colors
const headerBgColor = isDark ? "#333333" : "#f1f1f1";
const addrBgColor = isDark ? "#1e1e1e" : "#ffffff";
const addrTextColor = isDark ? "#aaaaaa" : "#666666";
const dotColors = ["#ff5f56", "#ffbd2e", "#27c93f"];
// Layout configuration
const headerHeight = 56;
// Calculate aspect ratio and dimensions
const imgRatio = originalImg.height / originalImg.width;
const imgHeight = windowWidth * imgRatio;
const windowHeight = headerHeight + imgHeight;
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
// Adjust canvas size to fit the window and its padding/shadow
canvas.width = windowWidth + padding * 2;
canvas.height = windowHeight + padding * 2;
// Helper for drawing rounded paths across all browsers safely
const buildRoundRectPath = (x, y, w, h, r) => {
ctx.beginPath();
ctx.moveTo(x + r, y);
ctx.lineTo(x + w - r, y);
ctx.quadraticCurveTo(x + w, y, x + w, y + r);
ctx.lineTo(x + w, y + h - r);
ctx.quadraticCurveTo(x + w, y + h, x + w - r, y + h);
ctx.lineTo(x + r, y + h);
ctx.quadraticCurveTo(x, y + h, x, y + h - r);
ctx.lineTo(x, y + r);
ctx.quadraticCurveTo(x, y, x + r, y);
ctx.closePath();
};
// 1. Draw Canvas Background
ctx.fillStyle = canvasBgColor;
ctx.fillRect(0, 0, canvas.width, canvas.height);
const winX = padding;
const winY = padding;
// 2. Draw Optional Window Drop Shadow
if (doShadow) {
ctx.save();
buildRoundRectPath(winX, winY, windowWidth, windowHeight, cornerRadius);
ctx.shadowColor = "rgba(0, 0, 0, 0.25)";
ctx.shadowBlur = 40;
ctx.shadowOffsetY = 15;
ctx.fillStyle = "#ffffff";
ctx.fill();
ctx.restore();
}
// 3. Define Window Clipping Mask (prevents internal elements from overflowing the corners)
ctx.save();
buildRoundRectPath(winX, winY, windowWidth, windowHeight, cornerRadius);
ctx.clip();
// 4. Draw Header / Address Bar section
ctx.fillStyle = headerBgColor;
ctx.fillRect(winX, winY, windowWidth, headerHeight);
// Draw Mac-style Window Controls
const dotY = winY + headerHeight / 2;
const startX = winX + 22;
const dotRadius = 6;
const dotSpacing = 20;
dotColors.forEach((color, i) => {
ctx.beginPath();
ctx.arc(startX + i * dotSpacing, dotY, dotRadius, 0, Math.PI * 2);
ctx.fillStyle = color;
ctx.fill();
});
// Address Bar background
const addrWidth = windowWidth * 0.55;
const addrHeight = 28;
const addrX = winX + (windowWidth - addrWidth) / 2;
const addrY = winY + (headerHeight - addrHeight) / 2;
ctx.fillStyle = addrBgColor;
buildRoundRectPath(addrX, addrY, addrWidth, addrHeight, 6);
ctx.fill();
// Address Tool Padlock Icon
const lockSize = 10;
const lockX = addrX + 20;
const lockY = addrY + (addrHeight / 2);
ctx.fillStyle = addrTextColor;
ctx.fillRect(lockX - lockSize / 2, lockY, lockSize, lockSize * 0.7);
ctx.beginPath();
ctx.arc(lockX, lockY, lockSize / 2, Math.PI, 0); // Open upward semi-circle for the shackle
ctx.strokeStyle = addrTextColor;
ctx.lineWidth = 1.5;
ctx.stroke();
// Address Bar Text Overlay
ctx.fillStyle = addrTextColor;
ctx.font = "13px -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
// Sub-clip the address text to gracefully hide it if line exceeds bar logic
ctx.save();
buildRoundRectPath(addrX, addrY, addrWidth, addrHeight, 6);
ctx.clip();
ctx.fillText(addressText, addrX + addrWidth / 2, addrY + addrHeight / 2);
ctx.restore();
// 5. Draw Target Website Interface Image Layout
ctx.drawImage(originalImg, winX, winY + headerHeight, windowWidth, imgHeight);
// Removing main window clip
ctx.restore();
// 6. Draw Subtle Window Borders
buildRoundRectPath(winX, winY, windowWidth, windowHeight, cornerRadius);
ctx.strokeStyle = isDark ? "rgba(255, 255, 255, 0.15)" : "rgba(0, 0, 0, 0.1)";
ctx.lineWidth = 1;
ctx.stroke();
// Header border separator line
ctx.beginPath();
ctx.moveTo(winX, winY + headerHeight);
ctx.lineTo(winX + windowWidth, winY + headerHeight);
ctx.strokeStyle = isDark ? "rgba(255, 255, 255, 0.05)" : "rgba(0, 0, 0, 0.08)";
ctx.stroke();
return canvas;
}
Apply Changes