Написание текста с диакритическими знаками (никуд, знаки вокализации) с использованием PIL (Python Imaging Library)

Написать простой текст на изображении с помощью PIL очень просто.

draw = ImageDraw.Draw(img)
draw.text((10, y), text2, font=font, fill=forecolor )

Однако, когда я пытаюсь написать знаки препинания на иврите (называемые «никуд» или ניקוד), символы не перекрываются должным образом. (Я предполагаю, что этот вопрос актуален также для арабского и других подобных языков.)

В поддерживающей среде эти два слова занимают одинаковое пространство/ширину (пример ниже зависит от вашей системы, отсюда и изображение):

סֶפֶר ספר

Однако при рисовании текста с помощью PIL я получаю:

ס ֶ פ ֶ ר

поскольку библиотека, вероятно, не подчиняется правилам кернинга (?).

Возможно ли, чтобы символ и знак препинания на иврите занимали одинаковое пространство/ширину без ручного ввода положения символов?

http://tinypic.com/r/jglhc5/5

URL изображения: http://tinypic.com/r/jglhc5/5


person Berry Tsakala    schedule 14.06.2009    source источник


Ответы (5)


Что касается арабских диакритических знаков: Python +Wand(Python Lib) +arabic_reshaper(Python Lib) +bidi.algorithme(Python Lib). То же самое относится к PIL/Pillow, вам нужно использовать arabic_reshaper и bidi.algorithm и передать сгенерированный текст draw.text((10, 25), artext, font=font):

from wand.image import Image as wImage
from wand.display import display as wdiplay
from wand.drawing import Drawing
from wand.color import Color
import arabic_reshaper
from bidi.algorithm import get_display

reshaped_text = arabic_reshaper.reshape(u'لغةٌ عربيّة')
artext = get_display(reshaped_text)

fonts = ['C:\\Users\\PATH\\TO\\FONT\\Thabit-0.02\\DroidNaskh-Bold.ttf',
         'C:\\Users\\PATH\\TO\\FONT\\Thabit-0.02\\Thabit.ttf',
         'C:\\Users\\PATH\\TO\\FONT\\Thabit-0.02\\Thabit-Bold-Oblique.ttf',
         'C:\\Users\\PATH\\TO\\FONT\\Thabit-0.02\\Thabit-Bold.ttf',
         'C:\\Users\\PATH\\TO\\FONT\\Thabit-0.02\\Thabit-Oblique.ttf',
         'C:\\Users\\PATH\\TO\\FONT\\Thabit-0.02\\majalla.ttf',         
         'C:\\Users\\PATH\\TO\\FONT\\Thabit-0.02\\majallab.ttf',

         ]
draw = Drawing()
img =  wImage(width=1200,height=(len(fonts)+2)*60,background=Color('#ffffff')) 
#draw.fill_color(Color('#000000'))
draw.text_alignment = 'right';
draw.text_antialias = True
draw.text_encoding = 'utf-8'
#draw.text_interline_spacing = 1
#draw.text_interword_spacing = 15.0
draw.text_kerning = 0.0
for i in range(len(fonts)):
    font =  fonts[i]
    draw.font = font
    draw.font_size = 40
    draw.text(img.width / 2, 40+(i*60),artext)
    print draw.get_font_metrics(img,artext)
    draw(img)
draw.text(img.width / 2, 40+((i+1)*60),u'ناصر test')
draw(img)
img.save(filename='C:\\PATH\\OUTPUT\\arabictest.png'.format(r))
wdiplay(img)

Арабская типографика на изображениях

person Nasser Al-Wohaibi    schedule 08.09.2014

забавно, через 5 лет и с огромной помощью @Nasser Al-Wohaibi я понял, как это сделать:

Необходимо было изменить текст с помощью алгоритма BIDI.

# -*- coding: utf-8 -*-
from bidi.algorithm import get_display
import PIL.Image, PIL.ImageFont, PIL.ImageDraw
img= PIL.Image.new("L", (400, 200))
draw = PIL.ImageDraw.Draw(img)
font = PIL.ImageFont.truetype( r"c:\windows\fonts\arial.ttf", 30)
t1 = u'סֶפֶר ספר!'
draw.text( (10,10), 'before BiDi :' + t1, fill=255, font=font)

t2 = get_display(t1)        # <--- here's the magic <---
draw.text( (10,50), 'after BiDi: ' + t2, fill=220, font=font)

img.save( 'bidi-test.png')

@ Ответ Нассера имеет дополнительную ценность, которая, вероятно, имеет отношение только к арабским текстам (буквы в арабском языке меняют форму и связанность в зависимости от их соседних букв, в иврите все буквы разделены), поэтому для этого вопрос имеет значение только часть биди.

в результате образца 2-я строка - правильная форма и правильное расположение знаков вокализации.

до и после биди

спасибо @tzot за помощь + фрагменты кода

по поводу:

примеры различного поведения шрифта с ивритом «nikud». Не все шрифты ведут себя одинаково: пример написания PIL, текст на иврите биди, с nikud, разными шрифтами

person Berry Tsakala    schedule 09.09.2014
comment
Привет, у меня был похожая проблема с использованием Pillow. Вы когда-нибудь находили способ правильно выровнять никуд независимо от шрифта? - person maltman; 22.12.2016

На какой системе вы работаете? У меня это работает в моей системе Gentoo; порядок букв обратный (я просто скопировал из вашего вопроса), что мне кажется правильным, хотя я мало разбираюсь в языках RTL.

Python 2.5.4 (r254:67916, May 31 2009, 16:56:01)
[GCC 4.3.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import Image as I, ImageFont as IF, ImageDraw as ID
>>> t= u"סֶפֶר ספר"
>>> t
u'\u05e1\u05b6\u05e4\u05b6\u05e8 \u05e1\u05e4\u05e8'
>>> i= I.new("L", (200, 200))
>>> d= ID.Draw(i)
>>> f= IF.truetype("/usr/share/fonts/dejavu/DejaVuSans.ttf", 20)
>>> d1.text( (100, 40), t, fill=255, font=f)
>>> i.save("/tmp/dummy.png", optimize=1)

производит:

пример текста отображается белым цветом на черном

EDIT: я должен сказать, что использование шрифта Deja Vu Sans не было случайным; хотя мне он не очень нравится (и все же я нахожу его глифы лучше, чем Arial), он удобочитаем, имеет расширенный охват Unicode и, кажется, лучше работает со многими приложениями, отличными от MS, чем Arial Unicode MS.

person tzot    schedule 19.06.2009
comment
Вы на самом деле не ответили, но вы помогаете увидеть ошибку: только DejaVuSans.ttf и Lucidaxxx.ttf ведут себя правильно под PIL! Все остальные мои TTF-файлы давали неправильный вывод (но они хорошо себя ведут вне PIL). Вы можете попробовать другие шрифты, например. Arial.ttf - person Berry Tsakala; 21.06.2009
comment
Шрифт TrueType (или шрифт OpenType) не обязательно означает, что это полный и полезный шрифт во всех приложениях. Майкл Каплан (в настоящее время работает в MS и тесно связан с проблемами Unicode) называет ArialUni шрифтом MS Office, а не шрифтом ОС, что бы он под этим ни имел в виду, здесь: blogs.msdn.com/michkap/archive/2007/07/15/3890144.aspx - person tzot; 22.06.2009
comment
для полноты вы не использовали алгоритм биди from bidi.algorithm import get_display; reversed = get_display(orig) - person Berry Tsakala; 17.04.2021
comment
@BerryTsakala: спасибо; кажется, что модуль bidi появился примерно через год после того, как я набрал ответ выше, так что это нормально, что о нем ничего не упоминается! :) В любом случае, вы сами дали более полный ответ. - person tzot; 17.04.2021

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

from bidi.algorithm import get_display
import arabic_reshaper
final_text = get_display(arabic_reshaper.reshape("اللغة العربية"))

это решит все проблемы, но не забывайте использовать шрифты Unicode, такие как введите здесь описание ссылки

person Feisal Aswad    schedule 29.03.2021

Мне кажется, что дело совсем простое. Вы можете использовать шрифты True Type и использовать

Вот пример: True печатать шрифты для PIL

Здесь вы можете найти шрифты True Type для иврита: Шрифты для иврита True Type

Удачи или как мы говорим на иврите - Мазаль Тов.

person Roman Kagan    schedule 15.06.2009
comment
Спасибо за ответ, но вы не ответили на вопрос. Как я уже писал - я умею писать TTF, и у меня уже есть шрифты TTF. - person Berry Tsakala; 15.06.2009