Suddenly I found a relevant library... I'm building wheels
Use Braille characters to draw black-and-white images on the terminal
Edible tips
If this article displays many boxes on your device, there may be a problem with the font. Please make sure that your font can display Braille normally.
On my device, no matter how I operate it, I can't make urxvt (rxvt, xterm) show what I want. Therefore, it is not recommended that you use urxvt (rxvt, xterm) when experimenting.
Source of ideas
One day I found that braille is a pile of pixels, so I wanted to draw pictures on the terminal with Braille.
Realization effect
analysis
⠀⠁⠂⠃⠄⠅⠆⠇⠈⠉⠊⠋⠌⠍⠎⠏ ⠐⠑⠒⠓⠔⠕⠖⠗⠘⠙⠚⠛⠜⠝⠞⠟ ⠠⠡⠢⠣⠤⠥⠦⠧⠨⠩⠪⠫⠬⠭⠮⠯ ⠰⠱⠲⠳⠴⠵⠶⠷⠸⠹⠺⠻⠼⠽⠾⠿ ⡀⡁⡂⡃⡄⡅⡆⡇⡈⡉⡊⡋⡌⡍⡎⡏ ⡐⡑⡒⡓⡔⡕⡖⡗⡘⡙⡚⡛⡜⡝⡞⡟ ⡠⡡⡢⡣⡤⡥⡦⡧⡨⡩⡪⡫⡬⡭⡮⡯ ⡰⡱⡲⡳⡴⡵⡶⡷⡸⡹⡺⡻⡼⡽⡾⡿ ⢀⢁⢂⢃⢄⢅⢆⢇⢈⢉⢊⢋⢌⢍⢎⢏ ⢐⢑⢒⢓⢔⢕⢖⢗⢘⢙⢚⢛⢜⢝⢞⢟ ⢠⢡⢢⢣⢤⢥⢦⢧⢨⢩⢪⢫⢬⢭⢮⢯ ⢰⢱⢲⢳⢴⢵⢶⢷⢸⢹⢺⢻⢼⢽⢾⢿ ⣀⣁⣂⣃⣄⣅⣆⣇⣈⣉⣊⣋⣌⣍⣎⣏ ⣐⣑⣒⣓⣔⣕⣖⣗⣘⣙⣚⣛⣜⣝⣞⣟ ⣠⣡⣢⣣⣤⣥⣦⣧⣨⣩⣪⣫⣬⣭⣮⣯ ⣰⣱⣲⣳⣴⣵⣶⣷⣸⣹⣺⣻⣼⣽⣾⣿
This is a Braille character in UTF-8. There are 256 in total. Each Braille character consists of several dots. The Braille character with the most dots (lower right corner) has 8 dots, which looks like a solid black frame; The Braille character with the least dots has 0 dots (upper left corner). Although it looks like a space, it is really not the same thing as a space.
A little observation shows that a Braille character can be used as a 4x2 small bitmap. If it can be well organized and arranged in a certain way, it can spell a larger bitmap.
There are 2 ^ 8 = 256 different 4x2 bitmaps, and 256 different Braille characters. This means that there is a one-to-one correspondence between Braille characters and 4x2 bitmaps. In order to facilitate the transformation between Braille and bitmap, we need to design a coding scheme.
The table listed above is obviously well organized, and it can be found that the arrangement of Braille characters is very regular. The process of finding rules is omitted. Here is only the coding scheme. After the following operations, it can be ensured that Braille characters and their corresponding 4x2 bitmap have the same number:
Braille: number the Braille in the above table from top to bottom and from left to right from 0 to 255.
Bitmap: consider making a weight table:
1 8 2 16 4 32 64 128
Add up the weights of all corresponding bitmap black positions in the table, and the sum is the number of bitmap.
For example, the character "⢫" is numbered 171 and its bitmap is:
1 1 1 0 0 1 0 1
And the weight table py, 1 + 8 + 2 + 32 + 128 = 171, which is consistent with the expected result.
Using this method, a 4x2 small bitmap can be mapped to the number of its corresponding Braille characters. So we can draw pictures at the terminal.
realization
First, make a table of Braille characters:
const char *magic_table[] = { "⠀", "⠁", "⠂", "⠃", "⠄", "⠅", "⠆", "⠇", "⠈", "⠉", "⠊", "⠋", "⠌", "⠍", "⠎", "⠏", "⠐", "⠑", "⠒", "⠓", "⠔", "⠕", "⠖", "⠗", "⠘", "⠙", "⠚", "⠛", "⠜", "⠝", "⠞", "⠟", "⠠", "⠡", "⠢", "⠣", "⠤", "⠥", "⠦", "⠧", "⠨", "⠩", "⠪", "⠫", "⠬", "⠭", "⠮", "⠯", "⠰", "⠱", "⠲", "⠳", "⠴", "⠵", "⠶", "⠷", "⠸", "⠹", "⠺", "⠻", "⠼", "⠽", "⠾", "⠿", "⡀", "⡁", "⡂", "⡃", "⡄", "⡅", "⡆", "⡇", "⡈", "⡉", "⡊", "⡋", "⡌", "⡍", "⡎", "⡏", "⡐", "⡑", "⡒", "⡓", "⡔", "⡕", "⡖", "⡗", "⡘", "⡙", "⡚", "⡛", "⡜", "⡝", "⡞", "⡟", "⡠", "⡡", "⡢", "⡣", "⡤", "⡥", "⡦", "⡧", "⡨", "⡩", "⡪", "⡫", "⡬", "⡭", "⡮", "⡯", "⡰", "⡱", "⡲", "⡳", "⡴", "⡵", "⡶", "⡷", "⡸", "⡹", "⡺", "⡻", "⡼", "⡽", "⡾", "⡿", "⢀", "⢁", "⢂", "⢃", "⢄", "⢅", "⢆", "⢇", "⢈", "⢉", "⢊", "⢋", "⢌", "⢍", "⢎", "⢏", "⢐", "⢑", "⢒", "⢓", "⢔", "⢕", "⢖", "⢗", "⢘", "⢙", "⢚", "⢛", "⢜", "⢝", "⢞", "⢟", "⢠", "⢡", "⢢", "⢣", "⢤", "⢥", "⢦", "⢧", "⢨", "⢩", "⢪", "⢫", "⢬", "⢭", "⢮", "⢯", "⢰", "⢱", "⢲", "⢳", "⢴", "⢵", "⢶", "⢷", "⢸", "⢹", "⢺", "⢻", "⢼", "⢽", "⢾", "⢿", "⣀", "⣁", "⣂", "⣃", "⣄", "⣅", "⣆", "⣇", "⣈", "⣉", "⣊", "⣋", "⣌", "⣍", "⣎", "⣏", "⣐", "⣑", "⣒", "⣓", "⣔", "⣕", "⣖", "⣗", "⣘", "⣙", "⣚", "⣛", "⣜", "⣝", "⣞", "⣟", "⣠", "⣡", "⣢", "⣣", "⣤", "⣥", "⣦", "⣧", "⣨", "⣩", "⣪", "⣫", "⣬", "⣭", "⣮", "⣯", "⣰", "⣱", "⣲", "⣳", "⣴", "⣵", "⣶", "⣷", "⣸", "⣹", "⣺", "⣻", "⣼", "⣽", "⣾", "⣿" };
Then implement the canvas structure. Here, the unsigned char array is used as a bool array. In future optimization, you can use bitmap to save space.
typedef struct canvas { int width; int height; void *buf; } canvas; int canvas_init(canvas *p, int width, int height) { width = ((width - 1) / 2 + 1) * 2; height = ((height - 1) / 4 + 1) * 4; p->width = width; p->height = height; p->buf = malloc(sizeof(unsigned char) * width * height); if (p->buf == NULL) return 1; return 0; } void canvas_clear(canvas p) { free(p.buf); }
Realize the functions of drawing pixels and printing:
void canvas_draw(canvas p, int x, int y) { ((unsigned char (*)[p.width])p.buf)[y][x] = 1; } void canvas_erase(canvas p, int x, int y) { ((unsigned char (*)[p.width])p.buf)[y][x] = 0; } int canvas_test(canvas p, int x, int y) { return ((unsigned char (*)[p.width])p.buf)[y][x]; } void canvas_print(canvas p) { int i, j, k, l; for (i = p.height; i > 0; i -= 4) { for (j = 0; j < p.width; j += 2) { int id = 0; for (l = 1; l >= 0; --l) for (k = 3; k >= 1; --k) id = (id << 1) | canvas_test(p, j + l, i - k); if (canvas_test(p, j, i - 4)) id += 64; if (canvas_test(p, j + 1, i - 4)) id += 128; printf("%s", magic_table[id]); } putchar('\n'); } }
The implementation is complete. The following is a description of function functions and parameters:
int canvas_init(canvas *p, int width, int height); take p Initialize to wide width high height Canvas of void canvas_clear(canvas p); Destroy canvas p void canvas_draw(canvas p, int x, int y); stay p of (x, y) Draw a pixel on the position void canvas_erase(canvas p, int x, int y); Erase p in (x, y) Pixels in position int canvas_test(canvas p, int x, int y); return p in (x, y) Has it been painted on the void canvas_print(canvas p); Print p
Achieve the effect in the example
Use the convert command of ImageMagick to convert the picture file into an xpm file with only two colors, write a fool xpm parser, and simply process it with the above code to get the effect in the example. For the code of fool parser, see: doxpm.c .
On this machine, the commands to realize the example effect are:
$ convert -colors 2 sample.png a.xpm $ gcc doxpm.c -o doxpm $ ./doxpm $ # If color is required: $ ./doxpm | lolcat
finish
The code is only used to illustrate ideas, not to write a usable library. So the code wind is slightly fast and rough. Please forgive me.
Thanks zrz_orz taught me to contribute to the Logue daily and put forward a lot of modification suggestions.