How do I generate circular image thumbnails using PIL? The space outside the circle should be transparent.
如何使用PIL生成圆形图像缩略图?圆圈外的空间应该是透明的。
Snippets would be highly appreciated, thank you in advance.
片段将受到高度赞赏,谢谢你提前。
2 个解决方案
#1
64
The easiest way to do it is by using masks. Create a black and white mask with any shape you want. And put that shape as an alpha layer
最简单的方法是使用面具。使用您想要的任何形状创建黑白面具。并将该形状作为alpha层
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 the ImageDraw and draw the mask.
如果希望缩略图大小可变,可以使用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')
If you want the output in GIF then you need to use the paste function instead of putalpha:
如果你想在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)
Note that I did the following changes:
请注意,我做了以下更改:
- The mask is now inverted. The white was replace with black and vis-versa.
- 面具现在倒置了。白色用黑色代替,反之亦然。
- I'm converting into 'P' with an 'adaptive' palette. Otherwise PIL will only use web-safe colors and the result will look bad.
- 我正在使用'自适应'调色板转换为'P'。否则PIL将只使用Web安全颜色,结果看起来很糟糕。
- I'm adding transparency info with to the image
- 我正在为图像添加透明度信息
Please note: There is a big issue with this approach. If the gif image contained black parts, all of them will become transparent as well. You can work around this by choosing another color for the transparency. I would strongly advice you to use PNG format for this. But if you can't then that is the best you could do.
请注意:这种方法存在很大问题。如果gif图像包含黑色部分,则所有这些部分也将变为透明。您可以通过为透明度选择另一种颜色来解决此问题。我强烈建议你使用PNG格式。但如果你不能那么那就是你能做的最好的事情。
#2
23
I would like to add to the already accepted answer a solution to antialias the resulting circle, the trick is to produce a bigger mask and then scale it down using an ANTIALIAS filter: here is the code
我想在已经接受的答案中添加一个解决方案来解决生成的圆圈,诀窍是生成一个更大的掩码,然后使用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)
this produces a far better result in my opinion.
在我看来,这会产生更好的结果。
#1
64
The easiest way to do it is by using masks. Create a black and white mask with any shape you want. And put that shape as an alpha layer
最简单的方法是使用面具。使用您想要的任何形状创建黑白面具。并将该形状作为alpha层
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 the ImageDraw and draw the mask.
如果希望缩略图大小可变,可以使用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')
If you want the output in GIF then you need to use the paste function instead of putalpha:
如果你想在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)
Note that I did the following changes:
请注意,我做了以下更改:
- The mask is now inverted. The white was replace with black and vis-versa.
- 面具现在倒置了。白色用黑色代替,反之亦然。
- I'm converting into 'P' with an 'adaptive' palette. Otherwise PIL will only use web-safe colors and the result will look bad.
- 我正在使用'自适应'调色板转换为'P'。否则PIL将只使用Web安全颜色,结果看起来很糟糕。
- I'm adding transparency info with to the image
- 我正在为图像添加透明度信息
Please note: There is a big issue with this approach. If the gif image contained black parts, all of them will become transparent as well. You can work around this by choosing another color for the transparency. I would strongly advice you to use PNG format for this. But if you can't then that is the best you could do.
请注意:这种方法存在很大问题。如果gif图像包含黑色部分,则所有这些部分也将变为透明。您可以通过为透明度选择另一种颜色来解决此问题。我强烈建议你使用PNG格式。但如果你不能那么那就是你能做的最好的事情。
#2
23
I would like to add to the already accepted answer a solution to antialias the resulting circle, the trick is to produce a bigger mask and then scale it down using an ANTIALIAS filter: here is the code
我想在已经接受的答案中添加一个解决方案来解决生成的圆圈,诀窍是生成一个更大的掩码,然后使用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)
this produces a far better result in my opinion.
在我看来,这会产生更好的结果。