Рисование азбукой Брайля
Если помните, недавно я, вдохновлённый строчкой из песни «в каждой строчке — только точки», пытался выяснить что вообще можно записать точками, если использовать азбуку Морзе. Мне тогда один из комментаторов напомнил про шрифт Брайля — тактильный шрифт для слепых, состоящий из точек.
Он есть в Юникоде, поэтому на экране им можно написать что угодно и, как и требуется в песне, там будут только точки. Я тогда подумал, что «что угодно» можно трактовать и шире — если постараться, точками этого шрифта можно выводить в консоли любую графику.
Сегодня, как это что-то часто за мной водится в последнее время, мне не спалось и хотелось не просто бездумно лежать, глядя в потолок, а найти себе какой-нибудь занятие. Вот я и вспомнил про эту идею. Оказалось, кстати, что я не один до неё додумался и библиотек, которые таким образом что-то выводят в консоль очень много.
Шрифт Брайля бывает двух систем — шеститочечный и восьмиточечный. Для целей рисования удобнее брать восьмиточечный — между символами есть зазоры, как если бы это были обычные буквы, и нам выгоднее использовать более насыщенный точками элемент.
Таким образом у нас получается блок 2×4, где мы, подбирая код символа, можем получить любое сочетание точек. Я боялся, что в расположении точек нет никакой системы, но к моему счастью оказалось, что каждая точка, которую надо закодировать, отображается на конкретный бит численного представления нужного символа.
Оставалось только решить, что я, собственно, буду выводить. Это должно быть что-то простое и одноцветное — набор из восьми точек можно покрасить только в один цвет, поэтому лучше цвета не использовать вообще. Поскольку в последнее время я много вожусь с браузером «Виола», где много однобитной графики в формате XBM, то я решил выводить картинки в этом формате — тем более, что он текстовый, что мне на руку.
Так, к примеру, выглядит картинка с логотипом «Виолы» в этом формате:
#define violaLogo_width 32
#define violaLogo_height 20
static char violaLogo_bits[] = {
0xe0, 0x03, 0x00, 0x00, 0x18, 0x0c, 0x0f, 0x00, 0xe4, 0x8b, 0x30, 0x00,
0xfa, 0x8f, 0x4f, 0x00, 0xfa, 0xff, 0xff, 0x00, 0xfd, 0xff, 0xff, 0x50,
0xfd, 0x2f, 0xe9, 0xff, 0xfd, 0x07, 0x00, 0x00, 0x7d, 0xfc, 0xff, 0x50,
0xbd, 0xfd, 0xff, 0x00, 0xba, 0x3b, 0x7f, 0x00, 0x3a, 0xdb, 0x1e, 0x00,
0x7c, 0xd7, 0x00, 0x01, 0x78, 0xd6, 0x06, 0x19, 0xe0, 0xce, 0x00, 0x25,
0x00, 0xcc, 0x32, 0x21, 0x00, 0xd8, 0x5a, 0x39, 0x00, 0xf0, 0x6a, 0x25,
0x00, 0x60, 0x32, 0x79, 0x00, 0x00, 0x00, 0x00};Алгоритм обещал получиться простым, поэтому для реализации я выбрал bash, тем более, что такую обработку там делать иногда даже проще, чем в большинстве других языков. Вот, например, вся функция чтения данных из файла картинки, получилось очень просто:
load_xbm() {
local file="$1" hex h
W=$(awk '/^#define.*_width/ {print $3;exit}' "$file")
H=$(awk '/^#define.*_height/{print $3;exit}' "$file")
BPR=$(( (W + 7) / 8 ))
for h in $(sed -n '/{/,/}/{/{/d;s/}.*//;s/0x//g;y/,/ /;p;}' "$file"); do
BYTES+=($[16#$h])
done
}Очень долго пришлось разбираться с битовыми сдвигами и порядком чтения точек из чисел, на это ушла просто прорва времени. Я пытался сделать это в уме, но не справился и перешёл на бумагу. Оказалось, что я не дошёл буквально полшага — надо было только изменить вывод точек на обратный.
В итоге получился небольшой скрипт, в котором, если убрать все пустые строки, около полусотни строчек. Я его выложил, как водится, на «Гитхаб».
Есть ли выигрыш по размеру?
Между чем и чем? Я не понял.
насколько UTF проигрывает XBM?
Он не проигрывает:
890 392 ./xbm/violaIcon.xbm
872 392 ./xbm/WWW.xbm
590 245 ./xbm/violaLogo.xbm
872 392 ./xbm/map.xbm
Первое — размер файла, второе — размер в Брайле