Почему мой шрифт TrueType размера 11 отличается от Windows? - PullRequest
4 голосов
/ 21 апреля 2011

То есть: Блокнот открыт, шрифт выбран как «Arial, размер 11», слова «это просто тест» тщательно введены, снимок экрана:

оригинал http://i53.tinypic.com/200skuv.png

Введен и запущен следующий код Python:

import ImageFont, ImageDraw, Image
im = Image.open("c:/textimg.png") #the above image

pilfont = ImageFont.truetype("arial.ttf", 11)

compimg = Image.new("RGB", im.size, (255, 255, 255))
draw = ImageDraw.Draw(compimg)

draw.text((0,0), "this is just a test", (0,0,0), font=pilfont)

compimg.save("c:/compimg.png")

И все же результат неутешительно отличается:

sad http://i56.tinypic.com/9h7x55.png

Мало того, что это неправильноразмер, но он также слегка затенен, в то время как рендеринг блокнота четкий и не пересекает границы пикселей.

Как я могу заставить его рендерить, как это делает блокнот?У меня тоже была эта проблема с pygame, так что я думаю, что мне здесь не хватает фундаментального понимания о TTF.

ОБНОВЛЕНИЕ: Я попробовал это снова с pygame.Это делает то же самое.У него есть возможность отключить сглаживание, но похоже, что он просто обрезает любые пиксели, которые он будет сглаживать, основываясь на некотором пороге.Самое близкое приближение, которое я получил, использовало размер 15. Код был:

pygfont = pygame.font.Font(r"c:\windows\fonts\arial.ttf", 15)
surf = pygfont.render("this is just a test", False, (0,0,0), (255,255,255))
pygame.image.save(surf, r"c:\pygameimg.png")

и результат (оригинал блокнота сверху для сравнения):

KILL ME http://i56.tinypic.com/2r26mbs.png

Гах, почему я не могу сразу предложить вознаграждение?

ОБНОВЛЕНИЕ: здесь сравниваются все методы:

AIFEOIFEF http://i56.tinypic.com/51ybtg.png

PIL 15, затем блокнот 11, затем pygame 15 - отключение псевдонима, затем pygame 15 - отключение псевдонима.

PIL 15 на самом деле имеет правильные пропорции, это просто сглаживание.итак: почему 15 против 11?Как заставить это сделать так же, как Windows?(и что делает Pygame?)

Ответы [ 5 ]

4 голосов
/ 22 апреля 2011

Рендеринг шрифтов - это сложный и тонкий процесс, который был реализован несколько раз.В вашем случае PIL и Windows выглядят по-разному, потому что они используют совершенно разные механизмы рендеринга шрифтов.Windows использует свой встроенный рендеринг, а PIL использует Freetype, с которым он был скомпилирован.

Я не знаю, как каждая среда интерпретирует свой параметр "size", но даже если вы их интерпретируете одинаково,рендеринг будет просто другим.Чтобы получить те же пиксели, что и в «Блокноте», нужно запустить «Блокнот» и захватить экран.

Возможно, если вы объясните больше, почему вы хотите использовать тот же рендеринг, что и в «Блокноте», у нас будут творческие решения вашей проблемы.

1 голос
/ 13 ноября 2016

Как уже отмечал Нед, не очень правильно пытаться получить тот же результат из какой-нибудь библиотеки рендеринга.Если вам нужен точно такой же внешний вид, вы пытаетесь получить доступ к внутренней функциональности Windows, и это то, что вы уже сделали, как я вижу из вашего другого поста, и это очень интересно.

Если говорить о реалистичной визуализации текста для экрана в целом, то здесь есть некоторые несущественные нюансы.Во-первых, все форматы векторных шрифтов изначально разрабатываются не для экрана, а просто для типографики и ее двух больших отличий.Для экрана все, что вам нужно, это растровое изображение, а именно информация о 8-битном альфа-канале, которую вы затем смешиваете с фоном экрана вместе со значениями пикселей.Чтобы все заработало, вам нужно буквально скопировать файл TTF в набор растровых изображений.

И вот два пути, грубо говоря:

  • Извлечение глифов с высоким разрешением в BW (1-бит).Например, ~ 600px растровых изображений будет достаточно для большинства случаев.Затем вы можете создавать и изменять размеры строк в зависимости от потребностей.

  • Извлечение их непосредственно к целевому разрешению в виде 8-битных массивов.В этом случае вы не можете изменять их размер, а только строите строки, просто помещая эти 8-битные массивы в альфа-канал и размещая их вдоль линии.

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

Лучше придерживаться первого шага, потому что второй подход, который вы можете реализовать и с растровыми изображениями с высоким разрешением, не нужно растеризовывать его каждый раз.Для небольших размеров для лучшей точности расстояния вы также можете генерировать «сдвинутые» глифы, то есть те же самые глифы, но смещенные на 1/2 или 1/3 пикселя в исходном изображении с высоким разрешением.Это снова потребует немного другой процедуры построения строки.

Важное примечание о размере : нет такой точной вещи, как размер шрифта.В типографии это размер квадрата Em и не имеет прямой связи с высотой x шрифта.Более того, если я выполняю рендеринг или повторную выборку растрового изображения, я работаю только с размером пикселя Em-квадрата (границы целого растрового изображения) и коэффициентом понижающей дискретизации, если я использую его для получения небольших растровых изображений.Реальный размер x-высоты может быть приблизительно рассчитан только для справки.

Для вашего случая не сглаженных растровых изображений эти небольшие растровые изображения должны быть уже включены в файл шрифта, по крайней мере, для собственных шрифтов, таких как Arial и Times.IIRC Они хранятся внутри TTF для особых небольших размеров обычно 7-16 пт и в виде 1-битных масок.Вопрос только в том, как извлечь или получить их из приложения.Я не знаю, на самом деле, я вижу это просто как устаревшие вещи.Я больше в реалистической проблематике рендеринга.

1 голос
/ 22 апреля 2011

Успех - посмотрите на красную линию:

Слава Господу http://i54.tinypic.com/2r60dc3.png

Используя созданный мной метод здесь .

Интересно,Я все еще должен был предоставить размер шрифта 15. Я не уверен, что это связано с точками и пикселями, хотя, как говорят в документах:

> 0: преобразователь шрифтов преобразует это значение вединицы устройства и сопоставляет его с высотой ячейки доступных шрифтов.

<0: преобразователь шрифтов преобразует это значение в единицы устройства и сопоставляет его абсолютное значение с высотой символа <strong> доступных шрифтов.

Тем не менее, поставка -11 не дала желаемого результата ... она просто сделала его меньше ... так что я понятия не имею.Вероятно, это точка против пикселя.

1 голос
/ 22 апреля 2011

Размеры отличаются, потому что они указаны по-разному. Чтобы преобразовать точки в пиксели, используйте формулу: pixels = points * 96 / 72, где 96 - это DPI, настроенный в Windows (не фактический DPI монитора). В вашем случае 11 * 96/72 = 14,6666, что округляет до 15.

Что касается того, чтобы сделать текст попиксельным, идентичным, это будет невозможно с помощью предоставленных инструментов - Нед является правильным . Если это абсолютно необходимо, вам нужно использовать Windows API, чтобы отобразить этот текст и скопировать его в изображение. Не простой процесс.

1 голос
/ 21 апреля 2011

Я думаю, что «размер» Блокнота равен pointsize, а «size» ImageFont.truetype () - это пиксели.

...