Source code for abilian.services.image

"""
Provides tools (currently: only functions, not a real service) for image
processing.
"""

from cStringIO import StringIO
from PIL import Image

import hashlib


__all__ = ['resize', 'crop_and_resize']

# TODO: cache to file
cache = {}


def get_format(img):
  if isinstance(img, basestring):
    img = StringIO(img)
  image = Image.open(img)
  return image.format


[docs]def resize(orig, hsize): cache_key = (hashlib.md5(orig).digest(), hsize, hsize) if cache_key in cache: return cache[cache_key] if isinstance(orig, basestring): orig = StringIO(orig) image = Image.open(orig) format = image.format x, y = image.size if x <= hsize: orig.seek(0) return orig.read() x1 = hsize y1 = int(1.0 * y * hsize / x) image.thumbnail((x1, y1), Image.ANTIALIAS) output = StringIO() if format in ('GIF', 'PNG'): image.save(output, "PNG") else: image.save(output, "JPEG") converted = output.getvalue() cache[cache_key] = converted return converted
[docs]def crop_and_resize(orig, hsize, vsize=0): if isinstance(orig, basestring): orig = StringIO(orig) if not vsize: vsize = hsize cache_key = (hashlib.md5(orig.read()).digest(), hsize, vsize) orig.seek(0) if cache_key in cache: return cache[cache_key] image = Image.open(orig) format = image.format # Compute cropping coordinates x1 = y1 = 0 x2, y2 = image.size w_ratio = 1.0 * x2 / hsize h_ratio = 1.0 * y2 / vsize if h_ratio > w_ratio: y1 = int(y2 / 2 - hsize * w_ratio / 2) y2 = int(y2 / 2 + vsize * w_ratio / 2) else: x1 = int(x2 / 2 - hsize * h_ratio / 2) x2 = int(x2 / 2 + vsize * h_ratio / 2) image = image.crop((x1, y1, x2, y2)) image.thumbnail((hsize, vsize), Image.ANTIALIAS) output = StringIO() if format in ('GIF', 'PNG'): image.save(output, "PNG") else: image.save(output, "JPEG") converted = output.getvalue() cache[cache_key] = converted return converted