annotate core/image_uploader.py @ 964:51a2051588f5

Image uploading now expects a file. Refactor image uploading to not expect a Django UploadedFile and use a regular file instead. This will be needed for the future feature of being able to save and upload images from the Internet.
author Brian Neal <bgneal@gmail.com>
date Wed, 02 Sep 2015 20:50:08 -0500
parents ee47122d6277
children
rev   line source
bgneal@700 1 """This module contains a function to upload an image file to a S3Bucket.
bgneal@696 2
bgneal@700 3 The image can be resized and a thumbnail can be generated and uploaded as well.
bgneal@696 4
bgneal@696 5 """
bgneal@885 6 from base64 import b64encode
bgneal@696 7 import logging
bgneal@696 8 from io import BytesIO
bgneal@696 9 import os.path
bgneal@696 10 import uuid
bgneal@696 11
bgneal@696 12 from PIL import Image
bgneal@696 13
bgneal@837 14 from core.image import orient_image
bgneal@700 15
bgneal@696 16
bgneal@696 17 logger = logging.getLogger(__name__)
bgneal@696 18
bgneal@696 19
bgneal@885 20 def make_key():
bgneal@885 21 """Generate a random key suitable for a filename"""
bgneal@885 22 return b64encode(uuid.uuid4().bytes, '-_').rstrip('=')
bgneal@885 23
bgneal@885 24
bgneal@964 25 def upload(filename, bucket, metadata=None, new_size=None, thumb_size=None):
bgneal@700 26 """Upload an image file to a given S3Bucket.
bgneal@696 27
bgneal@700 28 The image can optionally be resized and a thumbnail can be generated and
bgneal@700 29 uploaded as well.
bgneal@696 30
bgneal@700 31 Parameters:
bgneal@964 32 filename - The path to the file to process. The filename should have an
bgneal@964 33 extension, and this is used for the uploaded image & thumbnail
bgneal@964 34 names.
bgneal@700 35 bucket - A core.s3.S3Bucket instance to upload to.
bgneal@700 36 metadata - If not None, must be a dictionary of metadata to apply to the
bgneal@700 37 uploaded file and thumbnail.
bgneal@700 38 new_size - If not None, the image will be resized to the dimensions
bgneal@700 39 specified by new_size, which must be a (width, height) tuple.
bgneal@700 40 thumb_size - If not None, a thumbnail image will be created with the
bgneal@700 41 dimensions specified by thumb_size, which must be a (width,
bgneal@700 42 height) tuple. The thumbnail will use the same metadata, if
bgneal@700 43 present, as the image. The thumbnail filename will be the
bgneal@700 44 same basename as the image with a 't' appended. The
bgneal@700 45 extension will be the same as the original image.
bgneal@700 46
bgneal@700 47 A tuple is returned: (image_url, thumb_url) where thumb_url will be None if
bgneal@700 48 a thumbnail was not requested.
bgneal@696 49 """
bgneal@696 50
bgneal@737 51 logger.info('Processing image file: %s', filename)
bgneal@700 52
bgneal@885 53 unique_key = make_key()
bgneal@964 54 ext = os.path.splitext(filename)[1]
bgneal@696 55
bgneal@964 56 # Re-orient if necessary
bgneal@964 57 image = Image.open(filename)
bgneal@964 58 changed, image = orient_image(image)
bgneal@964 59 if changed:
bgneal@964 60 image.save(filename)
bgneal@696 61
bgneal@964 62 # Resize image if necessary
bgneal@964 63 if new_size:
bgneal@964 64 image = Image.open(filename)
bgneal@964 65 if image.size > new_size:
bgneal@964 66 logger.debug('Resizing from {} to {}'.format(image.size, new_size))
bgneal@964 67 image.thumbnail(new_size, Image.ANTIALIAS)
bgneal@964 68 image.save(filename)
bgneal@837 69
bgneal@964 70 # Create thumbnail if necessary
bgneal@964 71 thumb = None
bgneal@964 72 if thumb_size:
bgneal@964 73 logger.debug('Creating thumbnail {}'.format(thumb_size))
bgneal@964 74 image = Image.open(filename)
bgneal@964 75 image.thumbnail(thumb_size, Image.ANTIALIAS)
bgneal@964 76 thumb = BytesIO()
bgneal@964 77 image.save(thumb, format=image.format)
bgneal@696 78
bgneal@964 79 # Upload images to S3
bgneal@964 80 file_key = unique_key + ext
bgneal@964 81 logging.debug('Uploading image')
bgneal@964 82 image_url = bucket.upload_from_filename(file_key, filename, metadata)
bgneal@696 83
bgneal@700 84 thumb_url = None
bgneal@700 85 if thumb:
bgneal@700 86 logging.debug('Uploading thumbnail')
bgneal@700 87 thumb_key = '{}t{}'.format(unique_key, ext)
bgneal@700 88 thumb_url = bucket.upload_from_string(thumb_key,
bgneal@700 89 thumb.getvalue(),
bgneal@700 90 metadata)
bgneal@696 91
bgneal@737 92 logger.info('Completed processing image file: %s', filename)
bgneal@696 93
bgneal@700 94 return (image_url, thumb_url)