#!/usr/bin/env python
# Copyright 2016 Amazon.com, Inc. or its
# affiliates. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"). You may not
# use this file except in compliance with the License. A copy of the License is
# located at
#
#     http://aws.amazon.com/apache2.0/
#
# or in the "license" file accompanying this file. This file is distributed on
# an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
# express or implied. See the License for the specific language governing
# permissions and limitations under the License.
import os
import json
import urllib
import boto3
from PIL import Image
from PIL.ExifTags import TAGS

resized_dir = '/images/resized'
thumb_dir = '/images/thumbs'
input_bucket_name = os.environ['s3InputBucket']
output_bucket_name = os.environ['s3OutputBucket']
sqsqueue_name = os.environ['SQSBatchQueue']
aws_region = os.environ['AWSRegion']
s3 = boto3.client('s3', region_name=aws_region)
sqs = boto3.resource('sqs', region_name=aws_region)


def create_dirs():
    for dirs in [resized_dir, thumb_dir]:
        if not os.path.exists(dirs):
            os.makedirs(dirs)


def process_images():
    """Process the image

    No real error handling in this sample code. In case of error we'll put
    the message back in the queue and make it visable again. It will end up in
    the dead letter queue after five failed attempts.

    """
    for message in get_messages_from_sqs():
        try:
            message_content = json.loads(message.body)
            image = urllib.unquote_plus(message_content
                                        ['Records'][0]['s3']['object']
                                        ['key']).encode('utf-8')
            s3.download_file(input_bucket_name, image, image)
            resize_image(image)
            upload_image(image)
            cleanup_files(image)
        except:
            message.change_visibility(VisibilityTimeout=0)
            continue
        else:
            message.delete()


def cleanup_files(image):
    os.remove(image)
    os.remove(resized_dir + '/' + image)
    os.remove(thumb_dir + '/' + image)


def upload_image(image):
    s3.upload_file(resized_dir + '/' + image,
                   output_bucket_name, 'resized/' + image)
    s3.upload_file(thumb_dir + '/' + image,
                   output_bucket_name, 'thumbs/' + image)


def get_messages_from_sqs():
    results = []
    queue = sqs.get_queue_by_name(QueueName=sqsqueue_name)
    for message in queue.receive_messages(VisibilityTimeout=120,
                                          WaitTimeSeconds=20,
                                          MaxNumberOfMessages=10):
        results.append(message)
    return(results)


def resize_image(image):
    img = Image.open(image)
    exif = img._getexif()
    if exif is not None:
        for tag, value in exif.items():
            decoded = TAGS.get(tag, tag)
            if decoded == 'Orientation':
                if value == 3:
                    img = img.rotate(180)
                if value == 6:
                    img = img.rotate(270)
                if value == 8:
                    img = img.rotate(90)
    img.thumbnail((1024, 768), Image.ANTIALIAS)
    try:
        img.save(resized_dir + '/' + image, 'JPEG', quality=100)
    except IOError as e:
        print("Unable to save resized image")
    img.thumbnail((192, 192), Image.ANTIALIAS)
    try:
        img.save(thumb_dir + '/' + image, 'JPEG')
    except IOError as e:
        print("Unable to save thumbnail")


def main():
    create_dirs()
    while True:
        process_images()


if __name__ == "__main__":
    main()

#!/usr/bin/env python
# Copyright 2016 Amazon.com, Inc. or its
# affiliates. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"). You may not
# use this file except in compliance with the License. A copy of the License is
# located at
#
#     http://aws.amazon.com/apache2.0/
#
# or in the "license" file accompanying this file. This file is distributed on
# an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
# express or implied. See the License for the specific language governing
# permissions and limitations under the License.
import os
import json
import urllib
import boto3
from PIL import Image
from PIL.ExifTags import TAGS

resized_dir = '/images/resized'
thumb_dir = '/images/thumbs'
input_bucket_name = os.environ['s3InputBucket']
output_bucket_name = os.environ['s3OutputBucket']
sqsqueue_name = os.environ['SQSBatchQueue']
aws_region = os.environ['AWSRegion']
s3 = boto3.client('s3', region_name=aws_region)
sqs = boto3.resource('sqs', region_name=aws_region)


def create_dirs():
    for dirs in [resized_dir, thumb_dir]:
        if not os.path.exists(dirs):
            os.makedirs(dirs)


def process_images():
    """Process the image

    No real error handling in this sample code. In case of error we'll put
    the message back in the queue and make it visable again. It will end up in
    the dead letter queue after five failed attempts.

    """
    for message in get_messages_from_sqs():
        try:
            message_content = json.loads(message.body)
            image = urllib.unquote_plus(message_content
                                        ['Records'][0]['s3']['object']
                                        ['key']).encode('utf-8')
            s3.download_file(input_bucket_name, image, image)
            resize_image(image)
            upload_image(image)
            cleanup_files(image)
        except:
            message.change_visibility(VisibilityTimeout=0)
            continue
        else:
            message.delete()


def cleanup_files(image):
    os.remove(image)
    os.remove(resized_dir + '/' + image)
    os.remove(thumb_dir + '/' + image)


def upload_image(image):
    s3.upload_file(resized_dir + '/' + image,
                   output_bucket_name, 'resized/' + image)
    s3.upload_file(thumb_dir + '/' + image,
                   output_bucket_name, 'thumbs/' + image)


def get_messages_from_sqs():
    results = []
    queue = sqs.get_queue_by_name(QueueName=sqsqueue_name)
    for message in queue.receive_messages(VisibilityTimeout=120,
                                          WaitTimeSeconds=20,
                                          MaxNumberOfMessages=10):
        results.append(message)
    return(results)


def resize_image(image):
    img = Image.open(image)
    exif = img._getexif()
    if exif is not None:
        for tag, value in exif.items():
            decoded = TAGS.get(tag, tag)
            if decoded == 'Orientation':
                if value == 3:
                    img = img.rotate(180)
                if value == 6:
                    img = img.rotate(270)
                if value == 8:
                    img = img.rotate(90)
    img.thumbnail((1024, 768), Image.ANTIALIAS)
    try:
        img.save(resized_dir + '/' + image, 'JPEG', quality=100)
    except IOError as e:
        print("Unable to save resized image")
    img.thumbnail((192, 192), Image.ANTIALIAS)
    try:
        img.save(thumb_dir + '/' + image, 'JPEG')
    except IOError as e:
        print("Unable to save thumbnail")


def main():
    create_dirs()
    while True:
        process_images()


if __name__ == "__main__":
    main()

#!/usr/bin/env python # Copyright 2016 Amazon.com, Inc. or its # affiliates. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"). You may not # use this file except in compliance with the License. A copy of the License is # located at # #     http://aws.amazon.com/apache2.0/ # # or in the "license" file accompanying this file. This file is distributed on # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either # express or implied. See the License for the specific language governing # permissions and limitations under the License. Process the image      No real error handling in this sample code. In case of error we'll put     the message back in the queue and make it visable again. It will end up in     the dead letter queue after five failed attempts.