【问题标题】:How do I generate circular thumbnails with PIL?如何使用 PIL 生成圆形缩略图?
【发布时间】:2010-10-27 18:21:08
【问题描述】:

如何使用 PIL 生成圆形图像缩略图? 圆圈外的空间应该是透明的。

非常感谢您提供片段,在此先感谢您。

【问题讨论】:

    标签: python thumbnails python-imaging-library geometry


    【解决方案1】:

    最简单的方法是使用掩码。创建具有您想要的任何形状的黑白蒙版。并使用 putalpha 将该形状作为 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')
    

    这是我使用的面具:


    如果您希望缩略图大小可变,可以使用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)
    

    请注意,我做了以下更改:

    • 面具现在被反转了。白色 被替换为黑色,反之亦然。
    • 我正在使用“自适应”调色板转换为“P”。否则,PIL 将只使用网络安全颜色,结果看起来很糟糕。
    • 我正在为图像添加透明度信息。

    请注意:这种方法存在一个大问题。如果 GIF 图像包含黑色部分,它们也会全部变为透明。您可以通过为透明度选择另一种颜色来解决此问题。 我强烈建议您为此使用 PNG 格式。但如果你不能,那是你能做的最好的。

    【讨论】:

    • 太棒了!那么输出 gif 而不是 png 又如何呢?我猜 gif 不处理 alpha,是吗?
    • Gif 不支持 Alpha 通道透明度。它只支持将一种颜色设置为透明。但是,我进行了必要的调整以将结果输出为 gif。
    • 很好的答案。虽然我可以轻松地将这种技术应用于保存的图像,但在 python 中应用蒙版时遇到了问题。你有机会看看这个问题:stackoverflow.com/questions/20150552/…
    • 对于任何寻找面具的人,请在谷歌图片上搜索“圆形面具 png”,黑色背景上的白色圆圈。
    【解决方案2】:

    我想在已经接受的答案中添加一个解决方案来消除产生的圆的锯齿,诀窍是产生一个更大的蒙版,然后使用 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)
    

    在我看来,这会产生更好的结果。

    【讨论】:

    • 老兄,ANTIALIAS 带来了巨大的变化!谢谢! =D
    • 这对我很有效。无需设计面具。
    • 有史以来最好的提示!
    • 如果图像在圆圈内已经具有透明度,则此方法不起作用
    【解决方案3】:

    对@DRC 的解决方案稍作修改,以支持已经具有透明度的图像。他将 alpha 通道设置为圆圈外的 0(不可见)和内部的 255(不透明),所以我使用 darker 获取蒙版的 min 和原始 alpha 通道(可以是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')
    

    【讨论】:

      【解决方案4】:

      非常感谢。我找了好几个小时,你的想法成功了。

      与那里的其他脚本一起。 PIL round edges and add border 它非常适合我。

      from PIL import Image
      from PIL import ImageDraw, ImageChops
      
      def add_corners( im, rad=100):
          circle = Image.new('L', (rad * 2, rad * 2), 0)
          draw = ImageDraw.Draw(circle)
          draw.ellipse((0, 0, rad * 2, rad * 2), fill=255)
          alpha = Image.new('L', im.size, "white")
          w, h = im.size
          alpha.paste(circle.crop((0, 0, rad, rad)), (0, 0))
          alpha.paste(circle.crop((0, rad, rad, rad * 2)), (0, h - rad))
          alpha.paste(circle.crop((rad, 0, rad * 2, rad)), (w - rad, 0))
          alpha.paste(circle.crop((rad, rad, rad * 2, rad * 2)), (w - rad, h - rad))
      
          alpha = ImageChops.darker(alpha, im.split()[-1])
      
          im.putalpha(alpha)
          return im
      
      im = Image.open ('AceOfSpades.png').convert('RGBA')
      
      im = add_corners (im, 24)
      
      im.show()
      im.save("perfect.png")
      

      Name this image AceOfSpades.png for testing

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-06-28
        • 1970-01-01
        • 2012-04-07
        • 1970-01-01
        • 2010-11-26
        • 2011-06-24
        • 2012-11-18
        相关资源
        最近更新 更多