Понимаю, что все хотят большего и лучшего И чтобы бесплатно.
Однако, хотя я и учусь понемногу, моих познаний все еще недостаточно для разработки алгоритмов хинтинга и контроля за отсечкой.
"Деффекты растеризации" на самом деле таковыми не являются, причина "призрачных" выступов в следующем: разрешение глифа в SVG-шрифтах - 1000 на 1000 пикселей, и когда глиф растрируется в квадрат 12 на 12 пикселов, теряется очень много деталей. Если круг 1000 на 1000 пикселов растрировать в квадрат 1 на 1 пиксел или 2 на 2 пиксела, получится либо точка, либо полностью залитый цветом квадрат. Когда разрешение квадрата 3 на 3 пиксела, то круг может стать либо квадратом, либо ромбом. Продолжая размышлять по аналогии, можно понять, что на разрешениях значительно меньше "рассчетного" векторные изображения очень сильно искажаются.
Именно из-за этих искажений так трудно сделать хороший растеризатор. На принтере разрешение 300 или 600 dpi, и можно вывести в одном дюйме букву высотой в 600 пикселов - а значит, у нее будет очень много деталей, она будет гладкой и красивой. На мониторе разрешение 72, 96 или (в лучшем случае) 120 dpi - и значит, качество букв в 3*3 (то есть девять) раз ниже. Для сравнения - различия в качестве несглаженного и сглаженного субпикселями глифа - ровно в три раза. Причина в том, что горизонтальное разрешение сглаженного субпиксельно символа в три раза выше, чем у несглаженного.
Для вывода символов хорошего качества без сглаживания применяют две технологии: одна из них называется контролем за отсечкой, а другая - хинтингом.
Суть контроля за отсечкой следующая: при уменьшении символа может получиться так, что какая-то часть буквы (например, верхняя часть буквы о) будет иметь толщину менее одного пиксела. Обычный растеризатор в таком случае превратил бы букву о в подобие буквы u, но растеризатор с контролем за отсечкой не допускает разрывов, искусственно утолщая ширину штрихов (и внося искажения, разумеется). Этот метод непрост, но более-менее реализуем.
Другой, очень популярный метод, называется хинтингом. Технология патентованная, из-за нее много ругани когда-то было. Идея следующая: формат ttf - это байт-код для интерпретатора (да-да, ttf-растеризатор это интерпретатор байт-кода языка "программирования" TrueType), и в некоторых файлах ttf содержится код, изменяющий контур символа для того, чтобы буквы лучше читались при небольших разрешениях. Этот метод дает наилучшие результаты (обратите внимание на хвостик у Q в сообщении выше - у алгоритмов без хинтинга он явно искажен, что делает результаты FreeType и моего растеризатора почти одинаковыми). "Правильный" хинтинг невозможен без TTF шрифтов (да и во многих свободных шрифтах его просто нет), а поддержку TTF я в ближайшее время делать не намерен - во-первых, есть FreeType, а во-вторых, не такой уж это простой формат. Можно попробовать сделать "автоматический" хинтинг, как это делали ранние версии FreeType.
Посмотреть, что делает хинтинг с буквами, можно вот тут например: http://habrahabr.ru/blogs/typography/112401/
Кстати, толковые вещи написаны, но над ними для Колибри еще работать и работать. Согласен с XVilka, когда есть что-то работающее, то к нему можно что-то добавить, а когда ничего нет - то и не добавишь
P.S. Буду рад любой помощи, особенно в реализации хинтинга и контроля за отсечкой.
Алгоритмы заливки
Sorcerer
Ты молодец - продолжай работу. Брюзжание и ворчание были, есть и будут.
"Лучше уж никак, вместо как-нибудь" не является приемлемым выходом. В конечном счете это не монолитное ядро, а уровень приложений.
Ты молодец - продолжай работу. Брюзжание и ворчание были, есть и будут.
"Лучше уж никак, вместо как-нибудь" не является приемлемым выходом. В конечном счете это не монолитное ядро, а уровень приложений.
Я не о том. Конечно, лучше "как-нибудь" вместо "никак". Только не надо останавливаться на "как-нибудь". А ведь если все говорят "Молодец! Великое дело свершил, то человек легко поверит и пойдет делать чего нибудь интереснее.Mario wrote:Sorcerer"Лучше уж никак, вместо как-нибудь" не является приемлемым выходом.
Sorcerer, я не хочу "больше и лучше". Скорее всего мне нравиться "меньше и лучше". А ведь ты говориш "Не понимаю, моих познаний недостаточно...", а вот как прекрасно обьяснил все в подробностях.
В моей долгой и нелегкой програмисткой жизни, я убедился, что алгоритмы только кажутся сложными. Как только напишеш первые сто строки кода, и все пойдет само собой. Програмист, ето человек работающей всегда на грани своей компетентности.
Спасибо! Надеюсь, что не буду останавливаться на "как-нибудь" Хотя шрифты - это не единственное, чем я собираюсь в ближайшее время заняться.
Johnfound, я понимаю, как должен работать алгоритм, но не понимаю, как его сделать... И скромно надеюсь, что прилетит супермен и поможет мне
Тем временем, продолжаю оптимизацию алгоритмов по качеству и скорости. Начал работу над выводом строк, предстоит большая работа по поддержке шрифтов с различной шириной глифов.
После всех оптимизаций, показываю, как выглядит одинаковый текст, растрированный разными способами. Первый столбец - шрифт DroidSans высотой 12 пикселов. Простой алгоритм дает среднеотвратное качество, хотя буквы остаются читаемыми (разрешение глифа 12x12). Субпиксельное сглаживание дает хорошие, равномерно-широкие штрихи - с горизонтальной толщиной у них всё в порядке (потому что горизонтальное разрешение втрое больше вертикального: 36x12). Четырехоттеночное примитивное сглаживание дает размытость, но самые лучшие вертикальные штрихи именно у этого метода (разрешение глифа 24x24 пиксела). Пояснительный текст выполнен шрифтом Droid Sans 10px отдельно с помощью freetype, и можно убедиться, что "призрачные" выпирающие пиксели присутствуют.
Второй столбец - тот же шрифт высотой 10 пикселов. Из-за низкого вертикального разрешения произошли разрывы букв o и b при простой и субпиксельной растеризации. Примитивное четырехоттеночное сглаживание разрывов не дает (а я вам говорю, не было ни единого разрыва!11!1! ), но текст выглядит бледным и размазанным - вот к чему приводит отсутствие хинтинга. Кстати, сравните текст, растеризованный freetype с контролем отсечки, с текстом, растеризованным простым алгоритмом. Буквы о и b особенно. Freetype отбросил кучу деталей (скругления у o, скругления и ножку у b), которые все равно видно не будет, и - формально - исказил букву, однако тем самым повысил читаемость.
Третий столбец - тот же шрифт высотой 16 пикселов. Отрезанные края у o, b и "шляпы" у O и S - это не проблема растеризатора, это проблема алгоритма, определяющего ширину и высоту глифа Над этим я как раз сейчас работаю. Здесь результаты примерно одинаковые. Прошу обратить внимание на следующие детали:
* Точка у буквы i. Она на самом деле круглая. Простой алгоритм превращает ее в "запятую вверх ногами", субпиксельный - в ромбик, а антиалиасинговый - в "запятую в зеркальном отражении".
* Ножка у буквы b. Она действительно очень короткая и тонкая. У простого алгоритма она просто сливается с остальными деталями, у субпиксельного немного (совсем немного, на один субпиксель) отделяется по горизонтали, и лишь у антиалиасингового - различима (у него, как-никак, самое большое разрешение).
Я вот что сейчас подумал: алгоритм с антиалиасингом очень неплох по качеству. Его можно улучшить, добавив гамма-коррекцию. Сейчас я использую лишь 00, 40, 80 и FF, из-за этого буквы кажутся тусклыми. Если я буду использовать например 00, 70, B0 и FF, картинка должна стать немного получше. В идеале лучше добавить еще один метод сглаживания, более точный, с произвольным количеством оттенков (до 255). Держу пари, что при 255 оттенках результат будет не хуже, чем у FreeType 2 со сглаживанием, но без хинтинга.
Stay tuned на нашу волну Еще неделька-другая, и библиотеку можно будет использовать.
Интересует ваше мнение по следующим вопросам:
-Откуда брать настройки вывода шрифтов по умолчанию (со сглаживанием/без)?
-Как сделать так, чтобы для нескольких программ, использующих одно и то же начертание шрифта, не требовалось хранить в памяти несколько его копий? Shared memory?
-Как задавать имя шрифта? Вдруг программа захочет использовать шрифт Arial, а такого нет, зато есть Helvetica? Нужны будут, видимо, таблицы соответствия шрифтов?
p.s. SVG-шрифты состоят исключительно из SVG paths. Большая часть (99%) SVG-изображений состоит из SVG paths, SVG shapes и SVG filters. Фильтры обещать не могу (размытие и всё такое), но paths и shapes выводить попробую. Paths - это контуры (то есть линии и кривые Безье, залитые и нет), а shapes - это всего лишь круги, квадраты и звезды. Возможны проблемы с градиентной, текстурной заливкой и с штриховыми линиями, но добавлять новые алгоритмы заливки - это все же не придумывать программу с нуля. Не уверен, что простой алгоритм заливки, используемый в шрифтах, даст хотя бы приемлемую скорость одноцветной заливки, но попробовать стоит. Ожидается проблема с выводом полупрозрачных изображений. Мечтаю о функции, которая поддерживала бы вывод изображений с 32-битным цветом (AARRGGBB), такая пригодилась бы и для шрифтов. Или такая уже есть?
Johnfound, я понимаю, как должен работать алгоритм, но не понимаю, как его сделать... И скромно надеюсь, что прилетит супермен и поможет мне
Тем временем, продолжаю оптимизацию алгоритмов по качеству и скорости. Начал работу над выводом строк, предстоит большая работа по поддержке шрифтов с различной шириной глифов.
После всех оптимизаций, показываю, как выглядит одинаковый текст, растрированный разными способами. Первый столбец - шрифт DroidSans высотой 12 пикселов. Простой алгоритм дает среднеотвратное качество, хотя буквы остаются читаемыми (разрешение глифа 12x12). Субпиксельное сглаживание дает хорошие, равномерно-широкие штрихи - с горизонтальной толщиной у них всё в порядке (потому что горизонтальное разрешение втрое больше вертикального: 36x12). Четырехоттеночное примитивное сглаживание дает размытость, но самые лучшие вертикальные штрихи именно у этого метода (разрешение глифа 24x24 пиксела). Пояснительный текст выполнен шрифтом Droid Sans 10px отдельно с помощью freetype, и можно убедиться, что "призрачные" выпирающие пиксели присутствуют.
Второй столбец - тот же шрифт высотой 10 пикселов. Из-за низкого вертикального разрешения произошли разрывы букв o и b при простой и субпиксельной растеризации. Примитивное четырехоттеночное сглаживание разрывов не дает (а я вам говорю, не было ни единого разрыва!11!1! ), но текст выглядит бледным и размазанным - вот к чему приводит отсутствие хинтинга. Кстати, сравните текст, растеризованный freetype с контролем отсечки, с текстом, растеризованным простым алгоритмом. Буквы о и b особенно. Freetype отбросил кучу деталей (скругления у o, скругления и ножку у b), которые все равно видно не будет, и - формально - исказил букву, однако тем самым повысил читаемость.
Третий столбец - тот же шрифт высотой 16 пикселов. Отрезанные края у o, b и "шляпы" у O и S - это не проблема растеризатора, это проблема алгоритма, определяющего ширину и высоту глифа Над этим я как раз сейчас работаю. Здесь результаты примерно одинаковые. Прошу обратить внимание на следующие детали:
* Точка у буквы i. Она на самом деле круглая. Простой алгоритм превращает ее в "запятую вверх ногами", субпиксельный - в ромбик, а антиалиасинговый - в "запятую в зеркальном отражении".
* Ножка у буквы b. Она действительно очень короткая и тонкая. У простого алгоритма она просто сливается с остальными деталями, у субпиксельного немного (совсем немного, на один субпиксель) отделяется по горизонтали, и лишь у антиалиасингового - различима (у него, как-никак, самое большое разрешение).
Я вот что сейчас подумал: алгоритм с антиалиасингом очень неплох по качеству. Его можно улучшить, добавив гамма-коррекцию. Сейчас я использую лишь 00, 40, 80 и FF, из-за этого буквы кажутся тусклыми. Если я буду использовать например 00, 70, B0 и FF, картинка должна стать немного получше. В идеале лучше добавить еще один метод сглаживания, более точный, с произвольным количеством оттенков (до 255). Держу пари, что при 255 оттенках результат будет не хуже, чем у FreeType 2 со сглаживанием, но без хинтинга.
Stay tuned на нашу волну Еще неделька-другая, и библиотеку можно будет использовать.
Интересует ваше мнение по следующим вопросам:
-Откуда брать настройки вывода шрифтов по умолчанию (со сглаживанием/без)?
-Как сделать так, чтобы для нескольких программ, использующих одно и то же начертание шрифта, не требовалось хранить в памяти несколько его копий? Shared memory?
-Как задавать имя шрифта? Вдруг программа захочет использовать шрифт Arial, а такого нет, зато есть Helvetica? Нужны будут, видимо, таблицы соответствия шрифтов?
p.s. SVG-шрифты состоят исключительно из SVG paths. Большая часть (99%) SVG-изображений состоит из SVG paths, SVG shapes и SVG filters. Фильтры обещать не могу (размытие и всё такое), но paths и shapes выводить попробую. Paths - это контуры (то есть линии и кривые Безье, залитые и нет), а shapes - это всего лишь круги, квадраты и звезды. Возможны проблемы с градиентной, текстурной заливкой и с штриховыми линиями, но добавлять новые алгоритмы заливки - это все же не придумывать программу с нуля. Не уверен, что простой алгоритм заливки, используемый в шрифтах, даст хотя бы приемлемую скорость одноцветной заливки, но попробовать стоит. Ожидается проблема с выводом полупрозрачных изображений. Мечтаю о функции, которая поддерживала бы вывод изображений с 32-битным цветом (AARRGGBB), такая пригодилась бы и для шрифтов. Или такая уже есть?
Все данные настроек библиотеки хранить в INI файле. Они должны быть глобальными.
Если использовать расшареную память, есть смысл сделать сервер шрифтов, что-то типа fontconfig. Тогда приложение будет посылать IPC с описанием шрифта, а сервер возвращать имя расшареной области памяти со шрифтом. Всё это реализуется в dll. Сам сервер тоже можно держать в этой dll.
ОК, согласен.Mario wrote:Все данные настроек библиотеки хранить в INI файле. Они должны быть глобальными.
Какие страшные слова А обязательно в dll? Я конечно понимаю, что прогресс, будущее, и всё такое, но все же ядро (как я понимаю) PE пока не умеет, да и мнение людей по этому поводу неоднозначное. Или под dll имеются в виду и COFF-библиотеки тоже? Если так, то логично было бы сделать, чтобы и растеризация выполнялась на стороне "сервера", а "клиент" просто передавал "серверу" задание и получал бы изображение. Или правильнее сделать, чтобы библиотека еще и выводила в окно текст? Как будет быстрее? А как надежнее?Serge wrote:Если использовать расшареную память, есть смысл сделать сервер шрифтов, что-то типа fontconfig. Тогда приложение будет посылать IPC с описанием шрифта, а сервер возвращать имя расшареной области памяти со шрифтом. Всё это реализуется в dll. Сам сервер тоже можно держать в этой dll.
Может быть имеет смысл встроить один шрифт в библиотеку? На случай, если шрифтов не найдется.
Тем временем устранил ошибку в алгоритме растеризатора со сглаживанием. Причина тусклости букв - не в кривой гамме, а в кривых руках. Вместо 0х000000 использовался 0х333333. На глаз качество штрихов теперь приближается к субпиксельному сглаживанию, но при этом буквы значительно более четкие, смазанными для меня вообще не выглядят.
В планах - улучшение алгоритма анти-алиасинга и добавление возможности одновременного использования анти-алиасинга и субпиксельного сглаживания, что приведет к увеличению разрешения рендера в 12 раз по сравнению с простым растеризатором. Но он и работать будет медленнее его в 12 раз (правда, для небольших размеров шрифтов это мелочи).
Остужаю мозг, играюсь с выводом SVG paths. Немного тормознуто, криво с цветами, незамкнутыми контурами, и совсем туго со слоями и прозрачностью - но работает. Думаю, что это хорошая новость, которой стоит поделиться с сообществом
Печально, что творческая работа почти закночилась (вместе с идеями), и осталась одна рутина, без которой ничего не может быть, но которой так не хочется заниматься. Надеюсь, что буду уделять работе над шрифтами и (в перспективе) SVG не меньше времени, чем сейчас.
Печально, что творческая работа почти закночилась (вместе с идеями), и осталась одна рутина, без которой ничего не может быть, но которой так не хочется заниматься. Надеюсь, что буду уделять работе над шрифтами и (в перспективе) SVG не меньше времени, чем сейчас.
Sorcerer
Нет, я писал про COFF. Идея в том, чтобы спрятать и сервер и весь обмен библиотеки с сервером в одной DLL. В этом случае ты можешь как тебе угодно менять код и протоколы обмена с сервером и не заботиться о совместимости версий на этом уровне. Приложения работают с DLL через открытый API, а как там дальше реализована работа с сервером их не касается. Сам сервер необходим только если есть желание использовать расшареную память под шрифты, это единственный способ защитить её от затирания другими приложениями. Если есть желание двигаться в этом направлении я могу набросать примерный алгоритм инициализации.
Нет, я писал про COFF. Идея в том, чтобы спрятать и сервер и весь обмен библиотеки с сервером в одной DLL. В этом случае ты можешь как тебе угодно менять код и протоколы обмена с сервером и не заботиться о совместимости версий на этом уровне. Приложения работают с DLL через открытый API, а как там дальше реализована работа с сервером их не касается. Сам сервер необходим только если есть желание использовать расшареную память под шрифты, это единственный способ защитить её от затирания другими приложениями. Если есть желание двигаться в этом направлении я могу набросать примерный алгоритм инициализации.
Это было бы здорово! Только нужно будет хорошо продумать клиентский API (и не одному мне, потому что возможно не только я буду этой библиотекой пользоваться ), чтобы потом не пришлось менять программы, использующие библиотеку.Serge wrote:Sorcerer
Нет, я писал про COFF. Идея в том, чтобы спрятать и сервер и весь обмен библиотеки с сервером в одной DLL. В этом случае ты можешь как тебе угодно менять код и протоколы обмена с сервером и не заботиться о совместимости версий на этом уровне. Приложения работают с DLL через открытый API, а как там дальше реализована работа с сервером их не касается. Сам сервер необходим только если есть желание использовать расшареную память под шрифты, это единственный способ защитить её от затирания другими приложениями. Если есть желание двигаться в этом направлении я могу набросать примерный алгоритм инициализации.
Тем временем, исправлен баг в глифах с кривыми Безье, теперь все кривые стали более гладкими, стало меньше зубчиков. Улучшен алгоритм анти-алиасинга, экспериментирую с новыми вариантами субпиксельного сглаживания. Результат, который сейчас дает субпиксельное сглаживание, почти идеальный, если бы не было явных цветовых артефактов. Впрочем, в прошлом алгоритме они тоже сначала были в большом количестве.
Предлагаю сравнить...Вчерашние результаты и сегодняшние. Кривые, как я уже говорил, стали более гладкими. Исчезли (или почти исчезли) странные "блямбы" на них. Субпиксельно сглаженные глифы увеличили свое вертикальное разрешение вдвое и стали четче (правда, пока что плата за это - желтые и красные разводы вокруг букв). Разрывов стало гораздо меньше - и это, строго говоря, без контроля отсечки! Подписи по традиции растеризованы freetype без сглаживания.
upd: здесь антиалиасинговый растеризатор дал снова размытое и несколько тусклое (хотя лучше, чем в прошлый раз) изображение. Посмотрел на код, и обнаружил, что похоже сломал все то, что исправлял в нем вчера
Yep!
Что я говорил? Говорил, что скоро качество растеризации приблизится к FreeType2 с выключенным хинтингом.
Внес изменения в алгоритм субпиксельного сглаживания. И смотрите, что из этого вышло: Шрифт Droid Sans, 16px. Слева - самый новый вариант алгоритма, по центру - тот, что я показывал в прошлом сообщении, справа - растеризовано FreeType 2.
Сначала предлагаю посмотреть на первую строку. Выключить контроль отсечки в FreeType невозможно, так что без сглаживания глифы отличаются. Но я затрудняюсь сказать, где получилось лучше.
А теперь - мой триумф . Вторая и третья строки. По сравнению с тем, что было час назад, антиалиасинговый алгоритм дает более четкие буквы, а вокруг субпиксельно растеризованных букв исчезло цветовое гало (за это пришлось заплатить некоторой размытостью и тусклостью - но это можно исправить, подкрутив гамму). Но посмотрите пожалуйста на тот результат, что выдает FreeType 2 со сглаживанием. Он почти пиксельно идентичен тому, что выдают мои растеризаторы. Я пробовал наложить один на другой в GIMP - различия минимальны.
И даже если учитывать, что моя библиотека не понимает десяток форматов шрифтов и не содержит алгоритма хинтинга - все равно разница в размерах между моей библиотекой и FreeType приличная. В моей системе FreeType занимает 560 килобайт, а самая маленькая сборка, которую я смог сделать - 150кб для FreeType2 и 70кб для FreeType1. Текущая версия моей библиотеки занимает менее 10 килобайт.
Пффф, так, не расслабляться, впереди еще куча работы!
Что я говорил? Говорил, что скоро качество растеризации приблизится к FreeType2 с выключенным хинтингом.
Внес изменения в алгоритм субпиксельного сглаживания. И смотрите, что из этого вышло: Шрифт Droid Sans, 16px. Слева - самый новый вариант алгоритма, по центру - тот, что я показывал в прошлом сообщении, справа - растеризовано FreeType 2.
Сначала предлагаю посмотреть на первую строку. Выключить контроль отсечки в FreeType невозможно, так что без сглаживания глифы отличаются. Но я затрудняюсь сказать, где получилось лучше.
А теперь - мой триумф . Вторая и третья строки. По сравнению с тем, что было час назад, антиалиасинговый алгоритм дает более четкие буквы, а вокруг субпиксельно растеризованных букв исчезло цветовое гало (за это пришлось заплатить некоторой размытостью и тусклостью - но это можно исправить, подкрутив гамму). Но посмотрите пожалуйста на тот результат, что выдает FreeType 2 со сглаживанием. Он почти пиксельно идентичен тому, что выдают мои растеризаторы. Я пробовал наложить один на другой в GIMP - различия минимальны.
И даже если учитывать, что моя библиотека не понимает десяток форматов шрифтов и не содержит алгоритма хинтинга - все равно разница в размерах между моей библиотекой и FreeType приличная. В моей системе FreeType занимает 560 килобайт, а самая маленькая сборка, которую я смог сделать - 150кб для FreeType2 и 70кб для FreeType1. Текущая версия моей библиотеки занимает менее 10 килобайт.
Пффф, так, не расслабляться, впереди еще куча работы!
Отлично получилось !
Говорил: "Не могу, не знаю...", а вот, получается! Но не останавливайся, представь себе что тебе заставили читать книгу таким шрифтом.
Кстати ето 16px или 12?
Кстати ето 16px или 12?
Sorcerer
Браво!
В одиночку переплюнуть команду профессионалов... У меня просто нет слов...
Браво!
В одиночку переплюнуть команду профессионалов... У меня просто нет слов...
Это 16пкс. Спасибо Мне бы алгоритм автохинтинга... Попробую у экспертов спросить.
Who is online
Users browsing this forum: Bing [Bot] and 35 guests