single.php

Pythonで電子印鑑(ハンコ)の画像を描画する手順(其の四)

Pythonで利用できる画像ライブラリ[Pillow(PIL)]で画像に扁平させた文字を配置して背景透過をさせた電子印鑑(ハンコ)する手順を備忘録的に投稿しておきます。

Pillow(PIL)

Pythonで利用できるPillowは、画像に関する操作を行うライブラリで他のライブラリをインストールした際に、セットアップされている場合があります。

VSCodeの[ターミナル]画面などから次のコマンドで確認することができます。

pip show pillow

インストールされている場合にはバージョンなどの情報が表示されます。

インストールされていない場合には pip コマンドでインストールをしておきます。

pip install pillow

文字がはみ出した部分を非表示にする手順

先回、文字を描画した画像をリサイズさせて赤い丸に並べた画像を取得する手順を紹介しましたが、今回は文字の背景を透明にして印面(ハンコ)のような画像を作っていきます。

文字の背景を透過にするのは簡単ですが、文字の形で赤い枠からはみ出た部分をクリップ(非表示)にして透明化するのが難題になります。

実際には次のような手順で赤い枠からはみ出した部分をクリップして背景透過させていきます。

1. 背景が透過で文字と枠が黒色(グレースケール)の画像を用意します。

2. 背景を白色で塗りつぶした画像を用意します。

3. 白画像から非表示にする部分(赤い枠の外側)する画像を用意します。

4. グレースケール画像と非表示にする画像からマスク用の画像を用意します。

5. グレースケールと同じ配置のカラー画像を用意します。

6. 透明背景の画像を用意します。

7. カラー画像、透明背景の画像とマスク用の画像を合成します。

多少複雑な手順になりますが、マスク用の画像を用意することで赤い枠からはみ出た部分をクリップした背景透過の画像を作成することができます。

文字の背景を透過にする手順

実際にVSCodeを使って、はみ出た文字を非表示(クリップ)した印面画像を出力するには次の手順で行います。

1. VSCodeを起動しプロジェクト用のフォルダーを内に[transparent.py]ファイルを作成して次の関数を追加します。(後で使いやすいように関数化をしています)

from PIL import Image, ImageDraw, ImageFont

#扁平させた文字画像を作成
def flattext(moji, rasio, color):
    base_W, base_H = (320,320)
    if color == 'black':
        image = Image.new('L', (base_W, base_H), 'white')
    else:
        image = Image.new('RGBA', (base_W, base_H), (255, 255, 255, 0))

    d = ImageDraw.Draw(image)
    fontpath = "C:\Windows\Fonts\Meiryo.ttc"
    font = ImageFont.truetype(fontpath, 200)
    moji_W, moji_H = d.textsize(moji, font=font)
    d.text((0, 0 - (moji_H - moji_W)), moji, font=font, fill=color)
    image_crop = image.crop((0, 0, moji_W, moji_H))
    image_resize = image_crop.resize((moji_W, int(moji_H * rasio)))
    return image_resize, (moji_W, int(moji_H * rasio))

#文字画像を配置する
def getimage(moji, yohaku, color):
    base_W, base_H = (320,320)
    if color == 'black':
        base_image = Image.new('L', (base_W, base_H), 'white')
    else:
        base_image = Image.new('RGBA', (base_W, base_H), (255, 255, 255, 0))

    d = ImageDraw.Draw(base_image)
    rasio = 0.7
    image, (image_W, image_H) = flattext(moji[0], rasio, color)
    paste_W = int((base_W - image_W) / 2)
    paste_H = int(((base_H / 2) - image_H) / 2) + yohaku
    base_image.paste(image, (paste_W, paste_H))
    image, (image_W, image_H) = flattext(moji[1], rasio, color)
    paste_W = int((base_W - image_W) / 2)
    paste_H = int(((base_H / 2) - image_H) / 2) + int((base_H / 2)) - yohaku
    base_image.paste(image, (paste_W, paste_H))
    d.ellipse([(yohaku, yohaku), (base_W - yohaku, base_H - yohaku)], outline=color, width=6)
    return base_image, (base_W, base_H)

関数の細かな部分は、別記事をご覧ください。

2. 関数を呼び出すコードを[flattext.py]に追加します。

#画像に追加する余白
yohaku = 10

#グレースケール(黒)文字と黒い丸を描画した画像を作成
grayscale_image, (base_W, base_H) = getimage('印鑑', yohaku, 'black')

#白く塗りつぶした画像を作成
whiteback_image = Image.new("L", grayscale_image.size, 'white')

#非表示にする部分を黒くした画像を作成
waku_image = Image.new("L", grayscale_image.size, 0)
d = ImageDraw.Draw(waku_image)
d.ellipse([(yohaku, yohaku), (base_W - yohaku, base_H - yohaku)], fill=255)

#マスクに利用する画像を作成
mask_image = Image.composite(grayscale_image, whiteback_image, waku_image)

#カラー(赤)文字と赤い丸を描画した画像を作成
color_image, (base_W, base_H) = getimage('印鑑', yohaku, 'red') 

#背景が透明の画像を作成
transparent_image = Image.new("RGBA", color_image.size, (255,255,255,0))

#透明画像、カラー画像とマスク用の画像を合成
hanko_image = Image.composite(transparent_image, color_image, mask_image)

#取得した画像をファイルに保存
hanko_image.save('C:\\Datas\\Python\\drawtext\\output\\hanko_image.png')

最終的に[transparent.py]は次のようになります。

from PIL import Image, ImageDraw, ImageFont

def flattext(moji, rasio, color):
    base_W, base_H = (320,320)
    if color == 'black':
        image = Image.new('L', (base_W, base_H), 'white')
    else:
        image = Image.new('RGBA', (base_W, base_H), (255, 255, 255, 0))

    d = ImageDraw.Draw(image)
    fontpath = "C:\Windows\Fonts\Meiryo.ttc"
    font = ImageFont.truetype(fontpath, 200)
    moji_W, moji_H = d.textsize(moji, font=font)
    d.text((0, 0 - (moji_H - moji_W)), moji, font=font, fill=color)
    image_crop = image.crop((0, 0, moji_W, moji_H))
    image_resize = image_crop.resize((moji_W, int(moji_H * rasio)))
    return image_resize, (moji_W, int(moji_H * rasio))

def getimage(moji, yohaku, color):
    base_W, base_H = (320,320)
    if color == 'black':
        base_image = Image.new('L', (base_W, base_H), 'white')
    else:
        base_image = Image.new('RGBA', (base_W, base_H), (255, 255, 255, 0))

    d = ImageDraw.Draw(base_image)
    rasio = 0.7
    image, (image_W, image_H) = flattext(moji[0], rasio, color)
    paste_W = int((base_W - image_W) / 2)
    paste_H = int(((base_H / 2) - image_H) / 2) + yohaku
    base_image.paste(image, (paste_W, paste_H))
    image, (image_W, image_H) = flattext(moji[1], rasio, color)
    paste_W = int((base_W - image_W) / 2)
    paste_H = int(((base_H / 2) - image_H) / 2) + int((base_H / 2)) - yohaku
    base_image.paste(image, (paste_W, paste_H))
    d.ellipse([(yohaku, yohaku), (base_W - yohaku, base_H - yohaku)], outline=color, width=6)
    return base_image, (base_W, base_H)

yohaku = 10
grayscale_image, (base_W, base_H) = getimage('印鑑', yohaku, 'black')
whiteback_image = Image.new("L", grayscale_image.size, 'white')
waku_image = Image.new("L", grayscale_image.size, 0)
d = ImageDraw.Draw(waku_image)
d.ellipse([(yohaku, yohaku), (base_W - yohaku, base_H - yohaku)], fill=255)
mask_image = Image.composite(grayscale_image, whiteback_image, waku_image)
color_image, (base_W, base_H) = getimage('印鑑', yohaku, 'red') 
transparent_image = Image.new("RGBA", color_image.size, (255,255,255,0))
hanko_image = Image.composite(transparent_image, color_image, mask_image)
hanko_image.save('C:\\Datas\\Python\\drawtext\\output\\hanko_image.png')

3. 画像を保存するための[output]フォルダーを新しく作成します。

4. VSCodeの[ターミナル]画面で次のコマンドを実行します。

python transparent.py

5.[output]フォルダーに画像が保存されます。

赤い枠に縦横比が変更された文字が配置されて、文字が赤い枠からはみ出した場合には非表示になった画像が取得できました。

まとめ

Pythonで利用できる[Pillow]を利用して縦横比を変更した(横に伸ばした文字)を縦に並べて描画することで印面(ハンコ)のような画像を作成することができます。

少し複雑ですが、マスク画像を作成することで特定の場所から、はみ出した場合には非表示にする(クリップ)するして背景を透過にする操作をすることも可能です。

背景透過と枠からはみ出た部分を切り取ることで、印面に近い画像をPythonで作成することができます。

スポンサーリンク

最後までご覧いただき、ありがとうございます。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です