もがき系プログラマの日常

もがき系エンジニアの勉強したこと、日常のこと、気になっている技術、備忘録などを紹介するブログです。

Pythonで縦書き文字を画像合成してみた

参考サイト

PIL 1.1.7 で日本語縦書き描画を頑張る

前書き

こんにちは。

最近phpよりpython触ってる僕です。

php案件もそうですが、python案件やってみたい今日このごろです。

今回は仕事で、縦書きの文字の画像合成を携わったので記事にしておきます。

正直参考サイトに乗せていることをやっただけなので、参考サイトの記事を拝見すれば全てわかってしまいますが、とりあえず自分のために乗せておきます。

ちなみに参考サイトの記事は非常に分かりやすい内容でした。

自分の拙い文章で伝わらない場合は是非参考サイトの記事をご覧ください。

縦書きフォント作成

参考サイトで紹介されているサブセットフォントメーカーShift JIS に含まれる文字の一覧を使用して、縦書きフォントを作成します。

1. サブセットフォントメーカを起動

コチラからダウンロードして、起動します。

f:id:kojirooooocks:20180219224316p:plain

2. 作成元フォントファイルを指定

今回は「インストール済みフォントを参照」を選択します。

f:id:kojirooooocks:20180219224352p:plain

選択すると以下のような選択できる表示になります。

今回はこの中から凸版文久明朝 Regulerを選択します。

f:id:kojirooooocks:20180219224435p:plain

3. 作成後フォントファイルを指定

保存先ファイルのパスを指定します。

4. フォントに格納する文字を指定

以下のように、指定フィールドに、コチラの「Shift JIS に含まれる文字の一覧」の中身をコピペします。

f:id:kojirooooocks:20180219224646p:plain

5. 文字組方向を選択

縦書きで指定します。

6. 作成開始

作成開始ボタンを実行すると、すぐに作成されます。

f:id:kojirooooocks:20180219224714p:plain

縦書き用スクリプト作成

下準備としてpythonの画像処理ライブラリであるPillow(PIL)をインストールします。

$ pip install pillow

で、スクリプトは以下の感じです。

function.py

# coding: utf-8
from PIL import ImageFont, ImageDraw

def draw_text(frame_image, font_size, font_file_path, target_string, draw_start_x, draw_start_y, font_color='#ffffff'):
    """
    テキストの縦書き描画
    :param frame_image        Image:  フレームのImageオブジェクト
    :param font_size          int:    フォントサイズ
    :param font_file_path     string: OTFファイルまでのパス
    :param target_string      string: 対象の文字列
    :param draw_start_x       int:    描画開始位置_X
    :param draw_start_y       int:    描画開始位置_Y
    :param font_color         string: 描画する文字の色 (デフォルト: "#000000")
    """

    # 描画用データを取得
    draw = ImageDraw.Draw(frame_image)

    # フォントデータを取得
    image_font = ImageFont.truetype(font_file_path, font_size)

    # 各文字の描画管理変数
    ix, iy = 0, 0

    for c in target_string:
        x = draw_start_x - ix * font_size
        y = draw_start_y + (iy * font_size)

        # 今回描画する1文字の詳細なX, Yを設定
        char_width, char_height = image_font.getsize(c)
        x += (font_size - char_width) / 2
        y += draw_start_y

        # 指定の場所へ文字を描画
        draw.text((x, y), c, font=image_font, fill=font_color)

        # 次の文字へ
        iy += 1

    return True

main.py

# coding: utf-8
from PIL import Image
from function import draw_text
import sys

############################ Strat 各変数の宣言

# 引数から文字を受け取る
TARGET_STRING = sys.argv[1]

# otfファイルまでのパス
OTF_FILE_PATH = 'font.otf'

# 出力用ファイルまでのパス
OUTPUT_FILE_PATH = 'tmp/' + 'output.jpg'

# 元画像ファイルまでのパス
FRAME_FILE_PATH  = 'image.jpg'

############################ End 各変数の宣言

# 元画像データを取得
image_data = Image.open(FRAME_FILE_PATH)

# 文字合成
font_size          = 80
draw_start_x       = 60
draw_start_y       = 20
draw_text(image_data, font_size, OTF_FILE_PATH, TARGET_STRING, draw_start_x, draw_start_y)

# 合成した画像の書き出し
image_data.save(OUTPUT_FILE_PATH)
image_data.show();

本来は指定文字で改行とか、文字間・行間も指定できるようにしていたのですが、今回はテストということで簡素にしました。

以下で実行します。

$ python main.py "餌をください"

出来上がった画像が以下です。

f:id:kojirooooocks:20180219224743j:plain

 終わりに

おもしろかったー。

PHPのGDやImageMagickとかを使うより速度早い感じがあるのですが、どうなんですかね?

その辺も今度比べてみたいな。。

あ、簡単なものですが、今回のものはgithubにあげときます。

pillow_draw_text_sample

とりあえず今日はこれまで。

お疲れ様でした。

追記

以下の記事で、このプログラムをクラス化しました。

それにともない、githubの内容も変わっています。

kojirooooocks.hatenablog.com