python-pillow / Pillow

Python Imaging Library (Fork)
https://python-pillow.org
Other
12.18k stars 2.22k forks source link

The parameter direction of ImageDraw.text can't use Chinese sequence #3125

Closed xyl576807077 closed 5 years ago

xyl576807077 commented 6 years ago

What did you do?

  1. I try to draw chinese character by following test code

    from PIL import Image, ImageDraw, ImageFont
    size = 32
    font = ImageFont.truetype('./font/simsun.ttf', size)
    img = Image.new('RGBA', (size, size), (0, 0, 0, 0))
    draw = ImageDraw.Draw(img)
    draw.text((0, 0), '我和你',  fill='black', direction='ttb')
  2. Futhermore, if I don't use chinese, just english:

    from PIL import Image, ImageDraw, ImageFont, features
    size = 32
    img = Image.new('RGBA', (size, size), (255, 255, 255))
    draw = ImageDraw.Draw(img)
    draw.text((0, 0), 'abc', fill='black', direction='rtl')

    What did you expect to happen?

  3. I want to get the image like that

    我
    和
    你
  4. I want to get the image aa

What actually happened?

  1. The code can't run successfully. The log is
    Traceback (most recent call last):
    File "draw_character.py", line 111, in <module>
    draw.text((0, 0), '我和你',  font=font, fill='black', direction='ttb')
    File "/home/xyl/anaconda3/lib/python3.6/site-packages/Pillow-5.0.0-py3.6-linux-x86_64.egg/PIL/ImageDraw.py", line 220, in text
    File "/home/xyl/anaconda3/lib/python3.6/site-packages/Pillow-5.0.0-py3.6-linux-x86_64.egg/PIL/ImageFont.py", line 166, in getmask2
    RuntimeError: raqm_layout() failed.

    The font file can be downloaded in here: https://github.com/micmro/Stylify-Me/blob/master/.fonts/SimSun.ttf

  2. I get the image like this: hehe

What versions of Pillow and Python are you using?

python: 3.6.3
pillow: 5.0.0
lyu-huiyang commented 6 years ago

@xyl576807077

Hi, I meet the same problem, I try use python2 env to solve the problem but not work.

Finally, I change the font to solve it. You can try to use the Chinese font to draw the image If your text is in Chinese. For example, I use the font called '华文细黑.ttf' then the program will work.

The code:

im = Image.open("./source.jpeg")
font = ImageFont.truetype(font="./华文细黑.ttf", size=40)
draw = ImageDraw.Draw(im)
draw.text(xy=(100, 800), text="2018年5月23日,天气晴。", fill=(0, 0, 0, 0), font=font)

im.show() : show demo

xyl576807077 commented 6 years ago

@lvhuiyang Hi lvhuiyang, Thanks for your solution. But my question is the parameter direction in ImageDraw.text(). This parameter can change the text direction according to the documentation. I don't know this parameter whether it is useful or not on your env. I hope I can get your reply.

lyu-huiyang commented 6 years ago

@xyl576807077 I think I can't help you because I meet the same problem when I use parameter direction. I find the description from doc:

Direction of the text. It can be ‘rtl’ (right to left), ‘ltr’ (left to right), ‘ttb’ (top to bottom) or ‘btt’ (bottom to top). Requires libraqm.

Requires libraqm. So, I install libraqm from libraqm's doc but my program can't work yet. If get the solution you can tell me, thanks.

binhnq94 commented 6 years ago

I got the same bug.

Traceback (most recent call last):
  File "tools/check_generated_img.py", line 130, in <module>
    check_textimg_gen(sys.argv[1], 32, 820, 32, rotate=False, rand_invert=True, vertical=True)
  File "tools/check_generated_img.py", line 56, in check_textimg_gen
    for inp, out in textimagegen.next_train():
  File "/mnt/data/VisualRecognition/infordio/crnn/generators.py", line 351, in next_train
    self.minibatch_size, train=True)
  File "/mnt/data/VisualRecognition/infordio/crnn/generators.py", line 332, in get_batch
    X_data[i, 0:self.img_w, :, 0] = self.paint_func(text_obj).T
  File "/mnt/data/VisualRecognition/infordio/crnn/generators.py", line 380, in <lambda>
    vertical=self.vertical)
  File "/mnt/data/VisualRecognition/infordio/crnn/generators.py", line 436, in paint_text
    invert=gen_invert)
  File "/mnt/data/VisualRecognition/infordio/crnn/paint.py", line 564, in paint_txt_v51_vertical
    text_width, text_height = font.getsize(text_obj.sen, direction=direction)
  File "/home/binhnq/anaconda3/envs/infordio/lib/python3.5/site-packages/PIL/ImageFont.py", line 156, in getsize
    size, offset = self.font.getsize(text, direction, features)
RuntimeError: raqm_layout() failed.

Do someone have some idea? :(

Lyntball commented 6 years ago

ok i'm not the only one.

masushin commented 6 years ago

I think that the following issue of raqm is causing raqm_layout() to fail. https://github.com/HOST-Oman/libraqm/issues/81 So, we need to update raqm to latest.

However, I think that even if using latest raqm, Pillow cannot works the direction feature for "ttb" correctly. https://github.com/python-pillow/Pillow/issues/2656

I have checked it using latest raqm, it does not works yet.

KennethanCeyer commented 6 years ago

I have suffering the same issue

I tried to check various libraqm versions 0.3.0, 0.4.0, 0.5.0 0.6.0(master)

with pillow 5.2.0 and python 3.6 in MacOS HighSierra 10.13.6

4.3.0 + libraqm 0.3.0 + harfbuzz 1.7.0 => mangled 5.0.0 + libraqm 0.4.0 + harfbuzz 1.7.0 => mangled 5.0.0 + libraqm 0.5.0 + harfbuzz 1.8.0 => mangled 5.0.0 + libraqm 0.6.0 + harfbuzz 1.9.0 => mangled

2018-09-18 6 01 18

from os import path
from PIL import Image, ImageFont, ImageDraw

def test_layout():
    image = Image.new('RGBA', (500, 500))
    font = ImageFont.truetype(path.join('../../input/fonts/font.otf'), 40)
    draw = ImageDraw.Draw(image, 'RGBA')
    draw.text((0, 0), 'test', font=font, fill='#000000', direction='ttb')
    image.show()

test_layout()
hugovk commented 6 years ago

Should this be reported to https://github.com/HOST-Oman/libraqm?

KennethanCeyer commented 6 years ago

@hugovk I don't know of the detailed point of the problem (fault of libraqm or not)

KennethanCeyer commented 6 years ago

And i also found some error of documentation

check follows link https://pillow.readthedocs.io/en/5.2.x/reference/ImageDraw.html#PIL.ImageDraw.PIL.ImageDraw.ImageDraw.text

2018-09-18 6 52 22

Direction of the text. It can be ‘rtl’ (right to left), ‘ltr’ (left to right), ‘ttb’ (top to bottom) or ‘btt’ (bottom to top). Requires libraqm.

(top to bottom) or ‘btt’ option doesn't work in 5.2.0

Traceback (most recent call last):
  File "/Users/user/Desktop/project/vincent/source/project/src/designer/ruler/test_layout.py", line 22, in <module>
    test_layout()
  File "/Users/user/Desktop/project/vincent/source/project/src/designer/ruler/test_layout.py", line 18, in test_layout
    draw.text((0, 0), 'test', font=font, fill='#000000', direction='btt')
  File "/Users/user/.local/share/virtualenvs/project-rA-tx4nR/lib/python3.6/site-packages/PIL/ImageDraw.py", line 275, in text
    *args, **kwargs)
  File "/Users/user/.local/share/virtualenvs/project-rA-tx4nR/lib/python3.6/site-packages/PIL/ImageFont.py", line 184, in getmask2
    size, offset = self.font.getsize(text, direction, features)
ValueError: direction must be either 'rtl', 'ltr' or 'ttb'
hugovk commented 6 years ago

@KennethanCeyer Good find, Raqm doesn't support btt. Here's a PR to update the docs: https://github.com/python-pillow/Pillow/pull/3362.

KennethanCeyer commented 6 years ago

Is it some kind a bug of

https://github.com/python-pillow/Pillow/blob/3cf6ad1895ce6a77245d3bc96c8d19c440ad6132/src/_imagingft.c#L462-L467

?

or just

https://github.com/HOST-Oman/libraqm/blob/4ebfcd4121cb1796f7391d34d0a59a579d01505e/src/raqm.c#L834-L915

https://github.com/HOST-Oman/libraqm/blame/4ebfcd4121cb1796f7391d34d0a59a579d01505e/src/raqm.c#L834-L915

radarhere commented 5 years ago

@KennethanCeyer what font are you using in your example - 'input/fonts/font.otf'?

KennethanCeyer commented 5 years ago

@radarhere I've tried today again with follows code in MacOS.

and These issues seem to be still existed

from os import path
from PIL import Image, ImageFont, ImageDraw

def test_layout():
    image = Image.new('RGBA', (500, 500))
    font = ImageFont.truetype(path.join('/Library/Fonts/Arial.ttf'), 40)
    draw = ImageDraw.Draw(image, 'RGBA')
    draw.text((0, 0), 'test', font=font, fill='#000000', direction='ttb')
    image.show()

test_layout()

As you can see, I've tested with Truetype font, Arial.ttf

스크린샷 2019-05-06 오후 10 01 29

>>> import PIL
>>> print(PIL.__version__)
6.0.0
radarhere commented 5 years ago

I've created PR #3856 to resolve the problem from @KennethanCeyer.

radarhere commented 5 years ago

3856 has been merged. From the original post, 1 should be solved. Here is my slightly adjusted code -

from PIL import Image, ImageDraw, ImageFont
font = ImageFont.truetype('SimSun.ttf', 32)
im = Image.new('RGBA', (100, 100), (0, 0, 0, 0))
draw = ImageDraw.Draw(im)
draw.text((0, 0), '我和你', 'black', font, direction='ttb')
im.save('out.png')
radarhere commented 5 years ago

With regards to 2 in the original post, I don't think this is how rtl works. English characters are strong characters, and have a definite directionality. However, weak characters, such as arithmetical symbols, do not and are able to be shown right-to-left by Pillow.

from PIL import Image, ImageDraw, ImageFont
font = ImageFont.truetype('SimSun.ttf', 32)
im = Image.new('RGBA', (100, 100), (0, 0, 0, 0))
draw = ImageDraw.Draw(im)
draw.text((0, 0), '+-=', 'black', font, direction='rtl')
im.save('out.png')

Since your goal surely isn't just to show English characters in reverse, there's not a specific situation to help with here. If anyone has any further thoughts, feel free to comment, and this can be re-opened.

KennethanCeyer commented 5 years ago

@radarhere

You're the hero!

I will check the new version of Pillow and their result by build on your #3856 PR's source code as soon as possible


Yeah In this issue, The rtl option is not the main topic

Maybe that issue should be treated at another new issue

khaledhosny commented 5 years ago

The direction parameter sets the overall paragraph direction, the individual character's direction is determined by BiDi algorithm. Unicode bidi control characters can be to force text direction to be LTR or RTL and override the algorithm (though that is not usually something very useful todo, expect for ancient scripts that can be written in either direction or pseudo RTL localization strings).