[IMP] Compress resized /website/image's
authorFabien Meghazi <fme@openerp.com>
Sun, 7 Sep 2014 09:41:46 +0000 (11:41 +0200)
committerFabien Meghazi <fme@openerp.com>
Tue, 16 Sep 2014 17:55:00 +0000 (19:55 +0200)
Refactored and fixed tools.image_resize_image() that converted to RGBA
after making thumbnails, resulting in bad looking picture in case the
source is in 'P' mode (indexed palette)

addons/website/models/website.py
openerp/tools/image.py

index 949e276..a339bcb 100644 (file)
@@ -25,8 +25,7 @@ except ImportError:
 
 import openerp
 from openerp.osv import orm, osv, fields
-from openerp.tools import html_escape as escape
-from openerp.tools import ustr as ustr
+from openerp.tools import html_escape as escape, ustr, image_resize_and_sharpen
 from openerp.tools.safe_eval import safe_eval
 from openerp.addons.web.http import request
 
@@ -589,8 +588,16 @@ class website(osv.osv):
         if w < max_w and h < max_h:
             response.data = data
         else:
-            image.thumbnail((max_w, max_h), Image.ANTIALIAS)
-            image.save(response.stream, image.format)
+            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)
             # 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 93458fb..afa12ce 100644 (file)
@@ -88,13 +88,7 @@ def image_resize_image(base64_source, size=(1024, 1024), encoding='base64', file
         return base64_source
 
     if image.size != size:
-        # create a thumbnail: will resize and keep ratios, then sharpen for better looking result
-        image.thumbnail(size, Image.ANTIALIAS)
-        sharpener = ImageEnhance.Sharpness(image.convert('RGBA'))
-        resized_image = sharpener.enhance(2.0)
-        # create a transparent image for background and paste the image on it
-        image = Image.new('RGBA', size, (255, 255, 255, 0))
-        image.paste(resized_image, ((size[0] - resized_image.size[0]) / 2, (size[1] - resized_image.size[1]) / 2))
+        image = image_resize_and_sharpen(image, size)
     if image.mode not in ["1", "L", "P", "RGB", "RGBA"]:
         image = image.convert("RGB")
 
@@ -102,6 +96,25 @@ def image_resize_image(base64_source, size=(1024, 1024), encoding='base64', file
     image.save(background_stream, filetype)
     return background_stream.getvalue().encode(encoding)
 
+def image_resize_and_sharpen(image, size, factor=2.0):
+    """
+        Create a thumbnail by resizing while keeping ratio.
+        A sharpen filter is applied for a better looking result.
+
+        :param image: PIL.Image.Image()
+        :param size: 2-tuple(width, height)
+        :param factor: Sharpen factor (default: 2.0)
+    """
+    if image.mode != 'RGBA':
+        image = image.convert('RGBA')
+    image.thumbnail(size, Image.ANTIALIAS)
+    sharpener = ImageEnhance.Sharpness(image)
+    resized_image = sharpener.enhance(factor)
+    # create a transparent image for background and paste the image on it
+    image = Image.new('RGBA', size, (255, 255, 255, 0))
+    image.paste(resized_image, ((size[0] - resized_image.size[0]) / 2, (size[1] - resized_image.size[1]) / 2))
+    return image
+
 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.