Это сайт — моя персональная записная книжка. Интересна мне, по большей части, история, своя жизнь и немного программирование.

ASCII art vs. Unicode art

С приходом цветного Юникода некоторые символы могут присутствовать в системе в так называемом «стиле эмодзи», проще говоря в цвете.

«Мак» уже пару версий назад начал их показывать, я слышал, что и Винзоуз тоже что-то из этого набора показывает. Правда, мне непонятно насколько рисунки совпадают на разных операционных системах, думаю не совпадают, стандарт, как я понимаю, задаёт лишь смысл, цветовой исполнение и прорисовка уже на усмотрение автора шрифта.

Как бы там ни было, я решил попробовать, что будет, если уменьшить доступные цветные символы до одного пискеля (чтобы остался только преобладающий цвет) и порисовать таким образом картинки в браузере. Получился бы такой Юникод-арт.

Забегая вперёд, картинка того что вышло из этой затеи — ниже. Cправа — исходник картинки, слева — Юникод, то есть, каждый пиксель этой картинки — один цветной символ Юникода, написанный (или тут надо уже говорить «нарисованный») шрифтом размером 1px.

Что получилось (14.70КиБ)

Для начала я выяснил, что единственный браузер на «Маке», который показывает эти символы в цвете, это «Сафари», остальные показывают в лучшем случае в ч/б («Файрфокс», «Хром»), в худшем показывают какие-то обрывки («Опера»).

Дальше я собрал доступные цветные символы и вывел их в Сафари с размером шрифта в один пиксель и шагом в пять. Шаг нужен, чтобы символы не влияли друг на друга — разводы антиалиасинга выходят за контейнер с буквой и портят соседние символы. Получилась такая картинка:

Карта цветов (11.91КиБ)

На «баше» (ну да, я извращенец, но так просто быстрее было) накидал небольшую программу, который из этой картинки генерирует текстовый файл, состоящий из номера символа по порядку и значения цвета в формате #rrggbb:

#!/bin/bash
FILE='color-map.png'

wh=(`file $FILE | grep -oE '\S+ x [0-9]+'`)

function ColorAt {
    convert $1[1x1+$2+$3] txt: | grep -oE '#[0-9A-F]{6}'
}

for (( y=0; y<${wh[2]}; y+=5 )); do
    for (( x=0; x<${wh[0]}; x+=5 )); do
        pos=$(( $x/5 + $y*${wh[0]}/25 ))

        echo "$pos $(ColorAt $FILE $x $y)"
    done
done

Утилита convert, которая используется в скрипте, это часть пакета ImageMagick.

Дальше всё просто, проходим попиксельно по картинке и берём самый близкий цвет, который у нас только есть (формула простая — минимум суммы разностей каждого компонента цвета: красной, зелёной и синей), эту часть я писал на ПХП. Что-то такое выходит:

$cached = [];

for ($y = 0; $y<$h; $y++) {
    for ($x = 0; $x<$w; $x++) {
        $cnum = imagecolorat($im, $x, $y);

        if (isset($cached[$cnum])) {
            $outchar = $cached[$cnum];
        } else {
            $mindiff = $outchar = INF;

            $c = imagecolorsforindex($im, $cnum);
            foreach ($colors as $colorandch) {
                list($ch, $r, $g, $b, $ch) = $colorandch;

                $diff = abs($r - $c['red']) + abs($g - $c['green']) + abs($b - $c['blue']);

                if ($diff < $mindiff) {
                    $mindiff = $diff;
                    $outchar = $ch;
                }
            }
            $cached[$cnum] = $outchar;
        }
        echo '<b>', $outchar, '</b>';
    }
}

Я тут ещё кеширую уже найденные цвета, всё-таки три вложенных цикла, медленно получается, кеширование позволяет уменьшить время выполнения на треть на моей картинке. Кстати, каждый символ в результате я вывожу «болдом», так насыщеннее получается.

Если читателям интересно будет, выложу весь пакет. Правда, практического применения, видимо, никакого, мне интересно было сделать и помотреть хватит ли цветов для узнаваемости картинки.

7 комментариев
DuMOHsmol (anothersite.ru) 2013

Под Win7 нигде нормально не отображается, пробовал Firefox, Chrome, Opera, IE10.

Евгений Степанищев (bolknote.ru) 2013

Комментарий для anothersite.ru:

Насколько я сейчас почитал, требуется указать шрифт Segoe UI, попробуйте в каких браузерах у вас отобразится вот эта страница: http://www.istartedsomething.com/uploads/emojisegoe.html

DuMOHsmol (anothersite.ru) 2013

Символы видно во всех браузерах (большинство символов), но они не цветные. Похоже, что цвет в семёрке не поддерживается.

DuMOHsmol (anothersite.ru) 2013

Еще заметил, что Firefox неправильно определяет кодировку.

Евгений Степанищев (bolknote.ru) 2013

Кстати, если забить на все браузеры, кроме Сафари, можно выкинуть теги вокруг каждого символа, расставить <br>, сделать letter-spacing: -1px, подобрать transform: scaleX и облегчить файл на порядок.

artemp.pip.verisignlabs.com 2013

Поначалу не мог понять почему у меня в сафари картинка выглядит иначе. Оказалось дело в настройке Дополнения->Размер шрифта всегда не менее.

DuMOHsmol (anothersite.ru) 2013

Вспомнил, где уже давным-давно были цветные иконки, в браузерах сименсов. Только там были не символы, а картинки вида <img localsrc=«162»/>

http://img-fotki.yandex.ru/get/6446/26905228.0/0_ab26c_87fa587e_L#test.png%7Chttp%3A%2F%2Ffotki.yandex.ru%2Fusers%2Fdumohsmol%2Fview%2F701036%3Fpage%3D0#196x442