El resultado se muestra a continuación:
El arte ASCII se ha utilizado cuando no es posible la transmisión o la impresión de imágenes en las configuraciones de equipos computarizados, tales como maquinillas, teletipos y equipos de visualización (consolas y terminales) que no cuentan con tarjetas de proceso gráfico. El arte ASCII ha servido como lenguaje fuente para representar logos de compañías y productos, para crear diagramas procedimentales de flujo de operaciones y también en el diseño de los primeros videojuegos.
Para analizar de manera satisfactoria una imagen y convertirla a ASCII art, se debe analizar la imagen por regiones. El bloque a analizar puede ser de longitud variable, pero deben tenerse en cuenta distintos factores, como el tamaño de los simbolos ASCII o la densidad de la imagen.
Se tienen variables globales importantes como blockSize, que define el tamaño del bloque a analizar.
1linklet img;
2linklet v = 1.0 / 9.0;
3linklet blockSize = 3;
4linklet count = 500;
5link
6linkfunction preload() {
7link img = loadImage("/vc/docs/sketches/workshops/imaging/BabyYoda.jpg");
8link}
9link
10linkfunction setup() {
11link createCanvas(800, 550);
12link img.resize(800, 550);
13link noLoop();
14link}
15link
16linkfunction draw() {
17link background(255);
18link //image(img, 0, 0);
19link
20link img.loadPixels();
21link
22link let d = pixelDensity();
23link let npixels = 4 * (width * d) * (height * d);
24link //text(pixels.length, 200, 200);
25link for (let x = 0; x < width; x += blockSize) {
26link for (let y = 0; y < height; y += blockSize) {
27link scanBlock(x, y);
28link }
29link }
30link}
La función scanBlock toma un bloque individual de datos y lo envía a la función patternDef, para definir su nivel de brillo y así, asignar un ASCII correspondiente.
1linkfunction scanBlock(x, y) {
2link let sizeDef = 4 * blockSize;
3link let blockInformation = new Array(4 * blockSize);
4link let index = 0;
5link while (index < blockSize) {
6link let startPosition = (x + y * width) * 4;
7link blockInformation[index * 4] = img.pixels[startPosition];
8link blockInformation[index * 4 + 1] = img.pixels[startPosition + 1];
9link blockInformation[index * 4 + 2] = img.pixels[startPosition + 2];
10link blockInformation[index * 4 + 3] = img.pixels[startPosition + 3];
11link index++;
12link }
13link let res = patternDef(blockInformation);
14link textSize(10);
15link text(res, x, y);
16link
17link}
La función patternDef toma un bloque de información y lo analiza. Encuentra el brillo promedio del bloque y envía el resultado estandarizado (un valor entre 0 y 1) a la funcion selectCharacter, que se encargará de asignar un caracter a cada bloque analizado.
1linkfunction patternDef(blockInformation) {
2link let brillos = [];
3link let suma = 0;
4link for (let i = 0; i < blockInformation.length; i += 4) {
5link let br =
6link blockInformation[i] * 0.2126 +
7link blockInformation[i + 1] * 0.7152 +
8link blockInformation[i + 2] * 0.0722;
9link brillos.push(br);
10link }
11link
12link brillos.forEach((element) => {
13link suma += element;
14link });
15link let promedio = suma / brillos.length;
16link let result = promedio / 255;
17link return selectCharacter(result);
18link
19link}
La función selectCharacter recibe la intensidad de un bloque previamente analizado, y selecciona un ASCII adecuado para el ASCII art. Esta función es de mucha utilidad, ya que sin ella los caracteres no podrían representar la opacidad o profundidad de la imagen procesada.
1linkfunction selectCharacter(result) {
2link if (result > 0 && result <= 0.1) {
3link return "▓";
4link } else if (result > 0.1 && result <= 0.2) {
5link return "▒";
6link } else if (result > 0.2 && result <= 0.3) {
7link return "#";
8link } else if (result > 0.3 && result <= 0.4) {
9link return "@";
10link } else if (result > 0.4 && result <= 0.5) {
11link return "%";
12link } else if (result > 0.5 && result <= 0.6) {
13link return "E";
14link } else if (result > 0.6 && result <= 0.7) {
15link return "=";
16link } else if (result > 0.7 && result <= 0.8) {
17link return "0";
18link } else if (result > 0.8 && result <= 0.9) {
19link return "/";
20link } else if (result > 0.9 && result <= 1) {
21link return ".";
22link }
23link}