透明的PNG图片在被转换后失去了透明度(Django + PIL)

11

我在 Web 服务器上使用 sorl-thumbnailPILDjango 动态创建模板缩略图。

PIL 安装了 PNG 支持,但由于某种原因,转换过程会在图像的透明部分产生一些奇怪的伪影。

我使用了这个代码片段来安装所需的依赖项:https://raw.github.com/gist/1225180/eb87ceaa7277078f17f76a89a066101ba2254391/patch.sh

这是生成图像的模板代码(我不认为问题出在这里,但展示一下也无妨):

{% thumbnail project.image "148x108" crop="center" as im %}
  <img src='{{ im.url }}' />
{% endthumbnail %}

以下是发生的情况的示例。非常感谢任何帮助!

之前

带有透明度的图像

之后

含有伪影的图像


你使用的是哪个sorl-thumbnail后端? - jterrace
3个回答

25

看起来你的生成图像是JPEG格式。JPEG格式不支持透明度。尝试将缩略图模板更改为以下内容:

{% thumbnail project.image "148x108" crop="center" format="PNG" as im %}

6
要么:
  • 添加format='PNG'
  • 在设置中添加THUMBNAIL_PRESERVE_FORMAT=True
  • 或者按照此处描述的方法使用自定义引擎:

http://yuji.wordpress.com/2012/02/26/sorl-thumbnail-convert-png-to-jpeg-with-background-color/

"""
Sorl Thumbnail Engine that accepts background color
---------------------------------------------------

Created on Sunday, February 2012 by Yuji Tomita
"""
from PIL import Image, ImageColor
from sorl.thumbnail.engines.pil_engine import Engine


class Engine(Engine):
    def create(self, image, geometry, options):
        thumb = super(Engine, self).create(image, geometry, options)
        if options.get('background'):      
            try:
                background = Image.new('RGB', thumb.size, ImageColor.getcolor(options.get('background'), 'RGB'))
                background.paste(thumb, mask=thumb.split()[3]) # 3 is the alpha of an RGBA image.
                return background
            except Exception, e:
                return thumb
        return thumb

在您的设置中:
THUMBNAIL_ENGINE = 'path.to.Engine'

现在您可以使用这个选项:
{% thumbnail my_file "100x100" format="JPEG" background="#333333" as thumb %}
   <img src="{{ thumb.url }}" />
{% endthumbnail %}

2
THUMBNAIL_PRESERVE_FORMAT=True 似乎是最简单的方法。 - Silver Light
format='PNG' 对我有用...一旦我记得禁用浏览器缓存,这样我的之前失败的上传尝试就不会一直出现了。 - user984003

1
我建议你看一下sorl的PIL后端如何处理缩放。我想它会创建一些辅助图像来应用其他效果,然后告诉PIL将原始图像缩放到该图像上。你需要确保目标使用RGBA模式来支持透明度,并且它的alpha值为零(而不是纯白色或暗黑色等类似的颜色)。如果你的图像使用索引调色板,则可能不会被转换为RGBA。在索引模式下,PNG文件会在元数据中存储透明颜色索引,但是由于抗锯齿处理,创建缩略图的过程会改变像素,因此无法保留索引透明度。
source = Image.open('dead-parrot.png')
source.convert('RGBA')
dest = source.resize((100, 100), resample=Image.ANTIALIAS)
dest.save('ex-parrot.png')

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接