このページでは、Python の画像処理ライブラリ Pillow (PIL) を利用した「画像への透明な文字」の描画方法について解説していきます。
Contents
透明な文字の描画方法
では、早速透明な文字を描画する方法について解説していきます。
3つの手順を追加すればよいだけ
Pillow で文字列を描画する方法さえ知っていれば、その時の手順に下記の3つの手順を加えることで透明な文字を描画することが可能となります。画像をファイルとして保存する場合のみ③が必要で、画像を表示するだけで良い場合は③も不要になります。
- ①画像を
'RGBA'
形式に変換する - ②描画する文字の色の第4要素を
0
に設定する - ③文字描画後の画像を
.png
で保存する
画像への文字の描画自体は Pillow における ImgeDraw モジュールの text
メソッドを利用することで実現できます。画像への文字列の描画や text
メソッドについては下記ページでまとめていますので、詳しくは下記ページをご参照いただければと思います。
そして、普通に文字列を描画する時のスクリプトに上記の3手順を加えてやることで画像への透明な文字列の描画可能となります。
スポンサーリンク
画像への透明な文字を描画するスクリプト
下記は image.jpg
という画像に透明な文字列 ('Hello World!'
) を描画するスクリプトの例になります。
from PIL import Image, ImageDraw
image = Image.open('image.jpg')
image = image.convert('RGBA') # ①画像を 'RGBA' 形式に変換する
drawer = ImageDraw.Draw(image)
drawer.text(
xy=(image.width // 2, image.height // 2),
text='Hello World!',
fill=(0, 0, 0, 0), # ②描画する文字の色の第4要素を 0 に設定する
anchor='mm',
stroke_width=1,
font_size=40
)
# ③文字描画後の画像を .png で保存する
image.save('transparent_text.png')
text
メソッド実行時に指定している各種引数の意味合いについては、先ほども紹介した下記ページで解説していますので、詳しく知りたい方は下記ページをご参照いただければと思います。
透明な文字を描画した画像
例えば、image.jpg
が下記のような画像である場合、
上記のスクリプトを実行することで下の図のような画像が transparent_text.png
が保存されることになります。
次は保存された画像を開いてコピーし、例えばパワポなどに貼り付けてみましょう!そして、その画像を色のついた図形の上に配置してみると…
下の図のように、背景の色に応じて文字の色が変化することが確認できます。これは、描画した文字が透明であるため、背景の色が透けて見えていることを示しています(画像を図形よりも前面に配置しておかないと画像が隠れてしまうので注意してください)。
こんな感じで、Pillow を利用することで透明な文字の画像への描画を行うことができます。
3つの手順とスクリプトの対応
そして、透明な文字の画像への描画は、いつも画像に文字列を描画するときに比べて下記の3つの手順を追加するだけで実現できます。
- ①画像を
'RGBA'
形式に変換する - ②描画する文字の色の第4要素を
0
に設定する - ③文字描画後の画像を
.png
で保存する
先ほど示したスクリプトでコメントを記述していますが、①に関しては下記のように open
関数で生成した Image
オブジェクトに convert('RGBA')
を実行させることで実現できます。この①に関しては、Image
オブジェクト生成直後 ~ Draw
オブジェクト生成前に行えば良いです。
image = image.convert('RGBA')
また②に関しては、下記のように text
メソッドの fill
引数に指定するピクセル値の第4要素に 0
を指定することで実現できます。
drawer.text(
# 略
fill=(0, 0, 0, 0),
# 略
)
さらに③に関しては、下記のように save
メソッドの引数で指定するファイルパスの拡張子を .png
にするだけで実現できます。この③に関しては画像をファイルとして保存する際に必要な手順であり、ファイルとして保存しない場合、例えば save
メソッドで画像を表示するだけであれば不要な手順となります。
image.save('transparent_text.png')
そして、これらを行うことで、どんな画像に対しても透明な文字列が描画可能になります。
では、なぜ上記の3手順により透明な文字列が描画可能になるのでしょうか?
ここからは、オマケとして、上記の3手順を加えることで透明な文字列が描画されるようになる仕組みについて説明していきます。
スポンサーリンク
透明な文字が描画される仕組み
透明な文字の描画方法 で、通常の文字を描画する際の手順に対して下記の3つの手順を加えることで透明な文字が描画可能となることを説明しました。
- ①画像を
'RGBA'
形式に変換する - ②描画する文字の色の第4要素を
0
に設定する - ③文字描画後の画像を
.png
で保存する
②によって透明な色で文字が描画される
この3つの手順の中で、実際に文字の色を透明に設定しているのは②の手順になります。
Pillow で扱う色は色名の文字列やカラーコードの形式で指定することが可能ですが、ピクセル値によって色を指定することも可能です。画像にもよりますが、ピクセル値としては (R
, G
, B
) の3つの要素のタプルで指定するのが最も一般的で、R
で赤色の強さ、G
で緑色の強さ、B
で青色の強さを指定することになります。そして、これらの3色の色の強さによって最終的な色が決まり、その色で文字が描画されることになります。
さらに、特定の画像に対してはピクセル値を (R
, G
, B
) ではなく (R
, G
, B
, A
) の4つの要素のタプルで指定することが可能です。
A
は α
で表されることも多く、これらはアルファチャンネルと呼ばれます
そして、A
で色の透明度を指定することが出来ます。A
に関しては 0
~ 255
の値を指定することができ、値に応じた透明度が設定されることになります。値が小さいほど透明に近くなり、完全な透明にしたいのであれば A
に 0
を指定してやれば良いです。
下図は A
の値によって描画する文字の透明度が変化する様子を示しています。A = 0
の場合は完全に透明になるため背景の色がそのまま透けて見えますが、A
が大きくなると背景の色の透け度合いが小さくなっていくことが確認できると思います。
ここまでの説明のとおり、描画する文字の色を (R
, G
, B
, A
) の4つの要素のタプルのピクセル値として指定してやり、A
に 0
を指定してやれば透明な文字が描画されることになります。
①によって色に透明度を指定できるようになる
であれば、②の手順だけ行えば透明な文字の描画は実現できそうなものですが、実はそうではありません。
実はピクセル値に透明度が設定可能な画像は限定されているのです。なので、文字の描画先の画像が透明度を設定可能なものでない場合、色に透明度は設定することはできず、当然透明な文字の描画も実現できないことになります。
mode
と透明度の設定の関係
そして、色を表すピクセル値として指定可能な形式は、Pillow においては Image
オブジェクトの mode
によって決まります。この mode
やピクセル値に関しては下記ページで詳しく説明していますので、興味があれば読んでみてください。
mode
の代表例の1つは 'RGB'
となります。mode
が 'RGB'
の場合、その Image
オブジェクトではピクセル値が (R
, G
, B
) の3つの要素のみのタプルの形式で扱われることになります。したがって、この Image
オブジェクトでは透明な色を設定することが出来ません。それに対し、mode
の代表例の1つに 'RGBA'
があります。この場合、その Image
オブジェクトではピクセル値が (R
, G
, B
, A
) の4つの要素のタプルの形式で扱われることになります。そして、この mode
が 'RGBA'
の Image
オブジェクトでは透明な色を設定することが可能です。
例えば、先ほど示した下図の画像のファイルパスを image.jpg
とした時、
下記によって image.jpg
を読み込んで Image
オブジェクトが生成されることになります。そして、この Image
オブジェクトのデータ属性 mode
を出力してみると RGB
と出力されるはずです。
from PIL import Image
image = Image.open('image.jpg')
print(image.mode) # RGBが出力される
これは「この画像のピクセル値は (R
, G
, B
) の3つの要素のタプルの形式であること」を示しています。そして、前述のとおり mode
が 'RGB'
の場合は透明度は設定不可です。つまり、mode
が 'RGB'
となっている Image
オブジェクトに対し、色を (R
, G
, B
, A
) の4つの要素のタプルのピクセル値を指定して文字を描画したとしても A
の要素は無視されることになります。
じゃあ、なぜ上記のスクリプト例によって生成された Image
オブジェクトの mode
が 'RGB'
なのかというと、それは open
関数の第1引数で指定されたファイルパスの画像、すなわち、先ほど紹介した下図の画像の mode
が 'RGB'
だからになります。つまり、open
関数で Image
オブジェクトを生成する場合、第1引数で指定したファイルパスの画像によって生成される Image
オブジェクトの mode
も決まることになります。さらに言えば、JPEG 画像などは透明度が設定不可な画像フォーマットととなります。したがって、open
関数の第1引数に JPEG ファイルのパスを指定すると、open
関数によって生成された Image
オブジェクトに対しては基本的には透明な文字は描画不可となります。
mode
の変換
じゃあ、JPEG 画像に透明な文字を描画することが絶対に不可能なのかというと実はそうではありません。正確に言えば、やっぱり JPEG 画像に透明な文字を描画することはできません。これは、JPEG 画像から生成される Image
の mode
が基本的に 'RGB'
となるからになります。
なんですが、実は Pillow の Image
クラスには convert
メソッドが用意されており、この convert
メソッドにより mode
を変換することが可能となります。前述のとおり、mode
が 'RGBA'
の場合はピクセル値が (R
, G
, B
, A
) の4つの要素のタプルの形式で扱われることになり、A
の値によって透明度が設定可能です。
したがって、Image
オブジェクトの mode
が 'RGB'
であっても、convert
メソッドにより mode
を 'RGBA'
に変換してやれば透明度が設定可能なピクセル値を色として指定することができるようになり、その後に②の手順で透明な文字を画像に描画することが可能となります。
つまり、①の手順で行っているのは、open
関数によって生成した Image
オブジェクトの mode
が 'RGBA'
以外の場合でも、透明度が扱えるように 'RGBA'
に変換する処理を行っています。そして、これによって②の手順で透明な文字が描画することができるようになります。
ちなみに、JPEG 画像では透明度を扱うことが出来ず、JPEG 画像から open
関数で生成した Image
オブジェクトの mode
が 'RGBA'
になることは無いはずです。それに対し、PNG 画像は透明度を扱うことが可能で、画像によっては PNG 画像から open
関数で生成した Image
オブジェクトの mode
が 'RGBA'
となることがあります。この場合、convert
メソッドによる mode
の 'RGBA'
への変換を行わなくても透明な文字の描画が可能となります。
補足しておくと、JPEG 画像ではグレースケール画像や CMYK 画像も扱うことが可能であり、これらの画像から生成される Image
の mode
は、それぞれ 'L'
・'CMYK'
となります
が、このページでは最も一般的な 'RGB'
であることを前提に解説しています
ちなみに、mode
が 'L'
の場合も 'CMYK'
の場合も透明度の扱いは不可となっています
convert
以外での変換
先ほど透明度を扱うために convert
メソッドで Image
オブジェクトの mode
を 'RGBA'
に変換する必要があると説明しましたが、透明度を扱うための手段は他にもあって、その1つとして putalpha
メソッドの実行が挙げられます。この putalpha
メソッドを実行した Image
オブジェクトの各ピクセルにはアルファチャンネルが追加されます。つまり、各ピクセルの元々のピクセル値に要素が1つ追加され、その追加された要素で透明度を扱うことが出来るようになります。
具体的に言えば、mode
が 'RGB'
の Image
オブジェクトの場合はピクセル値が (R
, G
, B
) の3つの要素から構成されますが、この Image
オブジェクトに putalpha
メソッドを実行させればピクセル値に A
が追加されて (R
, G
, B
, A
) の4つの要素から構成されるようになります。この A
では、前述のとおり透明度を指定することが可能です。また、ピクセル値の構成は mode と連動しており、putalpha
メソッドの実行によってピクセル値が (R
, G
, B
, A
) の4つの要素から構成されるようになることで mode
も 'RGBA'
に自動的に変換されることになります。
そして、これによって透明な文字を描画可能な Image
オブジェクトに変換されることになります。
したがって、透明な文字の描画方法 で紹介したスクリプトにおける下記の convert
メソッド実行部分を
image = image.convert('RGBA')
下記のように putalpha
メソッドの実行に置き換えたとしても透明な文字は描画可能となります。
image.putalpha(255)
putalpha
は実行したオブジェクトそのものが変化するメソッドであることに注意してください。convert
メソッドの場合は実行したオブジェクトは変化せず、mode
を変換した後の Image
オブジェクトが新たに生成されて返却されることになります。putalpha
の場合は実行したオブジェクトが変化し(A
が追加される)、返却値は None
となります。
また、追加された A
の値は画像内の全ピクセルにおいて putalpha
の引数で指定した整数の値となります。上記の例では 255
を指定しており、255
は不透明であることを指定する値であるため画像内の全ピクセルは不透明で元々の色を保持することになります。逆に 0
を指定した場合は画像全体が透明になることになります。今回は描画する文字だけを透明とすることを目的としているため 255
を指定していますが、画像全体を半透明などにしたいような場合は 128
などの中間値を指定しても良いです。
もともと mode
が 'RGBA'
の Image
オブジェクトの場合は、putalpha
の実行によって全ピクセルの A
の値が putalpha
の引数に指定した値に置き換えられてしまうことになるので注意してください。
スポンサーリンク
③によって透明度が設定可能なフォーマットで保存される
さて、①と②によって透明な文字を画像に描画することが出来るようになったことになります。
では、すでに透明な文字を描画できているのに、なぜ③が必要なのでしょうか?
これは、透明度が設定可能な画像フォーマットでファイル保存するためになります。
Image
オブジェクトの save
メソッドで画像をファイル保存する際には、Image
オブジェクトが特定の画像フォーマットに変換された状態でファイルに保存されることになります。有名な画像フォーマットには JPEG や PNG 等があります。そして、どのフォーマットに変換されるかは save
メソッドの第1引数のファイルパスにおける拡張子(.jpg
や .png
など)によって決まります。
この時に注意が必要なのは、画像フォーマットには透明度の設定に対応していないものがあるという点になります。そして、mode
が 'RGBA'
の Image
オブジェクトから save
メソッドでファイル保存する際、透明度の設定が不可な画像フォーマットに変換されてしまうと例外が発生することになります。例えば、JPEG は透明度が設定不可な画像フォーマットであるため、mode
が 'RGBA'
の Image
オブジェクトから save
メソッドを実行させる際に第1引数のファイルパスの拡張子が .jpg
になっていると、JPEG は透明度の設定に対応していないため例外が発生します。
具体的には、下記のような例外が発生すると思います。
OSError: cannot write mode RGBA as JPEG
このような例外を防ぐためには、 save
メソッドの第1引数には透明度の設定が可能なフォーマットに対応する拡張子のファイルパスを指定する必要があります。そして、透明度の設定が可能なフォーマットの代表例の1つは PNG であり、.png
の拡張子のファイルパスを指定してやれば例外を防ぐことが出来るようになります。そして、これが手順の③となります。
他にも透明度が設定可能なフォーマットは存在するのですが、一番ポピュラーなのは PNG だと思いますので、特にファイルをより小さくしたい等の特別な理由がなければ .png
の拡張子のファイルパスを指定してやれば良いと思います。
以上が、透明な文字が描画される仕組みの説明となります。描画する文字の色に透明度を含めたピクセル値を指定すること、および、透明度を扱うことが可能な mode
に変換し、さらに透明度が保持されるような画像フォーマットでファイル保存する必要がある点がポイントになると思います!
まとめ
このページでは、Python の画像処理ライブラリ Pillow (PIL) を利用した「画像への透明な文字」の描画方法について解説しました!
通常の Pillow を利用した画像への文字の描画時のスクリプトを下記の3つの手順を行うように変更してやることで画像への透明な文字の描画を実現することが出来ます。
- ①画像を
'RGBA'
形式に変換する - ②描画する文字の色の第4要素を
0
に設定する - ③文字描画後の画像を
.png
で保存する
実際に透明な文字を描画するのは②になりますが、②で透明な文字を描画するために①が、②で透明な文字を描画した画像をファイルとして保存するために③が必要な手順となります。
透明な文字の描画手順を理解することで、目的となる透明な文字の描画を実現することは当然できますし、それだけでなく Pillow での画像の mode についての理解も深まると思います。是非このページで開設した内容は覚えておきましょう!
また、このサイトでは Pillow での文字の描画に関するページを他にも公開しておりますので、是非これらのページも読んでみていただければと思います!
【Python/Pillow】画像に文字列を描画する(textメソッド) 【Pillow/Python】textメソッドで描画する文字のフォントやサイズを変更する 【Pillow/Python】textメソッドで描画した文字列が文字化けする問題の解決方法