You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, logoShape = "circle", threshold = "128", smoothness = "2", fgColor = "#000000", bgColor = "transparent", borderWidth = "15", invert = "no") {
// Determine the size and proportions
const size = Math.min(originalImg.width, originalImg.height);
const finalWidth = logoShape === "none" ? originalImg.width : size;
const finalHeight = logoShape === "none" ? originalImg.height : size;
const canvas = document.createElement('canvas');
canvas.width = finalWidth;
canvas.height = finalHeight;
const ctx = canvas.getContext('2d');
// Helper to extract RGBA values from any valid CSS color string
function parseColor(c) {
if (c.toLowerCase() === 'transparent') return { r: 0, g: 0, b: 0, a: 0 };
const tempCanvas = document.createElement('canvas');
tempCanvas.width = 1;
tempCanvas.height = 1;
const tmpCtx = tempCanvas.getContext('2d');
tmpCtx.fillStyle = c;
tmpCtx.fillRect(0, 0, 1, 1);
const d = tmpCtx.getImageData(0, 0, 1, 1).data;
return { r: d[0], g: d[1], b: d[2], a: d[3] };
}
const fgRGB = parseColor(fgColor);
const bgRGB = parseColor(bgColor);
const thresh = parseInt(threshold, 10);
const blurLevel = parseInt(smoothness, 10);
// Calculate scaling and center crop if a specific shape is requested
let drawX = 0, drawY = 0, drawW = originalImg.width, drawH = originalImg.height;
if (logoShape !== "none") {
const scale = Math.max(finalWidth / originalImg.width, finalHeight / originalImg.height);
drawW = originalImg.width * scale;
drawH = originalImg.height * scale;
drawX = (finalWidth - drawW) / 2;
drawY = (finalHeight - drawH) / 2;
}
// Apply a blur before thresholding to organically smooth edges (simulating vector style)
if (blurLevel > 0) {
ctx.filter = `blur(${blurLevel}px)`;
}
ctx.drawImage(originalImg, drawX, drawY, drawW, drawH);
ctx.filter = 'none';
// Stencil/Threshold Effect
const imgData = ctx.getImageData(0, 0, finalWidth, finalHeight);
const data = imgData.data;
const doInvert = invert === "yes";
const colorDark = doInvert ? bgRGB : fgRGB;
const colorLight = doInvert ? fgRGB : bgRGB;
for (let i = 0; i < data.length; i += 4) {
const a = data[i + 3];
// Treat fully/mostly transparent pixels natively as background
if (a < 128) {
data[i] = colorLight.r;
data[i + 1] = colorLight.g;
data[i + 2] = colorLight.b;
data[i + 3] = colorLight.a;
} else {
// Calculate luminance for stencil cutoff
const lum = 0.299 * data[i] + 0.587 * data[i + 1] + 0.114 * data[i + 2];
if (lum < thresh) {
// Dark areas map to one color
data[i] = colorDark.r;
data[i + 1] = colorDark.g;
data[i + 2] = colorDark.b;
data[i + 3] = colorDark.a;
} else {
// Light areas map to the other
data[i] = colorLight.r;
data[i + 1] = colorLight.g;
data[i + 2] = colorLight.b;
data[i + 3] = colorLight.a;
}
}
}
ctx.putImageData(imgData, 0, 0);
// Apply Framing / Mascot Shape Clipping
if (logoShape !== "none") {
const bw = parseInt(borderWidth, 10);
const outCanvas = document.createElement('canvas');
outCanvas.width = finalWidth;
outCanvas.height = finalHeight;
const outCtx = outCanvas.getContext('2d');
const cx = finalWidth / 2;
const cy = finalHeight / 2;
outCtx.save();
if (logoShape === "circle") {
const radius = cx - bw / 2;
outCtx.beginPath();
outCtx.arc(cx, cy, radius, 0, Math.PI * 2);
outCtx.clip();
outCtx.drawImage(canvas, 0, 0);
outCtx.restore();
// Add Badge Rim
if (bw > 0) {
outCtx.lineWidth = bw;
outCtx.strokeStyle = fgColor;
outCtx.beginPath();
outCtx.arc(cx, cy, radius, 0, Math.PI * 2);
outCtx.stroke();
}
} else if (logoShape === "square") {
// "Squircle" bounds for a more stylistic logo feel
const radius = Math.min(finalWidth * 0.15, cx);
const x = bw / 2;
const y = bw / 2;
const w = finalWidth - bw;
const h = finalHeight - bw;
// Generate precise cross-browser rounded corners path
const generateRoundRectBound = () => {
outCtx.moveTo(x + radius, y);
outCtx.lineTo(x + w - radius, y);
outCtx.quadraticCurveTo(x + w, y, x + w, y + radius);
outCtx.lineTo(x + w, y + h - radius);
outCtx.quadraticCurveTo(x + w, y + h, x + w - radius, y + h);
outCtx.lineTo(x + radius, y + h);
outCtx.quadraticCurveTo(x, y + h, x, y + h - radius);
outCtx.lineTo(x, y + radius);
outCtx.quadraticCurveTo(x, y, x + radius, y);
};
outCtx.beginPath();
generateRoundRectBound();
outCtx.closePath();
outCtx.clip();
outCtx.drawImage(canvas, 0, 0);
outCtx.restore();
if (bw > 0) {
outCtx.lineWidth = bw;
outCtx.strokeStyle = fgColor;
outCtx.beginPath();
generateRoundRectBound();
outCtx.closePath();
outCtx.stroke();
}
}
return outCanvas;
}
return canvas;
}
Apply Changes