программирование

Brainf★ck в highlight.js

Я как-то писал, что ко Дню программиста сделал подсветку синтаксиса языка Brainfuck для библиотеки highlight.js.

Оказывается, я пропустил выход версии 7.3, куда вошла моя подсветка, теперь Brainfuck входит в список поддерживаемых языков.

6 комментариев

Как сохранять историю Skype

Мне сильно не нравится, когда собеседник удаляет в «Скайпе» свои сообщения. Бывает, что я их не успеваю прочитать, это печально. Я подумал, что было бы неплохо научиться их куда-то логировать, попробовал несколько модулей для «Пайтона», все они на «Маке» падают.

К счастью, «Скайп» хранит свою историю в SQLite, а там, как оказалось, есть триггеры. В общем, простой способ сохранять историю — создать ещё одну таблицу и триггер, который будет висеть на операции INSERT и копировать все новые сообщения в нашу таблицу:

CREATE TABLE Messages_backup (timestamp int, author text, body_xml text); -- таблица, где будут храниться сообщения

-- А вот и наш триггер, причём посмотрите, после WHEN у меня идёт условие, я сохраняю только сообщения
-- от пользователя megadestroyer, это условие можно убрать (вместе с WHEN)
-- или написать туда через OR несколько логинов  
CREATE TRIGGER Messages_insert INSERT ON Messages WHEN new.author='megadestroyer'
  BEGIN
    INSERT INTO Messages_backup VALUES(new.timestamp, new.author, new.body_xml);
  END;

Создать таблицу и тригер очень просто, база SQLite — это просто файл (вам нужен файл «main.db»), который лежит где-то у вас на диске (можно в интренете поискать, гуглится элементарно), у меня на «Маке» он лежит в папке «~/Library/Application Support/Skype/bolknote.#». Его надо открыть утилитой sqlite3 (на «Маке» она уже есть) и выполнить эти команды.

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

select * from Messages_backup;

и видеть весь лог сообщений, включая удалённые пользователем.

30 комментариев

Sleepsort

Из «Хабра» узнал про алгоритм sleepsort. Он больше забавный, чем практичный, я переписал его на баш:

while [ -n "$1" ]; do
    ( sleep "${1/%[0-9]/}.${1:(-1)}" ; echo "$1" ) &
    shift
done
wait
echo

Смысл в том, что запускается несколько параллельных процессов, по числу сортируемых значений, с паузой кратного значению размера. Вывод каждого из процессов происходит после истечения паузы, поэтому значения появляются в уже отсортированном виде:

$ bash sleepsort 1 2 7 10 3

1
2
3
7
10

4 комментария

Firefox 16 CSS hack

.selector, _:-moz-meter-optimum {
    background: red;
}

ЦСС-хак для Файрфокса 16, который выйдет сегодня вечером. Вместо «.selector» надо поставить нужный вам селектор.

2 комментария

int(?) в MySQL

Кто уверен, что точно знает что означает тип «int(11)» в MySQL? Я именно «интами» не пользовался никогда, всегда заводил через tinyint и т. п., поэтому, глядя на то СУБД в эти скобочки сама подставляет какие-то значения, был уверен, что это размер в каких-то попугаях. Руки не доходили проверить в каких.

Оказывается, это размер да не тот:

int(i) i — это не ограничение разрядности, int всегда одинаков -2³¹ до +2³¹-1 (или 0 до 2³²-1), а ограничение количества показываемых символов при отображении столбца, его значение от 1 до 255. Например, INT(5) объявляет столбец целого типа который при отображении будет выводиться в колонках по пять цифр.

Если в столбце реально записано значение которое нельзя отобразить 5-тью цифрами то оно будет отображено большим количеством символов, т. е. при выводе значение не усекается.

Так что будете заводить в следующий раз таблицу в MySQL, где идут подряд пять целых чисел, задайте им размерности 72, 101, 108, 108 и 111. Получится по кодам «Hello» в кодировке ASCII. Кто за вами потом разгадает, получит удовольствие.

4 комментария

Highlight.js+Brainfuck

brainfuck (12.90КиБ)

Ура! Иван Сагалаев, автор прекрасной библиотеки для подсветки синтаксиса кода highlight.js (которую я использую на своём сайте), принял мой патч, приуроченный ко Дню программиста, для расцветки кода на языке Brainfuck. Радость!

7 комментариев

Интерактив и CSS

Я считаю, что с появлением анимации в CSS, интерактивность, достигаемая без использования JavaScript вышла на новый уровень. После экспериментов с вложенными повернутыми структурами, мне стало интересно посмотреть как выглядит анимация таких структур, хороши они тем, что там надо анимировать всего один стиль, а структура сама будет выделывать всякие дикие штуки.

Например, если анимировать градус поворота, то получится забавный червяк, закреплённый с одного конца. Легко можно сделать, чтобы он ползал и извивался буквой «S», если бы целую кучу префиксов не приходилось писать.

Червяк (8.38КиБ)

Но самое потрясающее — возможность добавлять интерактив, жаль только возможности браузеров в этом пока очень ограничены. Попробуйте поводить курсором мыши по червяку и закон его движения изменится, причём совершенно без JavaScript! Изменится случайным порядком — всё зависит от того как вы проведёте мышкой.

Устройство простое (если убрать лишнее):

@keyframes wag {
    50% {
         transform: rotate(10deg);
    }
}

сегментхвоста {
       /* остальные стили */
        transform: rotate(-10deg);
        animation-name: wag;
        animation-duration: 3s;
        animation-iteration-count: infinite;
        animation-timing-function: ease-in-out;
}

сегментхвоста:hover {
        animation-name: none; /* отключаем анимацию, если навели мышкой */
}

На наведение мышкой анимация отключается, от начала червяка до места наведения (теги-то вложенные) причём остальные сегменты всё ещё анимируются. Если убрать мышку, то анимация начинается с начала, поэтому, поводив мышкой, можно заставить червяка причудливо извиваться — анимация разных сегментов будет стартовать в разные моменты времени!

17 комментариев

Шрифт на чистом CSS

Десять лет назад я пытался решить проблему отсутствия у пользователей татарского шрифта (с Юникодом тогда было плохо, да и татарский туда не входил по-моему) через CSS — комбинируя стилем буквы со знаками препинания, чтобы получить татарские «җ», «ө», «ң» и так далее. Т. е. я брал «ж» и запятую, сдвигал их относительно друг друга и получал «җ».

Мощность компьютеров и возможности браузеров тогда были таковы, что такой HTML выводился буквально по слогам — компьютер нагружался сильно.

Сейчас такой проблемы нет, зато мощность компьютеров и браузеров возросли многократно. Я попробовал для интереса создать шрифт на чистом ЦСС. Там где можно пользовался только стилем бордюра, где нельзя — использовал CSS-transformation.

CSS-шрифт (18.88КиБ)

Правда я сделал ошибку — сначала создал все самые простые буквы, а потом уже начал делать сложные. Ближе к концу я начал терять интерес к происходящему и на некоторых буквах уже халтурил — некоторые из них отличаются по размеру.

Слова пишутся внутри тега TEXT, буквы повешены на однобуквенные теги, им соответствующие. Для наглядности, вот код, который напишет HELLO с моим стилем CSS:

<text><h></h><e></e><l></l><l></l><o></o></text>

Цифр я изготовил всего две, они на тегах D1 и D8 (т. е. работают только однёрка и восьмёрка), кроме всего есть два знака препинания — точка (на теге DOT) и запятая (COMMA).

Из-за использования трансформаций, часть букв будет работать только в определённых версиях браузеров: ФФ 3.5+, ИЕ 9+, Опере 10.5, Сафари 3.1. По поводу «Хрома» ничего сказать не могу, когда он начал поддерживать трансформации мне неизвестно.

Обратите внимание, кстати, что в ИЕ можно такой шрифт создать уже с версии 5.5 — там есть фильтр matrix, при помощи которого можно эмулировать всё, что я использовал.

В ужатом состоянии (через оптимизатор CSSO) шрифт занимает всего 3,8КБ.

9 комментариев

Вложено и повёрнуто

Вложено и повёрнуто (85.42КиБ)

С тех пор как в браузерах появилась возможность свободно вращать любые объекты, мне нравится смотреть что из этого можно сделать, причём нравится экспериментировать с одинаковыми многократно вложенными объектами.

Т. е. поворот в CSS я задаю на один и тот же градус, но поскольку объекты вложены друг в друга, родительский угол тоже учитывается и получаются разнообразные кольца с регулярным рисунком. Если подключить к этому графику (тот же SVG), то всякие рождественские венки и прочие кольца со сложными, но повторяющимся рисунком, можно делать очень естественными образом.

Кстати, а если наложить несколько изображений с разным шагом и z-index, вообще страшно подумать какие рисунки можно выводить!

15 комментариев

Побочный эффект оператора «delete» в JavaScript

Как говорится «век живи, век учись, дураком помрёшь»:

Объяснение (по крайней мере для Хрома) очень простое: когда вы делаете delete testedObject[i].obj, V8 нормализует объект testedObject[i] — трансформирует его из быстрого компактного представления в медленное и раздутое представление на основе словаря, который еще и выделяется с запасом по размеру. При этом V8 не замечает, что после удаления в словаре будет пусто — и словарь (800 байтов) остается болтаться в воздухе. И так для каждого из ваших объектов.

Из коментария к статье на «Хабре», которая описывает странный эффект — при использовании оператора delete что-то продолжает занимать память.

2 комментария

ICC-профили в GIF

Формат ГИФ почему-то окружён каким-то нереальным количеством мифов, хотя до недавнего времени он был очень популярен, а для анимации до сих пор остаётся единственным универсальным форматом.

Например, считается, что анимация появилась только в версии 89a (неправда, она была уже в версии 87a, в 89а её возможности были расширены), что ГИФ может использовать не более 256 цветов (не совсем так — не более 256 цветов на кадр, кадры могут накладываться друг на друга, давая любое отображаемое компьютером количество цветов).

Другое распространённое заблуждение — что ГИФ не поддерживает цветовые профили (ICC).

В самом деле, если посмотреть спецификацию формата, то слово «ICC» там не найдётся, но не найдётся там и слова «loop» (здесь: количество повторов), тем не менее, вы видели анимации, где указано определённое количество повторений и браузеры как-то это понимают.

Дело в том, что формат ГИФ поддерживает расширения. Расширения в спецификацию формата не входят.

Упомянутое количество повторов анимации задаётся в расширении, которое было когда-то предложено фирмой «Нетскейп» и потому имеет заголовок «NETSCAPE2.0», у расширения, которое содержит цветовой профиль заголовок другой — «ICCRGBG1012». ГИФ всегда разбит на блоки, и блок расширения (любого) помечен специальным флагом; заголовок расширения позволяет просмотрщику (в нашем случае — браузеру) решить с каким из расширений формата он имеет дело.

Вот начало файла ГИФ с внедрённым профилем:

00000000 47 49 46 38 39 61 01 00 01 00 f0 00 00 fe 00 02 |GIF89a……….|
00000010 00 00 00 21 f9 04 00 00 00 00 00 21 ff 0b 49 43 |…!…….!..IC|
00000020 43 52 47 42 47 31 30 31 32 ff 00 00 03 f0 55 43 |CRGBG1012…..UC|
00000030 43 4d 02 40 00 00 6d 6e 74 72 52 47 42 20 58 59 |CM.@..mntrRGB XY|

Пока не все браузеры умеют поддерживать цветовые профили ГИФ (как и профили любого другого формата), так ФФ не научился делать это до сих пор, а «Опера» научится это делать в новой версии 12.50.

Проверить поддерживает ли браузер цветовые профили можно и через Джаваскрипт. Принцип такой: я загружаю ГИФ-изображение 1×1 с цветовым профилем в тег CANVAS, потом проверяю цвет точки, он должен быть определённого цвета. Проверить поддерживает ли ваш браузер цветовой профиль четвёртой версии ГИФ можно у меня на сайте, в разделе «Храню».

7 комментариев

Opera 12.50 CSS hack

Ребята из «Оперы» уже трудятся над весьма интересной версией 12.50 и у меня уже готов ЦСС-хак для неё:

@media (-o-min-device-pixel-ratio: 1/100) {
    @media all {
         body {
            background: red; /* Opera 12.50+ */
        }
    }
}

И ещё вариант:

_:-o-prefocus:fullscreen, body {
    background: red; /* Opera 12.50+ */
}

Вместо body надо подставить нужный вам селектор.

11 комментариев

Удаляем расладку «U.S. English» из «Мака»

Артём Поликарпов написал рецепт как можно удалить из «Мака» раскладку «U.S. English». Она очень мешается и совершенно не нужна, если поставить великолепную раскладку Ильи Бирмана (кстати, если вы почему-то ей не пользуетесь, то вы делаете большую ошибку).

Но рецепт Артёма мне не нравится тем, что для его выполнения приходится иметь у себя редактор Xcode, который ещё и несколько гигабайт весит. Поэтому я, как водится, написал скрипт, который нужно выполнить из «Терминала» (после его выполнения придётся опять залогиниться в систему) и ненужной раскладки уже не будет.

Меню с опциями: «Russian – Ilya Birman Typography», «English – Ilya Birman Typography», «Показать имя источника ввода» и «Открыть настройки языка и текста...
Ничего ненужного

Какое счастье!

Проще всего скрипт запускать из «Терминала» вот так:

bash  <(curl -fsSkL raw.github.com/bolknote/shellgames/master/us_layout_remover.sh)

Чтобы вернуть всё обратно достаточно запустить программу ещё раз.

Добавлено позднее: удалению раскладки может мешать Punto Switcher.

59 комментариев

До чего техника дошла

Вастрик-бокс

До чего техника дошла! У меня друг экзамен сдавал, когда упомянул про наушник, куда одногрупники будут начитывать билет, я, как мне показалось резонно, сказал ему, что не прокатит — волосы-то у него короткие. Он мне показал как выглядят современные наушники для списывания.

Найдите на картинке сам излучатель. Я попозже в комментариях расскажу что где.

22 комментария

Способ повалить Safari 6.0

Случайно нашёл способ как повалить браузер «Сафари» шестой версии (под «Мак»), другие версии не пробовал — не у меня их. Падает от такого HTML-кода:

<style>
* {
   background: -webkit-image-set(url(BOLK!) 1x), url(BOOM!)
}
</style>

3 комментария

Google Go GD binding

Исправил свой биндинг графической библиотеки GD к языку «Гоу» так, чтобы он работал под первой версией языка. Теперь изменился способ его установки и использования.

Ставить его теперь намного проще, достаточно выполнить следующую команду (в системе должна быть установлена библиотека GD):

go get github.com/bolknote/go-gd

Способ подключения бибилиотеки так же изменился (см. sample.go):

import gd "github.com/bolknote/go-gd"

Надеюсь, больше «Гугл» библиотеки языка и способ сборки менять не будет.

Добавлено позднее: заодно портировал на Go 1 и свою программу MakeCorner, ставиться, опять же, стала попроще, а вот размер сильно вырос. Версия r60 компилировала файл размером 1,6МБ, версия 1 компилирует уже в 2,2МБ. Безобразие!

Оставить комментарий

WEBP в PHP

WEBP (31.41КиБ)

Когда я делал биндинг GD для языка «Гугл Гоу», заметил, что в ПХП появилась поддержка формата WEBP. О самом формате как-нибудь в другой раз (пока можно почитать «Википедию»), скажу только, что многообещающий формат картинок для веба, который в настоящий момент поддерживается «Хромом» и «Оперой» (а в ФФ можно дёшево добавить поддержку через Джаваскрипт).

Чтобы поддержка формата (пока довольно куцая) появилась, нужно установить библиотеку libvpx и пересобрать ПХП с ключом —with-vpx-dir. У меня на «Маке» это выглядит так:

./configure --with-vpx-dir=/usr/local/Cellar/libvpx/1.1.0 \
… остальные опции
make
sudo make install

Правда в phpinfo информация как у меня на картинке не появится (это я сам немного пропатчил исходники), не пугайтесь — так должно быть, проверить наличие поддержки WEBP можно следующим образом:

var_dump(function_exists('imagewebp'));

Собственно, в языке появятся две новые функции: imagecreatefromwebp и imagewebp. У первой только одни аргумент — имя файла из которого надо создать ресурс GD (по действию ничем не отличается от любой другой подобной функции, например imagecreatefromjpeg), вторая принимает два параметра — ресурс и необязательные имя файла и качество, описание функции полностью совпадает с imagejpeg, с той только разницей, что сохраняет она формат WEBP.

Параметр качества изменяется от 0 до 100 и соотвествует параметру VP8 QP кодека в диапазоне от 1 до 63.

15 комментариев

Сжатие GIF через gzip

Эксперимент мой сжатию несжатых ГИФ, по сути, провалился — если статические изображения иногда оказываются меньше (или сравнимы) с PNG, то с анимированными изображениями, ради которых всё и затевалось, всё плохо, я не сумел подобрать условия, при которых новоявленный метод обгоняет обычные соптимизированные ГИФы.

Зато я попутно выяснил, что ГИФ, вопреки моим ожиданиям, иногда жмётся gzip, на первой попавшейся анимации я получил выигрыш порядка 9%. Так что вот он метод ещё больше утоптать файлы ГИФ:

#!/bin/sh

which -s defluff
if [ $? -eq 0 ]; then
    gifsicle -O3 "$1" |  gzip -9nc | defluff 2>&- > "$2".temp
else
    gifsicle -O3 "$1" |  gzip -9nc > "$2".temp
fi

size=( $(ls -l "$2".temp) )

# срезаем заголовок gzip и контрольную сумму
let 'size=size[4]-10-8'

dd if="$2".temp of="$2" bs=1 skip=10 count=$size 2>&-
rm -f "$2".temp

В настройки Апача надо добавить новое расширение файла:

AddEncoding deflate .gif-def
AddType image/gif .gif-def

Для браузера вместо gzip я указываю метод deflate — по факту это тот же gzip, но без заголовка и контрольной суммы, что позволяет сэкономить 18 байт, не бог весть сколько, конечно, но почему бы их не убрать, спрашивается.

Утилита defluff , которая у меня упоминается — это оптимизатор кодов Хаффмана для gzip, PNG и zip, иногда даёт выигрыш в размере.

25 комментариев

Конвертор в несжатый GIF

Сделал я конвертор из обычного ГИФа в несжатый формат сжатый gzip, выложил на ГитХабе. Основное (разбор ГИФа) написано на Пайтоне, утилита, которая всё запускает — на Шеле. Для работы требуются ImageMagick (предпочтительнее) или gifsicle, gitinter (из libungif) и интерпретатор Пайтона.

Кажется, эксперимент провалился, я ещё буду вертеть различные ГИФы, но вряд ли что-то получится. По сравнению с анимированными ГИФами, где не используется оптимизация (не убираюся из следующих кадров статические куски, не используется фокусы с прозрачностью и наложением) выигрыш бывает, но по сравнению с оптимизированными, ещё не видел, чтобы испытываемый формат выигрывал.

Из плюсов для себя: детально для себя разобрал формат GIF, освежил знания Пайтона (которые уже начинают тускнеть), Шела, поработал над интересной идеей.

11 комментариев

Сжатый несжатый GIF

Как многие знают, браузер нативно понимает сжатие gzip (алгоритм DEFLATE). Наконец-то браузеры научились с ним правильно работать, после стольких лет мучений — сжимать можно что угодно, достаточно просто указать правильный заголовок.

Графический файлы обычно так не сжимают — внутри у них свой алгоритм сжатия, например в ПНГ используется тот же DEFLATE. Но с ГИФом ситуация хуже — у него внутри более старый алгоритм LZW, к тому же нет никаких оптимизационных техник (например, ПНГ использует так называемые «фильтры», которые позволяют эффективно сжимать градиенты.

Вот я и подумал — нельзя ли как-то заменить алгоримт сжатия ГИФа с внутреннего LZW на внешний gzip? Если было бы нельзя, я бы эту заметку не писал.

Смотрите, слева у вас на экране ГИФ, сжатый при помощи gzip (так и грузится с сервера), справа — ПНГ.

Пиксельная снежинка с розовыми, оранжевыми и бирюзовыми лучами

Пиксельный узор в виде цветка с розовыми, оранжевыми и бирюзовыми лепестками на белом фоне.


В каждом из них равное количество уникальных цветов, ПНГ пропущен через все оптимизаторы, которые я только нашёл. При этом ПНГ занимает 1374 байта, а гзипованный ГИФ — 1347, на 27 байт меньше. Дело тут конечно, не в паре десятков байт, а в принципе — если бы я выбрал картинку побольше, выигрыш, возможно, был бы существеннее.

Почему же LZW внутри ГИФа, плюс DEFLATE снаружи сделали файл меньше, чем оптимизирующие просто DEFLATE, плюс фильтры в случае ПНГ? Обычно наложение одного сжимающего алгоритма на другой делает файл больше сравнению с применением одного, более удачного алгоритам из двоих.

Дело в том, что в ГИФ я использовал несжатый, он подготовлен специальным образом, так, что его собственный алгоритм сжатия не работает, а gzip работает над несжатым потоком данных.

Самый простой, по моему мнению, способ получить такой файл — пропустить его через утилиту gifinter из набора libungif — библиотеки и набора утилит для работы с несжатыми файлами ГИФ.

Утилиты эти отлично скомпилировались под мой «Мак» и обрабатывал я ГИФ следующим образом: для начала оптимизировал его при помощи giflite (эта старая утилита под DOS, которую я запускаю из-под dosbox, творит с ГИФами чудеса), потом пропустил через утилиту, вырезающую из ГИФа комментарии (их туда вставил giflite), только после этого пропустил файл через gifinter и сжал при помощи gzip:

gifinter optimized.gif > non-compressed.gif
gzip -9n non-compressed.gif

Дальше я переименовал файл в 2012.08.08.gif-gz и добавил в конфигурацию своего «Апача» следующие строки:

AddEncoding gzip .gif-gz
AddType image/gif .gif-gz

Теперь при запросе сервер будет выдавать все необходимые заголовки:

bolk@Bolk ~  $ telnet bolknote.ru 80
Trying 91.230.61.15...
Connected to bolknote.ru.
Escape character is '^]'.
HEAD /imgs/2012.08.08.gif-gz HTTP/1.0
Host: bolknote.ru
Accept-encoding: gzip

HTTP/1.1 200 OK
Server: nginx
Date: Wed, 08 Aug 2012 06:12:14 GMT
Content-Type: image/gif
Content-Length: 1347
Connection: close
Accept-Ranges: bytes
Cache-Control: max-age=2592000
Expires: Fri, 07 Sep 2012 06:12:14 GMT
Content-Encoding: gzip

Если интересно как устроен несжатый ГИФ, об этом можно прочитать в Википедии, откуда я взял картинку, там интересная уличная магия, перепечатывать «Википедию» не очень-то интересно.

Готовой разгадки почему сжатый несжатый ГИФ обогнал ПНГ у меня нет, но есть одно возможное соображение — ГИФ чуть-чуть компактнее ПНГ, кроме того, ГИФ сжат целиком, тогда как в ПНГ сжата только картинка. Если моё предположение правда, то хорошего выигрыша ждать не сто́ит, но списывать формат ГИФ со счетов тоже не нужно.

По-настоящему опыт ценен, если удасться сделать несжатую ГИФ-анимацию (этого я ещё не пробовал) и сжать её при помощи gzip. Если удасться, это будет очень полезно, буду держать вас в курсе.

14 комментариев

← 1 33 34 35 36 37 67 →