Automated Image Thumbnail Generation

Content Covered

  • Solution and simplified architecture diagram
  • AWS CDK Script (TypeScript)
  • Lambda Function (Python)

Solution

This pipeline demonstrates how to generate thumbnails for images uploaded to an S3 bucket using AWS Lambda and Amazon S3. The system leverages an S3 event notification to trigger a Lambda function that generates thumbnails and stores them back in the S3 bucket. By using AWS Lambda and Amazon S3 together, developers can create a seamless, serverless solution for dynamic thumbnail generation, enhancing the user experience with faster image loading times and optimized storage. This approach exemplifies the power and flexibility of AWS services in building scalable, automated workflows.

Use Case Description

In this scenario, whenever an image is uploaded to a specified S3 bucket, an event notification is sent to AWS Lambda. This event triggers the Lambda function, which contains code specifically written to resize images. Using the AWS SDK, the Lambda function retrieves the newly uploaded image from the S3 bucket.

The function then processes the image, generating a thumbnail with reduced dimensions. This resizing not only saves storage space but also improves load times when the thumbnails are displayed on websites or applications. Once the thumbnail is created, it is uploaded back to a designated folder within the same S3 bucket or to a different bucket, depending on the configuration.

This automated thumbnail generation system is designed to be scalable, capable of handling a high volume of images by leveraging the auto-scaling nature of AWS Lambda. It eliminates the need for manual image processing, thereby reducing operational overhead.

Industry domains

This solution is applicable across various industries, including e-commerce, media, social networking, and content management systems. Any application that involves image uploads and requires thumbnail generation can benefit from this pipeline. Examples include online marketplaces, photo-sharing platforms, and digital asset management systems.

Simplified architecture diagram

S3 Thumbnail Diagram

The architecture consists of:

  1. Amazon S3 Bucket: Stores the original images and generated thumbnails.
  2. AWS Lambda Function: Processes the image uploads and generates thumbnails.
  3. Amazon S3 Event Notification: Triggers the Lambda function upon image upload.
  4. IAM Role: Grants necessary permissions to the Lambda function to access S3.

AWS CDK Script (TypeScript)

import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as s3 from 'aws-cdk-lib/aws-s3';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as s3n from 'aws-cdk-lib/aws-s3-notifications';
import * as iam from 'aws-cdk-lib/aws-iam';

export class ThumbnailGeneratorStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const bucket = new s3.Bucket(this, 'ImageBucket', {
      removalPolicy: cdk.RemovalPolicy.DESTROY,
    });

    const thumbnailFunction = new lambda.Function(this, 'ThumbnailFunction', {
      runtime: lambda.Runtime.PYTHON_3_9,
      handler: 'index.handler',
      code: lambda.Code.fromAsset('lambda'),
      environment: {
        BUCKET_NAME: bucket.bucketName,
      },
    });

    bucket.grantReadWrite(thumbnailFunction);

    bucket.addEventNotification(s3.EventType.OBJECT_CREATED, new s3n.LambdaDestination(thumbnailFunction));

  }
}

Lambda Function (Python)

import os
import boto3
from PIL import Image
from io import BytesIO

s3_client = boto3.client('s3')

def handler(event, context):
    bucket_name = os.environ['BUCKET_NAME']
    for record in event['Records']:
        key = record['s3']['object']['key']
        if key.endswith(('jpg', 'jpeg', 'png')):
            image_object = s3_client.get_object(Bucket=bucket_name, Key=key)
            image_content = image_object['Body'].read()
            image = Image.open(BytesIO(image_content))
            thumbnail = image.copy()
            thumbnail.thumbnail((128, 128))
            thumb_io = BytesIO()
            thumbnail.save(thumb_io, format=image.format)
            thumb_key = f"thumbnails/{key}"
            s3_client.put_object(Bucket=bucket_name, Key=thumb_key, Body=thumb_io.getvalue())
    return {
        'statusCode': 200,
        'body': 'Thumbnail generated successfully!'
    }

Copyright © 2024. All rights reserved.