El arte ASCII a todo color solía ser bastante popular en DOS, lo que podía aprovechar el juego de caracteres ASCII extendido y su colección de elementos de dibujo. Puede agregar un poco de interés visual a su próximo programa FreeDOS agregando arte ASCII como una pantalla de "bienvenida" genial o como una pantalla de "salida" colorida con más información sobre el programa.
Pero este estilo de arte ASCII no se limita solo a las aplicaciones FreeDOS. Puede usar el mismo método en un programa en modo terminal de Linux. Si bien Linux usa ncurses para controlar la pantalla en lugar de conio de DOS, los conceptos relacionados se aplican bien a los programas de Linux. Este artículo analiza cómo generar arte ASCII colorido a partir de un programa C.
Más recursos de Linux
- Hoja de trucos de los comandos de Linux
- Hoja de trucos de comandos avanzados de Linux
- Curso en línea gratuito:Descripción general técnica de RHEL
- Hoja de trucos de red de Linux
- Hoja de trucos de SELinux
- Hoja de trucos de los comandos comunes de Linux
- ¿Qué son los contenedores de Linux?
- Nuestros últimos artículos sobre Linux
Un archivo de arte ASCII
Puede usar una variedad de herramientas para dibujar su arte ASCII. Para este ejemplo, utilicé una antigua aplicación de DOS llamada TheDraw, pero puede encontrar programas modernos de arte ASCII de código abierto en Linux, como Moebius (licencia Apache) o PabloDraw (licencia MIT). No importa qué herramienta utilice, siempre y cuando sepa cómo se ven los datos guardados.
Aquí hay parte de un archivo de arte ASCII de muestra, guardado como código fuente C. Tenga en cuenta que el fragmento de código define algunos valores:IMAGEDATA_WIDTH
y IMAGEDATA_DEPTH
definir el número de columnas y filas en la pantalla. En este caso, es una "imagen" de arte ASCII de 80x25. IMAGEDATA_LENGTH
define el número de entradas en el IMAGEDATA
formación. Cada carácter en la pantalla de arte ASCII se puede representar mediante dos bytes de datos:el carácter que se mostrará y un atributo de color que contiene los colores frontal y de fondo del carácter. Para una pantalla de 80x25, donde cada carácter se empareja con un atributo, la matriz contiene 4000 entradas (es decir, 80 * 25 * 2 =4000).
#define IMAGEDATA_WIDTH 80
#define IMAGEDATA_DEPTH 25
#define IMAGEDATA_LENGTH 4000
unsigned char IMAGEDATA [] = {
'.', 0x08, ' ', 0x08, ' ', 0x08, ' ', 0x08, ' ', 0x08, ' ', 0x08,
' ', 0x08, ' ', 0x08, '.', 0x0F, ' ', 0x08, ' ', 0x08, ' ', 0x08,
' ', 0x08, ' ', 0x08, ' ', 0x08, ' ', 0x08, ' ', 0x08, '.', 0x0F,
' ', 0x08, ' ', 0x08, ' ', 0x08, ' ', 0x08, ' ', 0x08, ' ', 0x08,
' ', 0x08, ' ', 0x08, ' ', 0x08, ' ', 0x08, ' ', 0x08, ' ', 0x08,
y así sucesivamente para el resto de la matriz.
Para mostrar este arte ASCII en la pantalla, debe escribir un pequeño programa para leer la matriz e imprimir cada carácter con los colores correctos.
Establecer un atributo de color
El atributo de color en este archivo de arte ASCII define el color de fondo y de primer plano en un solo byte, representado por valores hexadecimales como 0x08
o 0x6E
. El hexadecimal resulta ser una forma compacta de expresar un "par" de colores como este.
Los sistemas de modo de caracteres como ncurses en Linux o conio en DOS pueden mostrar solo dieciséis colores. Son dieciséis posibles colores de texto y ocho colores de fondo. Contar dieciséis valores (de 0 a 15) en binario requiere solo cuatro bits:
1111
es 16 en binario
Y convenientemente, el hexadecimal puede representar del 0 al 15 con un solo carácter:0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E y F. Entonces, el valor F
en hexadecimal es el número 15, o 1111
en binario.
Con los pares de colores, puede codificar los colores de fondo y de primer plano en un solo byte de ocho bits. Son cuatro bits para el color del texto (0 a 15 o 0 a F en hexadecimal) y tres bits para el color de fondo (0 a 7 o 0 a E en hexadecimal). El bit restante en el byte no se usa aquí, por lo que podemos ignorarlo.
Para convertir el par de colores o el atributo en valores de color que su programa pueda usar, necesitará usar una máscara de bits para especificar solo los bits usados para el color del texto o el color de fondo. Con el Compilador OpenWatcom C en FreeDOS, puede escribir esta función para establecer los colores de forma adecuada desde el atributo de color:
void
textattr(int newattr)
{
_settextcolor(newattr & 15); /* 0000xxxx */
_setbkcolor((newattr >> 4) & 7); /* 0xxx0000 */
}
El _settextcolor
establece solo el color del texto y el _setbkcolor
La función establece el color de fondo. Ambos están definidos en graph.h
. Tenga en cuenta que debido a que el atributo de color incluía tanto el color de fondo como el color de primer plano en un solo valor de byte, el textattr
la función usa &
(Y binario) para establecer una máscara de bits que aísle solo los últimos cuatro bits del atributo. Ahí es donde el par de colores almacena los valores del 0 al 15 para el color de primer plano.
Para obtener el color de fondo, la función primero realiza un cambio de bits para "empujar" los bits hacia la derecha. Esto coloca los bits "superiores" en el rango de bits "inferior", por lo que cualquier bit como 0xxx0000
convertirse en 00000xxx
en cambio. Podemos usar otra máscara de bits con 7 (binary 0111
) para seleccionar el valor del color de fondo.
Mostrar arte ASCII
Los IMAGEDATA
La matriz contiene toda la pantalla de arte ASCII y los valores de color para cada carácter. Para mostrar el arte ASCII en la pantalla, su programa necesita escanear la matriz, establecer el atributo de color y luego mostrar la pantalla un carácter a la vez.
Dejemos espacio en la parte inferior de la pantalla para un mensaje o mensaje separado para el usuario. Eso significa que en lugar de mostrar las 25 líneas de una pantalla ASCII de 80 columnas, solo quiero mostrar las primeras 24 líneas.
/* print one line less than the 80x25 that's in there:
80 x 24 x 2 = 3840 */
for (pos = 0; pos < 3840; pos += 2) {
...
}
Dentro del for
loop, necesitamos configurar los colores, luego imprimir el carácter. El compilador OpenWatcom C proporciona una función _outtext
para mostrar texto con los valores de color actuales. Sin embargo, esto requiere pasar una cadena y sería ineficiente si necesitamos procesar cada carácter de uno en uno, en caso de que cada carácter en una línea requiera un color diferente.
En cambio, OpenWatcom tiene una función similar llamada _outmem
que le permite indicar cuántos caracteres mostrar. Para un carácter a la vez, podemos proporcionar un puntero a un valor de carácter en IMAGEDATA
array y decirle a _outtext
para mostrar un solo carácter. Eso mostrará el carácter usando los atributos de color actuales, que es lo que necesitamos.
for (pos = 0; pos < 3840; pos += 2) {
ch = &IMAGEDATA[pos]; /* pointer assignment */
attr = IMAGEDATA[pos + 1];
textattr(attr);
_outmem(ch, 1);
}
Este for
bucle establece el carácter ch
asignando un puntero a IMAGEDATA
formación. A continuación, el bucle establece los atributos de texto y luego muestra el carácter con _outmem
.
Poniéndolo todo junto
Con el textattr
función y el for
bucle para procesar la matriz, podemos escribir un programa completo para mostrar el contenido de un archivo de arte ASCII. Para este ejemplo, guarde el arte ASCII como imgdata.inc
e incluirlo en el archivo fuente con un #include
declaración.
#include <stdio.h>
#include <conio.h>
#include <graph.h>
#include "imgdata.inc"
void
textattr(int newattr)
{
_settextcolor(newattr & 15); /* 0000xxxx */
_setbkcolor((newattr >> 4) & 7); /* 0xxx0000 */
}
int
main()
{
char *ch;
int attr;
int pos;
if (_setvideomode(_TEXTC80) == 0) {
fputs("Error setting video mode", stderr);
return 1;
}
/* draw the array */
_settextposition(1, 1); /* top left */
/* print one line less than the 80x25 that's in there:
80 x 24 x 2 = 3840 */
for (pos = 0; pos < 3840; pos += 2) {
ch = &IMAGEDATA[pos]; /* pointer assignment */
attr = IMAGEDATA[pos + 1];
textattr(attr);
_outmem(ch, 1);
}
/* done */
_settextposition(25, 1); /* bottom left */
textattr(0x0f);
_outtext("Press any key to quit");
getch();
textattr(0x00);
return 0;
}
Compile el programa utilizando OpenWatcom C Compiler en FreeDOS y obtendrá un nuevo programa que muestra este mensaje de vacaciones:
¡Feliz Halloween a todos!
Descargue el archivo de código INC aquí.
Descargue el archivo de código C aquí.