62
57

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

nana musicAdvent Calendar 2018

Day 19

Pythonで画像を編集したり、文字を入れたりする

Posted at

はじめに

nana musicでサーバサイドエンジニアをやっている@xKxAxKxです
この記事はnana music Advent Calendar 2018の19日目の記事です

nanaのTwitterカードの画像が変更されたぞ!

nanaのサウンドへのリンクをTwitterに投稿した時、以前は投稿ユーザのアイコンが表示されているだけだったんだけど、以下のように投稿ユーザのアイコン、再生ボタン画像、投稿パート毎の背景色画像、投稿楽曲タイトル、投稿楽曲アーティスト名、投稿ユーザ名の組み合わせで画像を生成し、それがTwitterカードの画像として使用されるようになった
スクリーンショット 2018-12-13 16.35.01.png
画像ファイルを色々といじるの、割とカジュアルにやることができたので、どのような処理をやっているかについて書いていく

用意するもの

アイコン画像

いらすとや様から借りた
中二病(厨二病)の女の子が自分で考えたかっこいいポーズを取っているイラストです
image.png

再生ボタン画像

はい
背景は透過になっている
image.png

パート毎の画像

ベースとなる画像
この画像に対してアイコン画像を貼っていったり、文字を入れたりする
今回はギターパートを投稿した場合の画像です
935.png

その他必要なもの

  • Python3系(実際の環境は3.6.5)
  • 画像を生成するぞ、という気持ち(重要)

手順

各種ライブラリのインストール

Pythonの画像処理ライブラリ Pillow をインストールする
公式ドキュメントはこちら

$ pip install Pillow

再生ボタン画像とアイコンを合成する

まずは再生ボタン画像と、アイコンをそれぞれ Image.open() でpath/urlから画像データとして読み込みを行う

画像データの読み込み
from PIL import Image

play_path = '再生ボタン画像のpath/url'
play = Image.open(play_path).copy()

icon_path = 'アイコンのpath/url'
icon = Image.open(icon_path).copy()

次にアイコン画像を適切なサイズに縮小する
nanaでは全てのアイコン画像は正方形で保存されているので以下の処理だけでいいけれどp、仮に正方形じゃない画像を扱う場合だと、画像を正方形にトリミングしないと、縦横比が変な画像になってしまう

アイコンの縮小
icon = icon.resize(size=(252, 252), resample=Image.ANTIALIAS)

resize関数で resample=Image.ANTIALIAS というように指定しておかないと、大きい画像を縮小する時にジャギジャギしたような感じに処理されてしまう

最後に再生ボタンとアイコンの合成
アイコンに再生ボタンを貼り付けるという、イメージ

合成
icon.paste(play, (51, 51), play)

第一引数が貼り付ける画像
第二引数が左端からのwidth/height
第三引数がマスクとなる画像を指定
今回の場合、再生ボタン画像は円形の背景透過であるため、透過部分がそのままマスクとなる

これにより以下のような画像が生成される
image.png

アイコンを円形に切り出し、背景を透過にする

Twitterカードの画像を見てもらえばわかるとおり、アイコンは円形で貼り付けられているのでアイコンを円形に切り出して、背景をとうかにするひつようがある

まずは、円形に切り取るためのマスクを生成する

マスクの生成
from PIL import ImageDraw

mask = Image.new("L", icon.size, 0)
draw = ImageDraw.Draw(mask)
draw.ellipse((0, 0, icon.size[0], icon.size[1]), fill=255)
mask = mask.filter(ImageFilter.GaussianBlur(1))

これにより以下のようなアイコンの画像のサイズに合わせた円形で、背景が透過の画像が生成される
mask.png

このマスクを putalpha() を使ってアイコン+再生ボタンの画像にかぶせる

アイコンを円形の透過画像にする
icon.putalpha(mask)

白背景なので分かりづらいけれど、以下のような画像となる
image.png

背景画像にアイコンを貼り付ける

ここは非常に簡単で、アイコンと再生ボタンの合成と同じ要領でやるだけで良い

base_image_path = '背景画像のpath/url'
base_img = Image.open(base_image_path).copy()
base_img.paste(icon, (80, 134), icon)

結果、以下のような画像が生成される
new.png

文字の入力

最後に文字を入力していく
ここは、まずは文字を入力するための関数で説明していきたい

画像に文字を入れる関数
from PIL import ImageFont

def add_text_to_image(img, text, font_path, font_size, font_color, height, width, max_length=740):
    position = (width, height)
    font = ImageFont.truetype(font_path, font_size)
    draw = ImageDraw.Draw(img)
    if draw.textsize(text, font=font)[0] > max_length:
        while draw.textsize(text + '', font=font)[0] > max_length:
            text = text[:-1]
        text = text + ''

    draw.text(position, text, font_color, font=font)

    return img

第1引数に画像データ
第2引数に入れる文字列
第3引数に使用するフォントのpath
第4引数に文字の大きさ
第5引数に文字の色
第6、第7引数にそれぞれ、文字を入れる位置
第8引数に文字列の最大の長さ
引数が多い関数だけれど、このような感じ

文字列の長さがmax_lengthを超えた場合は以下省略する、という感じになっている

最後にImageクラスの text() で文字入力を行なっていく

この関数を以下のようにそれぞれ呼び出していく

文字の入力やっていき
song_title = "There Is A Light That Never Goes Out"
font_path = "フォントファイルのpath"
font_size = 57
font_color = (255, 255, 255)
height = 155
width = 380
img = add_text_to_image(base_img, song_title, font_path, font_size, font_color, height, width)

song_artist = "The Smiths"
font_path = "フォントファイルのpath"
font_size = 40
font_color = (255, 255, 255)
height = 244
width = 380
img = add_text_to_image(base_img, song_artist, font_path, font_size, font_color, height, width)

user_name = 'by xKxAxKx'
font_path = "フォントファイルのpath"
font_size = 40
font_color = (20, 23, 26)
height = 328
width = 380
img = add_text_to_image(base_img, user_name, font_path, font_size, font_color, height, width)

img.save('ファイルのパス')

すると、実際に使用しているtwitterカードの画像のようになる
new.png

最後に

実際は様々な部分を関数化したり、アイコン画像に対しても処理を追加したりしている
また、絵文字対応なども行なったりしているんだけれど、ざっとした流れとしては以上のような感じになっている

自分自身、Pythonで画像をどうのこうのする、という経験がほとんどなかったのだが、何かと需要はありそうではあるし、視覚的に成果が見えやすいのでやってて楽しかったっす

参考リンク

62
57
0

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
62
57

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?