bgneal@696: """images.py bgneal@696: bgneal@696: This module contains image processing routines for the user_photos application. bgneal@696: bgneal@696: """ bgneal@696: import datetime bgneal@696: import logging bgneal@696: from io import BytesIO bgneal@696: import os.path bgneal@696: import uuid bgneal@696: bgneal@696: from django.conf import settings bgneal@696: from PIL import Image bgneal@696: from boto.s3.connection import S3Connection bgneal@696: from boto.s3.key import Key bgneal@696: bgneal@696: bgneal@696: logger = logging.getLogger(__name__) bgneal@696: bgneal@696: bgneal@696: def process_file(f, user): bgneal@696: """Perform processing on the given uploaded image file: bgneal@696: bgneal@696: * The image is resized if necessary bgneal@696: * A thumbnail version is created bgneal@696: * The image and thumbnail are uploaded to an S3 bucket bgneal@696: * The image and thumbnail URLs are returned as a tuple bgneal@696: bgneal@696: """ bgneal@696: logger.info('Processing image file for {}: {}'.format(user.username, f.name)) bgneal@696: bgneal@696: unique_key = uuid.uuid4().hex bgneal@696: ext = os.path.splitext(f.name)[1] bgneal@696: filename = '/tmp/' + unique_key + ext bgneal@696: with open(filename, 'wb') as fp: bgneal@696: for chunk in f.chunks(): bgneal@696: fp.write(chunk) bgneal@696: bgneal@696: # Resize image if necessary bgneal@696: image = Image.open(filename) bgneal@696: if image.size > settings.USER_PHOTOS_MAX_SIZE: bgneal@696: logger.debug('Resizing from {} to {}'.format(image.size, settings.USER_PHOTOS_MAX_SIZE)) bgneal@696: image.thumbnail(settings.USER_PHOTOS_MAX_SIZE, Image.ANTIALIAS) bgneal@696: image.save(filename) bgneal@696: bgneal@696: # Create thumbnail bgneal@696: logger.debug('Creating thumbnail') bgneal@696: image = Image.open(filename) bgneal@696: image.thumbnail(settings.USER_PHOTOS_THUMB_SIZE, Image.ANTIALIAS) bgneal@696: thumb = BytesIO() bgneal@696: image.save(thumb, format=image.format) bgneal@696: bgneal@696: # Upload both images to S3 bgneal@696: logger.debug('Getting connection / bucket') bgneal@696: conn = S3Connection(settings.USER_PHOTOS_ACCESS_KEY, bgneal@696: settings.USER_PHOTOS_SECRET_KEY) bgneal@696: bucket = conn.get_bucket(settings.USER_PHOTOS_BUCKET, validate=False) bgneal@696: bgneal@696: now = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') bgneal@696: bgneal@696: logging.debug('Uploading image') bgneal@696: k1 = Key(bucket) bgneal@696: k1.key = unique_key + ext bgneal@696: k1.set_metadata('user', user.username) bgneal@696: k1.set_metadata('date', now) bgneal@696: k1.set_contents_from_filename(filename) bgneal@696: bgneal@696: logging.debug('Uploading thumbnail') bgneal@696: k2 = Key(bucket) bgneal@696: k2.key = '{}t{}'.format(unique_key, ext) bgneal@696: k2.set_metadata('user', user.username) bgneal@696: k2.set_metadata('date', now) bgneal@696: k2.set_contents_from_string(thumb.getvalue()) bgneal@696: bgneal@696: logging.debug('Making public') bgneal@696: k1.make_public() bgneal@696: k2.make_public() bgneal@696: bgneal@696: os.remove(filename) bgneal@696: bgneal@696: logger.info('Completed processing image file for {}: {}'.format(user.username, f.name)) bgneal@696: bgneal@696: url_base = '{}/{}/'.format(settings.USER_PHOTOS_BASE_URL, bgneal@696: settings.USER_PHOTOS_BUCKET) bgneal@696: bgneal@696: return (url_base + k1.key, url_base + k2.key)