[ADD] tools.image_save_for_web() helper for image compression
authorFabien Meghazi <fme@openerp.com>
Mon, 8 Sep 2014 13:53:02 +0000 (15:53 +0200)
committerFabien Meghazi <fme@openerp.com>
Tue, 16 Sep 2014 17:55:00 +0000 (19:55 +0200)
addons/website/models/website.py
openerp/tools/image.py

index a339bcb..983d419 100644 (file)
@@ -25,7 +25,7 @@ except ImportError:
 
 import openerp
 from openerp.osv import orm, osv, fields
-from openerp.tools import html_escape as escape, ustr, image_resize_and_sharpen
+from openerp.tools import html_escape as escape, ustr, image_resize_and_sharpen, image_save_for_web
 from openerp.tools.safe_eval import safe_eval
 from openerp.addons.web.http import request
 
@@ -588,16 +588,9 @@ class website(osv.osv):
         if w < max_w and h < max_h:
             response.data = data
         else:
-            image_format = image.format
             size = (max_w, max_h)
             image = image_resize_and_sharpen(image, size)
-
-            if image_format == 'PNG':
-                image.convert('P').save(response.stream, optimize=True, format='PNG')
-            elif image.format == 'JPEG':
-                image.save(response.stream, quality=80, optimize=True, format='JPG')
-            else:
-                image.save(response.stream, format=image_format)
+            image_save_for_web(image, response.stream)
             # invalidate content-length computed by make_conditional as
             # writing to response.stream does not do it (as of werkzeug 0.9.3)
             del response.headers['Content-Length']
index afa12ce..bf81be8 100644 (file)
@@ -115,6 +115,28 @@ def image_resize_and_sharpen(image, size, factor=2.0):
     image.paste(resized_image, ((size[0] - resized_image.size[0]) / 2, (size[1] - resized_image.size[1]) / 2))
     return image
 
+def image_save_for_web(image, fp=None):
+    """
+        Save image optimized for web usage.
+
+        :param image: PIL.Image.Image()
+        :param fp: File name or file object. If not specified, a bytestring is returned.
+    """
+    opt = dict(format=image.format)
+    if image.format == 'PNG':
+        opt.update(optimize=True)
+        if image.mode != 'P':
+            # Floyd Steinberg dithering by default
+            image = image.convert('RGBA').convert('P', palette=Image.WEB, colors=256)
+    elif image.format == 'JPEG':
+        opt.update(optimize=True, quality=80)
+    if fp:
+        image.save(fp, **opt)
+    else:
+        img = StringIO.StringIO()
+        image.save(img, **opt)
+        return img.getvalue()
+
 def image_resize_image_big(base64_source, size=(1204, 1024), encoding='base64', filetype=None, avoid_if_small=True):
     """ Wrapper on image_resize_image, to resize images larger than the standard
         'big' image size: 1024x1024px.