From 89362bd6cd3daab7acdd2e1416f594fcf7b3ea59 Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Mon, 8 Sep 2014 15:53:02 +0200 Subject: [PATCH] [ADD] tools.image_save_for_web() helper for image compression --- addons/website/models/website.py | 11 ++--------- openerp/tools/image.py | 22 ++++++++++++++++++++++ 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/addons/website/models/website.py b/addons/website/models/website.py index a339bcb..983d419 100644 --- a/addons/website/models/website.py +++ b/addons/website/models/website.py @@ -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'] diff --git a/openerp/tools/image.py b/openerp/tools/image.py index afa12ce..bf81be8 100644 --- a/openerp/tools/image.py +++ b/openerp/tools/image.py @@ -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. -- 1.7.10.4