JSFiddle - React, Tailwind, and code Playground
by Scott Kaye
HTML
<span id="out"></span>
<div class="message">Drag and drop an image to box on the right.</div>
CSS
body {
margin: 0;
background: #111;
color: #fff;
}
#out {
font-family: monospace;
font-size: 16px;
white-space: pre;
display: block;
zoom: 0.5;
}
canvas {
position: fixed;
top: 0;
right: 0;
padding: 0.5vw;
margin: 0.5vw;
background: #666;
max-width: 25vw;
max-height: 25vw;
}
canvas.drag {
background: #38f;
}
.message {
background: #222;
padding: 25px;
font-family: Segoe UI, sans-serif;
}
JavaScript
const out = document.getElementById("out");
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
const RESOLUTION_FACTOR = 5;
const VERTICAL_SQUISH = 2;
document.body.appendChild(canvas);
canvas.ondragover = function(e) {
canvas.classList.add("drag");
e.preventDefault();
};
canvas.ondragleave = function(e) {
canvas.classList.remove("drag");
e.preventDefault();
};
canvas.ondrop = async function(e) {
e.preventDefault();
canvas.classList.remove("drag");
let file = e.dataTransfer.files[0];
if (!file) {
return;
}
let image = await window.createImageBitmap(file);
loadImage(image);
generateASCII();
};
let pixels = ` .,╹░█`;
const scale = (num, in_min, in_max, out_min, out_max) => {
return (num - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
function loadImage(img) {
canvas.width = img.width / RESOLUTION_FACTOR;
canvas.height = img.height / RESOLUTION_FACTOR / VERTICAL_SQUISH;
ctx.drawImage(img,
0, 0, img.width, img.height,
0, 0, img.width / RESOLUTION_FACTOR, img.height / RESOLUTION_FACTOR / VERTICAL_SQUISH
);
}
function generateASCII() {
let imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
let result = imageData.data.batch(4).reduce((a, c, i) => {
let avg = (c[0] + c[1] + c[2]) / 3;
let pixel = pixels[scale(avg, 0, 255, 0, pixels.length - 1) | 0];
return a + pixel + (i % (imageData.width) !== 0 ? "" : "\n");
}, "");
out.textContent = result;
}
Uint8ClampedArray.prototype.batch = function(size) {
let result = [];
for (let i = 0; i < this.length; i += size) {
let subResult = [];
for (let j = 0; j < size; ++j) {
subResult.push(this[i + j]);
}
result.push(subResult);
}
return result;
};