LoginSignup
6

More than 3 years have passed since last update.

Pillowを日本語縦書きに対応させる

Last updated at Posted at 2018-10-10

(追記 2019.12.14)

Pillowは少なくとも Ver6以降(+raqmの0.7以降)で日本語縦書きが可能になっています。
本記事の内容は古いものなのでご注意下さいませ。

前置き

ずいぶん前に以下の記事を投稿しました。

テキストデータから小説体の縦書き画像を生成する

xmlで記述したテキストから、日本語の縦書き画像を生成するというものです。記事を書いた時点ではPillowが縦書きの文字描画に対応していなかったので、フォントファイルに手を加えて強制的に縦書き用のグリフを描画する事で縦書き描画をしていました。

その後、Pillowはバージョンがあがり、4.2.0で、テキストの描画方向を指定できるようになりました。ところが、いざ試してみると全く正しく動作しません。Pillowのコードを調べてみると、実際にはy_advanceの値を考慮しておらず縦書きに全く対応していませんでした。

修正してみる

というわけで、forkして、手元で修正をしてみました。
https://github.com/masushin/Pillow

from PIL import Image, ImageDraw, ImageFont

txt = Image.new('RGBA', (200,300), (215,215,220,255))
fnt = ImageFont.truetype("GenEiKoburiMin-R.otf", 24, layout_engine=ImageFont.LAYOUT_RAQM)
d = ImageDraw.Draw(txt)
d.multiline_text((120,20), "パパの動かす車なんて、\nあぶなくてのれますか。", spacing=24, font=fnt, fill=(0,0,0,255), direction="ttb")
txt.show()

このコードで、以下の画像が表示されます。ちゃんと縦書きのグリフが使われていますね。
tmpzek65m96.png

修正の概要

ほぼ自分向けの備忘録になりますが、

glyph_image.png

freetypeからはbounding box(グリフを含む最小矩形)に相当するサイズのビットマップデータが得られます。これを1文字毎に、Pillowのイメージ上の適切な位置に転送していく必要があります。
PillowのAPIから指定された描画始点を上図でのorigin(黒の四角点)であるとすると、raqmライブラリから得られる水平オフセット位置(x_offset)から、bounding boxの最小x(xMin)だけ正方向に位置するのがグリフの左端位置になります。
また、originからascender値だけ下方向に水平のベースラインがあるのでここから、bouding boxの最大yだけ上方向に位置するのがグリフ上端としました。
グリフを上端からグリフの高さ(height)だけビットマップを転送します。
次の文字を描画するには、originをy_advanceだけ加算して、次の文字の描画基準となるoriginを求め、以降同様の処理を行ないます。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6