The easiest way to do this is to use masks. Create a black and white mask with any shape you want. And use putalpha to put this shape as an alpha layer:
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')
Here is the mask I used:

If you want the thumbnail size to be variable, you can use ImageDraw and draw a mask:
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')
If you want output in GIF, you need to use the insert function instead of 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)
Please note that I made the following changes:
- The mask is now upside down. White has been replaced by black and vice versa.
- I convert to "P" with an "adaptive" palette. Otherwise, PIL will only use web-safe colors, and the result will look bad.
- I am adding transparency information to the image.
Please note : there is a big problem with this approach. If the GIF image contains black parts, all of them will also become transparent. You can get around this by choosing a different color for transparency. I highly recommend you use the PNG format for this. But if you cannot, then this is the best you can do.