(вторая часть перевода статьи Раскрыты алгоритмы растеризации шрифтов )
Линукс
Унаследовав худшее
Windows плохо растрирует шрифты, Linux еще хуже.Все системы Linux, которые я видел, используют FreeType [10] Дэвид Тернер, Роберт Вильгельм и Вернер Лемберг.
Это отличная библиотека, но способ ее использования, к сожалению, нельзя назвать удачным.
Типичный скриншот Linux выглядит так:
Вот полный скриншот: связь
Проблема заметна сразу — черные пятна в скругленных углах, возникшие в результате сглаживания.
В целом можно сказать, что косые штрихи выглядят тяжелее вертикальных, что в результате создает впечатление «грязи».
Вы можете утверждать, что FreeType и Linux могут использовать субпиксельную растеризацию, аналогичную ClearType, но на мой взгляд, это не дает каких-либо существенных преимуществ.
Посмотрите на «W», «v» и «y» — проблема по сути та же, символы выглядят грязно.
Немного улучшить ситуацию в углах можно, воспользовавшись гамма-коррекцией в процессе растеризации, но идеального отображения этим все равно не добиться.
Гамма-коррекция
Гамма-коррекция работает следующим образом:Как вы могли заметить, закругленные углы со сглаживанием выглядят намного лучше с гаммой 2.0. Гамма-коррекция – это отдельная нетривиальная тема, и если вам интересно, исчерпывающую информацию вы можете найти в «Гамма FAQ» Чарльз Пойнтон [6].
В нашем случае речь идет не о кривых «исходный сигнал – результат» в электронных схемах, а скорее об особенностях человеческого зрения.
Визуальная реакция примерно пропорциональна квадратному корню из физической яркости.
Другими словами, если у нас есть два белых пикселя на черном фоне, и один излучает вдвое больше фотонов, чем другой, это не значит, что он будет вдвое ярче.
На самом деле примерно в 1,4 раза.
Вы можете легко убедиться в этом:
Справа есть два пикселя, и можно с уверенностью сказать, что они излучают в два раза больше фотонов в секунду, чем пиксель слева.
Однако они не выглядят в два раза ярче.
Четыре пикселя дадут примерно двойную яркость, а не два.
Без дальнейших объяснений мы можем сказать, что существует два основных цветовых пространства RGB: субъективно однородное, называемое sRGB, и физически однородное.
В последнем значение пропорционально физической яркости, в отличие от sRGB, в котором значение пропорционально субъективной яркости.
Обычно физически однородное цветовое пространство называют просто «линейным RGB».
При использовании сглаживания цвета должны быть сглажены в линейном пространстве, но перед отображением цвета должны быть преобразованы в sRGB. На практике этот шаг часто игнорируется и сглаживание выполняется непосредственно в sRGB. Во многих случаях это дает приемлемый результат, но не для растеризации текста, которую можно продемонстрировать непосредственно в Microsoft Word. Все дело в том, что они используют какой-то трюк для выделения текста, что-то вроде тривиальной инверсии, вместо того, чтобы перерисовывать его с нуля.
При обычном черно-белом сглаживании выделенный текст выглядит грязным.
С ClearType он получает цветную рамку:
Таким образом, можно сделать вывод, что Windows корректирует гамма-коррекцию (но не выделенного текста), а Linux ее обычно игнорирует. FreeType может легко применить желаемое гамма-преобразование к черно-белой маске сглаживания, создаваемой растеризатором.
Но работать это будет так же, как и в Windows: инвертирование цветов даст инвертированную гамму.
На практике это бесполезно, поскольку перед смешиванием гамму необходимо применять отдельно к каждому цветовому компоненту (что на практике эквивалентно работе в линейном RGB).
Поэтому гамма-коррекция черно-белой маски поможет только в том случае, если вы отображаете черный текст на белом фоне.
В этом случае для коррекции можно использовать значение около 2. Но если вы отображаете белый текст на черном фоне, вам нужно инвертировать значение гаммы, то есть использовать что-то около 0,5. Проблема в том, что вы не знаете точный цвет текста и фона; текст также может отображаться поверх градиента или изображения.
Таким образом, «черно-белая» гамма-коррекция не будет работать, а «полноцветная» гамма-коррекция может оказаться дорогостоящей и сложной в реализации.
Проблема в том, что для линейного RGB требуется более 8 бит на канал, иначе вы неизбежно получите потерю цвета.
Для текста это может быть приемлемо, но вы не можете требовать этого для всего рабочего стола! А работать в линейном RGB с использованием 16 бит на канал — все еще непозволительная роскошь.
Гамма не работает
На самом деле ситуация еще хуже.Вы можете применить гамма-коррекцию со значением 2 к скриншоту Linux в том же Irfanview (Изображение-> Улучшить цвета.
) и посмотреть на текст. Пожалуйста, постарайтесь не обращать внимания на то, что значки выглядят пересвеченными, и сосредоточьтесь на тексте.
Тебе нравится? Я до сих пор не знаю.
Когда я работал над растеризацией текста в АГГ , я думал, что правильная гамма-коррекция может решить все проблемы.
Ничего подобного! Независимо от того, насколько хорошо это работает, некоторые элементы кажутся толще, а некоторые тоньше, чем вертикальные и горизонтальные штрихи.
Это очень заметно в шрифтах без засечек, особенно когда штрихи строго выровнены по пикселям.
Проблема в том, что хинтинг TrueType был специально разработан для обычного черно-белого растеризатора без сглаживания! Использование любого сглаживания технически неверно, и большинство систем Linux так и поступают. Изображение ниже — результат сглаженной растеризации с использованием FreeType и GetGlyphOutline().
Текст выглядит паршиво и очень похож на то, что мы видим в Linux большую часть времени.
Никакая гамма-коррекция здесь не поможет. Например, лучший результат я получил при значении гаммы 1,5. Все равно выглядит плохо:
По мере продвижения вы могли заметить, что после определенного размера текст начинает казаться тяжелым.
Именно это и происходит в Windows. Если отключить ClearType, то это будет видно (размер текста точно не сохраняется).
В общем, вы поняли.
Чтобы сделать это более очевидным, мы можем увеличить векторное изображение, возвращаемое функцией GetGlyphOutline() из Win32 API, и посмотреть, что произойдет.
Вот как работает фирменный агрессивный хинтинг для номинального размера 13 пикселей.
Вот почему штрихи в букве «к» выглядят такими тонкими, почти незаметными.
В курсиве Times New Roman дела обстоят еще хуже: косая черта в букве «z» полностью исчезает. Искажение не влияет на обычный растеризатор без сглаживания, но тот, который использует FreeType, чувствителен к этим вещам.
Он напрямую вычисляет степень покрытия пикселей, поэтому честно получает нулевое покрытие для косой линии «z».
То есть получается, что интерпретировать байт-код TrueType для хинтинга нет смысла (не говоря уже о том, что придется покупать лицензию).
Сглаживание — это хорошо, но его не стоит использовать само по себе.
В любом случае, я бы предпочёл текст без сглаживания, если он используется в сочетании с неадекватным хинтингом.
Автохиндер FreeType
Во второй версии FreeType Дэвид Тернер представил механизм автоподсказок.Он работает достаточно хорошо, но, тем не менее, его прямое применение дает результаты, далекие от идеальных.
Посмотрите на результат растеризации гарнитуры Verdana с гаммой 1,5:
Сравните с примером без намеков:
Версия без намеков определенно выглядит чище, но и размытее.
Есть три основных различия:
- Автоматическая хинтинг по-прежнему дает ошибки в небольших закругленных элементах (такая же визуальная разница в толщине между вертикальными и наклонными штрихами).
- Иногда автохинтинг приводит к неправильному кернингу, как в случае с «ог» в слове «Собака» (в данном примере использовалась таблица кернинга из шрифта).
- Автоматические подсказки приводят к той же проблеме: ошибки накапливаются по всей строке текста, в результате чего правый край текста становится неровным.
Что делать?
Забегая вперед, покажу вам еще один пример.
Найти приемлемое решение все же возможно! Но сначала вам нужно признать, что невозможно использовать какие-либо хинтинги и при этом сохранять правильное расположение текста в любом масштабе.
Только текст без намеков, с его естественной размытостью.
Однако мы можем улучшить растеризацию, хотя и придется пожертвовать чем-то не очень важным.
А именно, мы можем позволить себе небольшую неточность в вертикальном расположении и высоте текста.
Помимо прочего, хинтинг TrueType работает одинаково: строки текста высотой, скажем, 12 и 13 пикселей будут иметь одинаковую высоту на экране, хотя и будут выглядеть по-разному.
Короче говоря, чтобы текст выглядел приятно для глаз, сохраняя при этом аккуратное горизонтальное позиционирование, нам нужно следующее:
- Используйте горизонтальное субпиксельное сглаживание RGB на ЖК-мониторах.
- Используйте только вертикальные хинтинги и полностью откажитесь от горизонтальных хинтингов.
- Используйте точные значения смещения глифа, рассчитанные в высоком разрешении для глифов без хинтинга.
- Используйте точные значения высокого разрешения из таблицы кернинга.
Текст хорошо выглядит даже непосредственно в sRGB, а значит, в инвертированных цветовых схемах проблем не будет. Вы можете легко добиться приемлемых результатов с помощью FreeType и его автохиндера.
Это означает, что вам не нужно беспокоиться о лицензировании собственных подсказок TrueType. То же самое можно сделать с помощью функции GetGlyphOutline() из Win32 API. Это сложнее, но все же возможно.
Субпиксельная растеризация в RGB
Подробное руководство по использованию субпиксельной растеризации в RGB можно найти на страницах Стива Гибсона.«Технология субпиксельной растеризации» [2].
Я также пробовал использовать эту технологию с 64-уровневыми сглаженными растровыми изображениями, которые может генерировать GetGlyphOutline(): Максим Шиманарев, «Как ClearType работает в Windows Longhorn» [3] (UPD: ссылка битая, но прочитать можно Здесь , Здесь или Здесь ).
Скачать демо-программу для Windows со всеми исходниками можно по этой ссылке: antigrain.com/stuff/lcd_font.zip Кроме того, я написал простой, «вечером на коленях», растеризатор для АГГ .
Его можно найти в демонстрациях, которые приведены ниже.
На данный момент код небезопасен и довольно медленный.
Это нормально для демонстрационных программ, но неприемлемо в реальном проекте, прежде всего потому, что он использует временный буфер не более чем на 2048 пикселей в стеке.
В простейшем случае все, что нам нужно — это значения прозрачности для каждого цветового канала.
В этом файле agg_pixfmt_rgb24_lcd.h. Я также использовал дополнительное размытие, которое описывает Стив Гибсон.
Это делается на лету, хотя это можно сделать и заранее, используя какой-то механизм кэширования.
В этом случае он будет работать гораздо быстрее, по крайней мере, не медленнее, чем классическое альфа-микширование.
Для отладки микширования каналов я использовал программу Приблизить [9] Брайан Фризен.
Я добавил «расшифровку» троек цветов во всех масштабах, кратных трем.
Скачать исполняемый файл можно здесь: antigrain.com/stuff/ZoomInLcd.zip (Измененные исходники я потерял в 2005 году.
В любом случае, эти модификации несложно сделать самостоятельно).
Вы можете сравнить увеличенные результаты обычной черно-белой и субпиксельной растеризации RGB:
Черно-белая растеризация
Субпиксельная растеризация RGB
Прочие нюансы
Чтобы сохранить вертикальные хинтинги, но избавиться от горизонтальных, мы просто обманываем хинтер: растягиваем символы по горизонтали, чтобы хинтер был вынужден работать с высокой точностью.Проблема в том, что движок шрифтов АГГ для FreeType используются неточные значения смещения с учетом хинтинга.
Технически подсказка должна рассчитывать точные значения смещения для сильно растянутых глифов, но по неизвестной причине этого не происходит. Мне пришлось изменить его, чтобы использовать исходные, «ненамеренные» смещения.
Модифицированная версия также включена в демо-программы.
Как только кривая глифа получена, мы используем аффинное преобразование, чтобы сжать ее обратно.
В простейшем случае это все, что нам нужно.
Таблица кернинга содержит достаточно точные значения.
Поэтому я хотел бы спросить Дэвида Тёрнера: может быть, имеет смысл добавить в его автохиндер опцию, которая позволяла бы хинтовать только по оси Y, игнорируя хинтинг по оси X? Или можно сделать отдельную 1-D подсказку, намного проще существующей.
Как вы увидите, субпиксельный текст RGB выглядит очень похоже на Adobe Acrobat Reader и в любом случае намного лучше, чем в любой современной системе Linux ( Статья написана в 2007 году – прим.
перевод ).
Я считаю, что это поможет продвинуть и увеличить популярность систем на базе Linux. Использование Windows API значительно сложнее.
Функция GetGlyphOutline() возвращает значение смещения в целочисленных пикселях, что для нас слишком грубо.
Растяжка не помогает. Есть еще такие функции, как GetCharABCWidthsFloat(), но они бесполезны, поскольку вычисляют значения для глифов с подсказками и, несмотря на то, что они содержат числа с плавающей запятой, они по-прежнему являются целыми числами.
Поэтому я не нашел простого способа получить точные смещения.
В результате мне пришлось использовать одновременно два шрифта, один высотой 1024 пикселя, а другой нужного нам размера, с хинтингом и растянутой аффинной матрицей.
Допускаю, что мог что-то упустить, но понятия не имею, как это можно было бы реализовать более корректно.
Возможно, они используют какие-то недокументированные возможности Microsoft Word, что совершенно несправедливо с точки зрения конкуренции.
Я, конечно, не могу быть в этом полностью уверен, но ситуация заставляет меня думать, что Microsoft намеренно не предоставляет достаточно хороший API для разработки инструментов для работы с WYSIWYG-документами.
Это типичная политика монополистов, которая в результате приводит к замедлению технического прогресса.
На самом деле все еще хуже.
Фирменная подсказка не работает с «растянутой» матрицей! Как минимум, я не нашел коэффициента масштабирования, который правильно обрабатывал бы глифы.
Корректно работал только масштаб 1:1, но в результате я получил те же проблемы, которые заставили меня использовать черно-белый растеризатор без сглаживания:
Выглядит жутко, не так ли? Любое масштабирование приводило к сильному повреждению глифов.
Вот, например, курсив Times New Roman (растяжение по горизонтали в 16 раз):
Или даже это.
Arial (100-кратное растяжение по горизонтали) — смешные мазки, да? Но невозможно прочитать:
Думаю, нет смысла говорить, что автохиндер FreeType работает корректно на любом отрезке.
Выглядит так, будто Microsoft API — это просто куча нездоровых случайных решений «на коленке» без какой-либо инженерной культуры и глобальной идеи, стоящей за всем этим.
Как правило, вы можете использовать программное обеспечение Microsoft только одним строго определенным способом.
Шаг вправо, шаг влево – и все пропало.
Возможно, это и хорошо для их бизнеса, но это как минимум нечестно.
Такая политика нарушает условия добросовестной конкуренции и, как следствие, замедляет общий прогресс на рынке.
Антимонопольному комитету следует обратить внимание на эту ситуацию, а не на нелепые требования удалить из системы Media Player или Internet Explorer.
В конце концов я обнаружил, что «16» — меньшее зло и работает в большинстве случаев, но по-прежнему не работает для курсива Times New Roman.
Демо-программа
Вот она, программа для Windows, использующая TrueType: www.antigrain.com/research/font_rasterization/truetype_test_02_ft.zip А вот версия, использующая Windows API: www.antigrain.com/research/font_rasterization/truetype_test_02_win.zip Версия FreeType требует наличия в каталоге программы следующих файлов: arial.ttf, ariali.ttf, georgia.ttf, georgiai.ttf, tahoma.ttf, times.ttf, timesi.ttf, verdana.ttf, verdanai.ttf. Вы можете найти их в папке %WINDIR%\Fonts. Если вы хотите скомпилировать его, скачайте АГГ версию 2.4 или 2.5 и извлеките файлы куда-нибудь вроде agg-2.4\research\win32\trutype_lcd\*.*.
Для версии FreeType вам также потребуется собрать FreeType самостоятельно и, возможно, изменить настройки проекта.
Программу также можно собрать для Linux/X11 или другой системы, если вы напишете соответствующий make-файл, подобный тем, которые используются в примерах.
АГГ .
Текст в версиях FreeType и WinAPI выглядит по-разному из-за разных алгоритмов хинтинга.
Здесь вы видите большое количество настроек.
Во-первых, мы можем менять шрифты, а также включать или отключать кернинг, хинтинг и субпиксельную растеризацию RGB. Кроме того, вы можете инвертировать изображение, чтобы получить белый текст на черном фоне.
Ползунок «Масштаб шрифта» позволяет плавно менять размер шрифта.
Как видите, при включении хинтинга линии привязываются к пикселям, но ширина текста продолжает плавно изменяться.
Вы можете лучше увидеть этот эффект, изменив интервал.
Без хинтов размещение текста прекрасно сохраняется в любом масштабе, но текст выглядит размытым.
Привязка вертикальных линий — наиболее разумный компромисс между резкостью и точностью размещения текста.
Я сам шокирован тем, насколько вертикальные хинтинги улучшают качество, сохраняя при этом форму персонажей.
Я думаю, что интервал, ширина и ползунки «фальшивого курсива» не нуждаются в комментариях.
Для людей, знакомых с компьютерной графикой, очевидно, что это обычные аффинные преобразования .
Хотелось бы отметить лишь один факт: в режимах «черно-белое» и «субпиксельная RGB-растеризация» ползунок «имитация курсива» работает немного по-другому.
Это потому, что мне было лень правильно обработать его значения, через арктангенсы.
В любом случае это неважно.
Функция, которой я особенно горжусь, — это функция «имитировать жирный шрифт».
Это работает следующим образом:
Есть еще один простой трюк.
Включено АГГ Существует утилита conv_contour, которая позволяет вычислить равноудаленный многоугольник для данного многоугольника.
Но его использование напрямую дает слишком размытый результат, а также заметно меняет форму персонажей (хотя это может быть полезно для эффектов свечения и тени):
Размытия легко избежать.
Мы растягиваем глифы по вертикали, скажем, в 100 или 1000 раз, вычисляем равноотстоящий многоугольник и снова сжимаем его.
В результате координаты по оси Y почти не меняются и текст остается четким.
Демо-программа имеет класс «faux_weight».
Опять же, удивительно, сколько свободы дает свободное горизонтальное масштабирование.
И не менее удивительно, насколько вертикальная привязка пикселей улучшает визуальный результат.
Другой пример (я люблю эту свободу):
Это все та же гарнитура Georgia, но только программно преобразованная.
Вполне читаемый, ясный и в то же время плавный (да, я согласен, можно было бы использовать ручной кернинг).
Или то же самое для гарнитуры Tahoma:
Ползунок регулировки гаммы управляет гамма-коррекцией (осуществляется отдельно для каждого канала).
Теоретически вам следует применить «прямую гамму» к исходным цветам, а затем, после рендеринга сцены, применить «инвертированную гамму».
Но поскольку текст в этих примерах всегда белый или черный, первая операция не имеет смысла.
Ползунок «основной вес» управляет распределением энергии так же, как описано Стивом Гибсоном: www.grc.com/freeandclear.htm .
Достаточно хорошо распорядиться только основным весом и соответственно рассчитать остальные.
Увеличив основной вес, можно сделать текст более четким, но при этом вокруг символов появится цветной контур.
Имеет смысл использовать значения до 0,5; при больших значениях «свечение» цвета становится слишком заметным.
Как по мне, Windows ClearType тоже дает слишком заметное цветовое «свечение».
Эта растеризация может работать быстро
Демо-программа работает довольно медленно.Частично потому, что векторные операции выполняются на лету, но в первую очередь из-за функции WinAPI GetGlyphOutline(), которая сама по себе жутко медленная.
С другой стороны, такая растеризация может быть не менее быстрой, чем любая аппаратная растеризация текста.
Но для начала согласитесь, что ускорить растеризацию произвольно переменного текста с сохранением хинтинга, правильной разметки и четкого качества субпикселей — задача в принципе непростая.
Под произвольными преобразованиями я подразумеваю действительно произвольные, включая перспективные и любые нелинейные преобразования.
Большую часть времени нам приходится иметь дело с горизонтальным текстом, даже если мы используем восточноазиатские языки.
Кроме того, в большинстве случаев глифы имеют один и тот же номинальный размер.
Отсюда следует, что здесь будет полезен механизм кэширования.
Субпиксельная черно-белая маска для трех каналов RGB требует в три раза больше памяти, но при этом обеспечивает точность позиционирования текста до 1/3 пикселя.
В большинстве случаев это работает вполне хорошо.
За исключением теоретической «роскошной» растеризации, вы можете использовать две черно-белые маски для каждого глифа, получая точность 1/6 пикселя.
Даже программное альфа-смешение происходит довольно быстро — около 2-4 мс на глиф на современных процессорах Intel или PPC. При использовании графического процессора это может произойти еще быстрее, если вы загрузите соответствующие текстуры.
Единственная проблема заключается в том, что графический процессор должен разрешать альфа-смешение между каналами, что, насколько мне известно, кажется возможным.
По крайней мере, Дэвид Браун об этом упоминает. в вашей презентации [8].
Но я не смог найти дополнительной информации по этой теме (как получить 6-канальный вывод из пиксельного шейдера), и я был бы признателен, если бы вы могли предложить мне несколько ссылок по этой теме.
Ссылки
- Джоэл Спольски, Сглаживание шрифтов, сглаживание и субпиксельный рендеринг.
- Стив Гибсон, Технология рендеринга субпиксельных шрифтов.
- Максим Шеманарев, Внутри ClearType в Windows Longhorn. www.byte.com/documents/s=9553/byt1113241694002/0411_shemanarev.html
(требуется онлайн-регистрация.
)
- Официальный документ Font Focus, artofcode.com/fontfocus
- Джефф Этвуд, «Рендеринг шрифтов: уважение к пиксельной сетке».
- Чарльз Пойнтон, Часто задаваемые вопросы о Гамме.
- Дэйв Ши, «Субпиксельное сафари».
- Дэвид Браун, Avalon Text. Презентация PowerPoint. download.microsoft.com/download/1/8/f/18f8cee2-0b64-41f2-893d-a6f2295b40c8/TW04007_WINHEC2004.ppt
- Брайан Фризен, программа ZoomIn. www.csc.calpoly.edu/~bfriesen/software/zoomin.shtml
- Дэвид Тернер и другие, Библиотека шрифтов FreeType. freetype.org
- Джим Мэтис, Масштабирование DPI в стиле XP. www.mathies.com/weblog/Эp=908
- Лонг Чжэн, Масштабирование DPI в Windows Vista: моя Vista больше, чем ваша Vista www.istartedsomething.com/20061211/vista-dpi-scaling
Вторая часть статьи в веб-архиве (с картинками).
PPS: Несколько интересных ссылок для тех, кто интересуется темой экранной типографики: Теги: #Типография #графика #алгоритм #шрифты #субпиксельная растеризация #FreeType #сглаживание шрифтов #сглаживание шрифтов
-
Уход За Детской Ванной
19 Oct, 24 -
Numpy На Python. Часть 1
19 Oct, 24 -
Blu-Ray Плееры – 93% Продаж
19 Oct, 24 -
Микрокопирайтеры – Наше Будущее
19 Oct, 24