PILを使用して円形の画像サムネイルを生成するにはどうすればよいですか?円の外側のスペースは透明でなければなりません。
スニペットをいただければ幸いです。よろしくお願いします。
それを行う最も簡単な方法は、マスクを使用することです。好きな形で白黒のマスクを作成します。 putalpha
を使用して、その形状をアルファレイヤーとして配置します。
from PIL import Image, ImageOps
mask = Image.open('mask.png').convert('L')
im = Image.open('image.png')
output = ImageOps.fit(im, mask.size, centering=(0.5, 0.5))
output.putalpha(mask)
output.save('output.png')
これが私が使ったマスクです:
サムネイルのサイズを可変にする場合は、ImageDraw
を使用してマスクを描画します。
from PIL import Image, ImageOps, ImageDraw
size = (128, 128)
mask = Image.new('L', size, 0)
draw = ImageDraw.Draw(mask)
draw.ellipse((0, 0) + size, fill=255)
im = Image.open('image.jpg')
output = ImageOps.fit(im, mask.size, centering=(0.5, 0.5))
output.putalpha(mask)
output.save('output.png')
GIFで出力する場合は、putalpha
の代わりに貼り付け関数を使用する必要があります。
from PIL import Image, ImageOps, ImageDraw
size = (128, 128)
mask = Image.new('L', size, 255)
draw = ImageDraw.Draw(mask)
draw.ellipse((0, 0) + size, fill=0)
im = Image.open('image.jpg')
output = ImageOps.fit(im, mask.size, centering=(0.5, 0.5))
output.paste(0, mask=mask)
output.convert('P', palette=Image.ADAPTIVE)
output.save('output.gif', transparency=0)
次の変更を行ったことに注意してください。
注意してください:このアプローチには大きな問題があります。 GIF画像に黒い部分が含まれている場合、それらのすべても透明になります。透明度に別の色を選択することで、これを回避できます。これにはPNG形式を使用することを強くお勧めします。しかし、それができない場合は、それが最善の方法です。
私はすでに受け入れられている回答に、結果の円をアンチエイリアスするソリューションを追加したいと思います。トリックは、より大きなマスクを作成し、ANTIALIASフィルターを使用してそれを縮小することです。ここにコードがあります
from PIL import Image, ImageOps, ImageDraw
im = Image.open('image.jpg')
bigsize = (im.size[0] * 3, im.size[1] * 3)
mask = Image.new('L', bigsize, 0)
draw = ImageDraw.Draw(mask)
draw.ellipse((0, 0) + bigsize, fill=255)
mask = mask.resize(im.size, Image.ANTIALIAS)
im.putalpha(mask)
これは私の意見でははるかに良い結果をもたらします。
すでに透過性のある画像もサポートするための@DRCのソリューションのわずかな変更。彼はアルファチャネルを円の外側で0(非表示)、内側で255(不透明)に設定しているので、マスクのminと元のアルファチャネル(_)を使用するdarker
を使用します( 0-255の間のどこでもかまいません):-)
from PIL import Image, ImageChops, ImageDraw
def crop_to_circle(im):
bigsize = (im.size[0] * 3, im.size[1] * 3)
mask = Image.new('L', bigsize, 0)
ImageDraw.Draw(mask).ellipse((0, 0) + bigsize, fill=255)
mask = mask.resize(im.size, Image.ANTIALIAS)
mask = ImageChops.darker(mask, im.split()[-1])
im.putalpha(mask)
im = Image.open('0.png').convert('RGBA')
crop_to_circle(im)
im.save('cropped.png')