The benefits of PNGs are obvious: it’s lossless and it supports transparency (alpha).
Unfortunately, that means these files are humongous. As PNGs get more complex, every pixel gets recorded so a product shot might be 1000KB as PNG, and 50KB as a JPEG looking not all that much worse.
If you try to convert a PNG to a JPEG via Sorl thumbnail library, it will by default use a white background, and for some reason causes artifacting as well on partial alphas such as shadows.
Ideally, we have a super high quality PNG that can be converted and optimized to a JPG on the fly, so I created a PIL sorl thumbnail engine that accepts a new template tag argument: “background” – which is an RGB color that will be applied as the background color to an RGBA image source.
Apparently, my solution is the simplest, and fastest of the RGBA->JPG methods described at this stack overflow question.
The Code: Converting Transparent PNGs to JPEGs with Background Colors
"""
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
Now, just modify your thumbnail engine setting
THUMBNAIL_ENGINE = 'path.to.Engine'
Usage
{% thumbnail my_file "100x100" format="JPEG" background="#333333" as thumb %}
<img src="{{ thumb.url }}" />
{% endthumbnail %}
Done!
Conclusion
Now, we can store/upload one copy of a perfect PNG and have the website automatically generate an optimized JPEG regardless of the situation. Seriously amazing.
Need a smaller PNG? done.
Need a smaller JPEG with background color black? done.
3 Comments