You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, cellSize = 10, dingbatsStr = ' ✢✤✥✦✧★✩✪✫✬✭✮✯✰✱✲✳✴✵✶✷✸✹✺✻✼✽✾✿❀❁❂❃❄❅❆❇❈❉❊❋❍❏❐❑❒❖❘❙❚❤❥❦❧➔➕➖', bgColor = '#ffffff', useOriginalColor = 1, overrideColor = '#000000') {
// Validate and parse parameters
cellSize = Number(cellSize) || 10;
if (cellSize < 2) cellSize = 2; // Prevent performance issues with extremely small grid cells
const isOriginalColor = Number(useOriginalColor) !== 0;
// Deduplicate and get characters (handles complex Unicode surrogate pairs)
const chars = Array.from(new Set(Array.from(dingbatsStr)));
if (chars.length === 0) chars.push(' ');
// Pre-calculate visual density of each dingbat character map
const measureCanvas = document.createElement('canvas');
measureCanvas.width = 40;
measureCanvas.height = 40;
const mCtx = measureCanvas.getContext('2d', { willReadFrequently: true });
mCtx.font = '24px sans-serif';
mCtx.textBaseline = 'middle';
mCtx.textAlign = 'center';
const charDensities = chars.map(char => {
mCtx.clearRect(0, 0, 40, 40);
mCtx.fillStyle = '#000000';
mCtx.fillText(char, 20, 20);
const data = mCtx.getImageData(0, 0, 40, 40).data;
let density = 0;
for (let i = 3; i < data.length; i += 4) {
density += data[i]; // Sum of the alpha channel maps to visual density
}
return { char, density };
});
// Sort ascending (lowest density/lightest first to highest density/darkest last)
charDensities.sort((a, b) => a.density - b.density);
const sortedChars = charDensities.map(c => c.char);
const width = originalImg.naturalWidth || originalImg.width;
const height = originalImg.naturalWidth || originalImg.height;
// Read original image pixels
const offCanvas = document.createElement('canvas');
offCanvas.width = width;
offCanvas.height = height;
const offCtx = offCanvas.getContext('2d', { willReadFrequently: true });
offCtx.drawImage(originalImg, 0, 0, width, height);
let imgData;
try {
imgData = offCtx.getImageData(0, 0, width, height).data;
} catch (e) {
// Fallback for CORS origin tainted canvas issues
const errCanvas = document.createElement('canvas');
errCanvas.width = Math.max(width, 400);
errCanvas.height = Math.max(height, 100);
const errCtx = errCanvas.getContext('2d');
errCtx.fillStyle = '#ffffff';
errCtx.fillRect(0, 0, errCanvas.width, errCanvas.height);
errCtx.fillStyle = '#ff0000';
errCtx.font = '16px sans-serif';
errCtx.fillText("Error: Canvas tainted by cross-origin data. Cannot read image pixels.", 20, 40);
return errCanvas;
}
// Output generation
const outCanvas = document.createElement('canvas');
outCanvas.width = width;
outCanvas.height = height;
const outCtx = outCanvas.getContext('2d');
// Fill the background
outCtx.fillStyle = bgColor;
outCtx.fillRect(0, 0, width, height);
outCtx.textBaseline = 'middle';
outCtx.textAlign = 'center';
// Scale the font size slightly above cellSize to remove extra gaps but keep grid alignment
outCtx.font = `${Math.floor(cellSize * 1.1)}px Arial, sans-serif`;
const numChars = sortedChars.length;
// Process grid cells
for (let y = 0; y < height; y += cellSize) {
for (let x = 0; x < width; x += cellSize) {
// Get center pixel of the current grid cell
let sampleX = Math.min(x + Math.floor(cellSize / 2), width - 1);
let sampleY = Math.min(y + Math.floor(cellSize / 2), height - 1);
const i = (sampleY * width + sampleX) * 4;
const r = imgData[i];
const g = imgData[i + 1];
const b = imgData[i + 2];
const a = imgData[i + 3];
// Ignore transparent pixels
if (a < 128) continue;
// Calculate luminance/brightness of original pixel (returns 0-255)
const brightness = (r * 0.299 + g * 0.587 + b * 0.114);
// Map brightness to sorted index
// 255 (white/bright) -> Lightest character (index 0)
// 0 (black/dark) -> Darkest character (index numChars - 1)
let mappedIndex = Math.floor((1 - brightness / 255) * (numChars - 1));
// Safety bounds
if (mappedIndex < 0) mappedIndex = 0;
if (mappedIndex >= numChars) mappedIndex = numChars - 1;
const selectedChar = sortedChars[mappedIndex];
// Apply color
if (isOriginalColor) {
outCtx.fillStyle = `rgb(${r}, ${g}, ${b})`;
} else {
outCtx.fillStyle = overrideColor;
}
// Draw dingbat logotype
outCtx.fillText(selectedChar, x + cellSize / 2, y + cellSize / 2);
}
}
return outCanvas;
}
Apply Changes