Text-zu-Bild ASCII-Art Generator mit Canvas und Text-Messung
Erstelle ASCII-Art aus Videos, indem du Text-Zeichen auf ein Raster legst und die Helligkeit von Video-Pixeln nutzt, um festzulegen, welche Zeichen angezeigt werden.
Originalvideo ansehen: He just crawled through hell to fix the browser…4 Schritte
1
Character-Grid mit Text-Messung erstellen
Nutze Pretext, um ein Raster zu erstellen, bei dem jede Cell genau ein Character enthält
const script = 'Dein langer Text...'; // Die ASCII-Art Zeichen
const segments = pretext.prepare(script, { font: '10px monospace' });
const characterGrid = [];
let charIndex = 0;
for (let row = 0; row < totalRows; row++) {
const layoutInfo = pretext.layout(segments, { width: containerWidth });
// Jede Row entspricht einer Zeile im Video
characterGrid[row] = script.substring(charIndex, charIndex + layoutInfo.charsPerLine);
charIndex += layoutInfo.charsPerLine;
}Tipp: Verwende Monospace-Font für gleichmäßiges Raster
Warnung: Character-Count pro Zeile ändert sich mit Font-Größe
2
Video auf offscreen Canvas zeichnen und Pixel auslesen
Zeichne das Video auf ein Canvas-Element derselben Größe wie das Character-Grid und lese die Helligkeit aus
const offscreenCanvas = document.createElement('canvas');
offscreenCanvas.width = characterGrid[0].length * charWidth;
offscreenCanvas.height = characterGrid.length * charHeight;
const offscreenCtx = offscreenCanvas.getContext('2d');
// Video-Frame zeichnen
offscreenCtx.drawImage(videoElement, 0, 0, offscreenCanvas.width, offscreenCanvas.height);
// Pixel-Daten auslesen
const imageData = offscreenCtx.getImageData(0, 0, offscreenCanvas.width, offscreenCanvas.height);
const pixelData = imageData.data; // RGBA-ArrayTipp: Canvas sollte genau die Größe des Character-Grids haben
Warnung: getImageData() ist synchron und kann langsam sein bei großen Canvas
3
Pixel-Helligkeit pro Character-Cell berechnen
Für jede Cell im Grid, berechne die durchschnittliche Helligkeit der entsprechenden Pixel
function getPixelBrightness(pixelData, x, y, pixelIndex) {
const r = pixelData[pixelIndex];
const g = pixelData[pixelIndex + 1];
const b = pixelData[pixelIndex + 2];
// Luminosity-Formel
return 0.299 * r + 0.587 * g + 0.114 * b;
}
const brightnessGrid = [];
for (let row = 0; row < characterGrid.length; row++) {
brightnessGrid[row] = [];
for (let col = 0; col < characterGrid[row].length; col++) {
const pixelX = col * charWidth;
const pixelY = row * charHeight;
const pixelIndex = (pixelY * offscreenCanvas.width + pixelX) * 4;
brightnessGrid[row][col] = getPixelBrightness(pixelData, pixelX, pixelY, pixelIndex);
}
}Tipp: Luminosity-Formel besser als einfacher Durchschnitt für menschliches Auge
Warnung: Performance kritisch; erwäge WebWorker für große Grids
4
Characters basierend auf Helligkeit rendern
Zeige nur Characters an, wenn die entsprechenden Pixel hell genug sind
const brightnessThreshold = 128; // Schwellenwert anpassen
const finalHTML = characterGrid.map((row, rowIndex) => {
return row.split('').map((char, colIndex) => {
const brightness = brightnessGrid[rowIndex][colIndex];
if (brightness > brightnessThreshold) {
return `<span style="color: rgb(${brightness}, ${brightness}, ${brightness})">${char}</span>`;
}
return '<span> </span>'; // Leerer Platz
}).join('');
}).join('<br>');
document.getElementById('output').innerHTML = finalHTML;Tipp: Variantentext-Helligkeitswerte für Graustufeneffekte
Warnung: Zu niedriger Threshold = unlesbares Chaos; zu hoch = keine Details