You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, maxWidth = 80, charset = " `.-':_,^=;><+!rc*/z?sLTv)J7(|Fi{C}fI31tlu[neoZ5Yxjya]2ESwqkP6h9d4VpOGbUAKXHm8RD#$Bg0MNWe%&@", useColor = 1, invert = 0) {
/**
* Helper function to generate an ANSI 256 color palette as an array of [r, g, b] tuples.
* The result is memoized on the function itself for performance.
* @returns {Array<[number, number, number]>} The sRGB palette.
*/
const generateAnsiPalette = () => {
if (generateAnsiPalette.palette) {
return generateAnsiPalette.palette;
}
const palette = [];
// 16 standard colors (using a common sRGB approximation)
palette.push([0, 0, 0], [170, 0, 0], [0, 170, 0], [170, 85, 0], [0, 0, 170], [170, 0, 170], [0, 170, 170], [170, 170, 170]);
palette.push([85, 85, 85], [255, 85, 85], [85, 255, 85], [255, 255, 85], [85, 85, 255], [255, 85, 255], [85, 255, 255], [255, 255, 255]);
// 6x6x6 color cube (colors 16-231)
const levels = [0, 95, 135, 175, 215, 255];
for (let r = 0; r < 6; r++) {
for (let g = 0; g < 6; g++) {
for (let b = 0; b < 6; b++) {
palette.push([levels[r], levels[g], levels[b]]);
}
}
}
// Grayscale ramp (colors 232-255)
for (let i = 0; i < 24; i++) {
const level = 8 + i * 10;
palette.push([level, level, level]);
}
generateAnsiPalette.palette = palette;
return palette;
};
/**
* Finds the nearest color in the palette to a given RGB color.
* @param {number} r - Red component (0-255).
* @param {number} g - Green component (0-255).
* @param {number} b - Blue component (0-255).
* @param {Array<[number, number, number]>} palette - The color palette to search in.
* @returns {[number, number, number]} The closest color from the palette.
*/
const findNearestColor = (r, g, b, palette) => {
let minDistanceSq = Infinity;
let closestColor = palette[0];
for (const color of palette) {
const dr = r - color[0];
const dg = g - color[1];
const db = b - color[2];
const d2 = dr * dr + dg * dg + db * db;
if (d2 < minDistanceSq) {
minDistanceSq = d2;
closestColor = color;
}
}
return closestColor;
};
// 1. Parameter parsing
const width = parseInt(String(maxWidth), 10) || 80;
const colorEnabled = parseInt(String(useColor), 10) === 1;
const inverted = parseInt(String(invert), 10) === 1;
// 2. Canvas setup and image scaling
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d', { willReadFrequently: true });
const aspectRatio = originalImg.width / originalImg.height;
const newWidth = width;
// Correct for the aspect ratio of typical monospace fonts (taller than wide)
const newHeight = Math.round((newWidth / aspectRatio) * 0.5);
canvas.width = newWidth;
canvas.height = newHeight;
ctx.drawImage(originalImg, 0, 0, newWidth, newHeight);
const imageData = ctx.getImageData(0, 0, newWidth, newHeight);
const data = imageData.data;
// 3. Prepare output element and character set
const pre = document.createElement('pre');
pre.style.fontFamily = '"Courier New", Courier, monospace';
pre.style.backgroundColor = '#1e1e1e'; // Common terminal background color
pre.style.color = '#cccccc'; // Common terminal text color
pre.style.lineHeight = '1.0';
pre.style.fontSize = '12px'; // Font size affects final rendered aspect ratio
pre.style.margin = '0';
pre.style.whiteSpace = 'pre'; // Crucial for respecting newlines and spaces
const ansiPalette = colorEnabled ? generateAnsiPalette() : null;
const finalCharset = inverted ? charset.split('').reverse().join('') : charset;
const charLen = finalCharset.length;
// 4. Build output using a DocumentFragment for efficient DOM manipulation
const fragment = document.createDocumentFragment();
for (let y = 0; y < newHeight; y++) {
for (let x = 0; x < newWidth; x++) {
const i = (y * newWidth + x) * 4;
const r = data[i];
const g = data[i + 1];
const b = data[i + 2];
const a = data[i + 3];
// Use a space for transparent/semi-transparent pixels
if (a < 128) {
fragment.appendChild(document.createTextNode(' '));
continue;
}
// Calculate grayscale value to map to a character
const gray = (0.299 * r + 0.587 * g + 0.114 * b);
// Map the grayscale value (0-255) to an index in the charset
const charIndex = Math.floor((gray / 256) * charLen);
const char = finalCharset[charIndex] || ' ';
if (colorEnabled) {
const nearestColor = findNearestColor(r, g, b, ansiPalette);
const span = document.createElement('span');
span.textContent = char;
span.style.color = `rgb(${nearestColor[0]}, ${nearestColor[1]}, ${nearestColor[2]})`;
fragment.appendChild(span);
} else {
fragment.appendChild(document.createTextNode(char));
}
}
fragment.appendChild(document.createTextNode('\n'));
}
pre.appendChild(fragment);
// 5. Return final DOM element
return pre;
}
Apply Changes
Could help, if you could download an actual ANSI file, not PNG of ansi picture ffs.