abilian.services.image — Abilian 0.1 documentation

# 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

    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

    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