In this article, we’ll explore how to create an AWS Lambda function that automatically resizes images, adds a watermark, and converts the images to a specified format. This functionality can be particularly useful for blog posts, thumbnails for videos, and any other automated image processing tasks.
Watch the Video
To see this process in action, check out my YouTube channel, where I explain how this Lambda function works.
Prerequisites
Before we dive in, ensure you have the following:
- An AWS account
- Basic knowledge of AWS Lambda, S3 and IAM
- An EC2 instance set up with Amazon Linux 2023 to build the Pillow layer – optional
- S3 bucket for uploading images
- IAM role with the necessary permissions for your Lambda function
Overview of the Process
To create an AWS Lambda function that automatically resizes images, adds a watermark, and converts the images to a specified format we will follow these main steps:
- Build a Lambda layer with the Pillow library, which allows us to manipulate images – optional
- Add code to resize images, add watermark and convert.
- Configure the function to trigger on S3 events when new images are uploaded.
1. Creating the Lambda Layer with Pillow
Pillow is not included by default in AWS Lambda, so we need to create a layer for it. There are two ways to do this:
– Option 1 – Use an existing ARN for the Pillow layer if available.
– Option 2 – Create your own layer following the steps below.
Steps to Create the Pillow Layer
Log in to your EC2 instance running Amazon Linux 2023 and execute the following commands:
# 1. Install essential build dependencies for compiling Python
sudo dnf install -y gcc openssl-devel bzip2-devel libffi-devel make zlib-devel
# 2. Download Python 3.12 source code
wget https://www.python.org/ftp/python/3.12.0/Python-3.12.0.tgz
# 3. Extract the downloaded Python tarball
tar xzf Python-3.12.0.tgz
cd Python-3.12.0
# 4. Configure and compile Python with zlib support enabled for AWS Lambda compatibility
./configure --enable-optimizations --with-zlib
make
sudo make altinstall
# 5. Download `get-pip.py` to manually install `pip` for Python 3.12
cd ~
curl -O https://bootstrap.pypa.io/get-pip.py
# 6. Install `pip` for Python 3.12
sudo /usr/local/bin/python3.12 get-pip.py
# Verify `pip` installation
/usr/local/bin/python3.12 -m pip --version
# 7. Create a virtual environment with Python 3.12
/usr/local/bin/python3.12 -m venv pillow-layer-env
# 8. Activate the virtual environment
source pillow-layer-env/bin/activate
# 9. Install Pillow in the virtual environment
pip install Pillow
# 10. Create the folder structure for AWS Lambda layer
mkdir -p python/lib/python3.12/site-packages
# 11. Copy the installed packages to the Lambda layer structure
cp -r pillow-layer-env/lib/python3.12/site-packages/* python/lib/python3.12/site-packages/
# 12. Compress the `python` folder into a ZIP file for Lambda layer deployment
zip -r pillow-layer.zip python
# You can now upload `pillow-layer.zip` to AWS Lambda as a layer
Uploading the Layer to AWS Lambda
Now that we have our pillow-layer.zip
file, you can upload it to AWS Lambda:
- Go to the AWS Lambda console.
- Click on Layers in the left-hand menu.
- Click Create Layer.
- Upload your
pillow-layer.zip
file. - Choose the Python version that matches your Lambda function.
Option 1: Adding the Layer through the AWS Lambda Console
- Go to the AWS Lambda console.
- Select the Lambda function to which you want to add the layer.
- Scroll down to the Layers section and click on Add a layer.
- Choose Custom layers from the options.
- From the Layer name dropdown, select the
pillow-layer
you created. - Ensure you’ve selected the correct layer version and Python version that matches your Lambda function.
- Click Add to apply the layer to your Lambda function.
Option 2: Adding the Layer Using an ARN
- Go to the AWS Lambda console.
- Select the Lambda function to which you want to add the layer.
- In the Layers section, click on Add a layer.
- Select Specify an ARN.
- Paste the ARN of your layer in the text field. The ARN format typically looks like:
codearn:aws:lambda:<region>:<account-id>:layer:<layer-name>:<version>
- Click Add to apply the layer to your Lambda function.
2. Example Code for the Lambda Function
Below is the code you’ll need to create the Lambda function that resizes images, adds a watermark, and saves the output with the specified format. You can modify this code according to your specific requirements.
import boto3
from PIL import Image, ImageDraw, ImageFont
import io
import os
s3 = boto3.client('s3')
def lambda_handler(event, context):
# Define output format (e.g., 'WEBP', 'JPEG', 'PNG'...)
output_format = 'WEBP'
bucket_name = event['Records'][0]['s3']['bucket']['name']
object_key = event['Records'][0]['s3']['object']['key']
print(bucket_name)
print(object_key)
if object_key.startswith('input/'):
s3_response = s3.get_object(Bucket=bucket_name, Key=object_key)
image_content = s3_response['Body'].read()
img = Image.open(io.BytesIO(image_content))
# Set watermark text
watermark_text = "https://lepczynski.it"
file_extension = os.path.splitext(object_key)[1].lower()
if file_extension != f'.{output_format.lower()}':
img = img.convert('RGB')
# Resize image to HD resolution (1280x720)
img = img.resize((1280, 720))
draw = ImageDraw.Draw(img)
font = ImageFont.load_default()
text_bbox = draw.textbbox((0, 0), watermark_text, font=font)
text_width = text_bbox[2] - text_bbox[0]
text_height = text_bbox[3] - text_bbox[1]
watermark_position = (img.width - text_width - 10, img.height - text_height - 10)
draw.text(watermark_position, watermark_text, font=font, fill=(255, 255, 255, 128)) # White with transparency
buffer = io.BytesIO()
img.save(buffer, output_format)
buffer.seek(0)
output_key = object_key.replace('input/', 'output/').rsplit('.', 1)[0] + f'.{output_format.lower()}'
s3.put_object(Bucket=bucket_name, Key=output_key, Body=buffer, ContentType=f'image/{output_format.lower()}')
return {
'statusCode': 200,
'body': f'Image successfully processed and saved as {output_key}'
}
else:
return {
'statusCode': 400,
'body': 'File not in the input folder.'
}
3. Setting Up an S3 Trigger for Your Lambda Function
To make your Lambda function automatically process images as soon as they are uploaded to an S3 bucket, you need to set up an S3 trigger. This trigger will invoke your Lambda function whenever a new object is created in the specified bucket. Here’s how to do it:
- In the Configuration tab, find the Triggers section, and Click on Add Trigger.
- In the Trigger configuration dropdown, select S3.
- Choose the S3 bucket you want to monitor for new uploads.
- For the Event type, select PUT. This will trigger the Lambda function only when a new object is created (uploaded) to the S3 bucket, avoiding unnecessary invocations for object deletions or other events.
- If you want to filter which files trigger the Lambda function, you can specify a prefix e.g.,
input/
like me or a suffix e.g.,.jpg
or.png
. This way, only files that match the criteria will invoke the function. - The console will automatically add the necessary permissions for the S3 bucket to invoke your Lambda function. Ensure that the IAM role associated with your Lambda function has permissions to read from the S3 bucket.
- Finally, click the Add button to create the trigger.
If you are interested in adding triggers to lambda functions, you can check out my other articles where I focus more on this topic. Take a look at this article How to automatically copy data from AWS S3 – Lambda events, or use the search function.
Testing
After setting up the S3 trigger, you can test it by uploading an image to your specified S3 bucket. Once the image is uploaded, your Lambda function should automatically be invoked, processing the image as per the code you have written.
Monitoring and Logs
You can monitor the execution of your Lambda function by checking the Monitor tab in the Lambda console. Additionally, you can view logs in Amazon CloudWatch to troubleshoot any issues that arise during execution.
Remember to adjust the Lambda function permissions so that it can read from and write to your S3 bucket. You can also modify the watermark text, size, and position to fit your needs.
Conclusion
Now you have a powerful AWS Lambda function that automatically resizes images, adds a watermark, and converts them to the desired format. This setup can greatly improve your workflow, especially when creating thumbnails for YouTube videos or processing images for your blog, social media, or whatever you want.
If the article was helpful to you, I would be very happy if you leave a comment under this article or the video on YouTube. Remember that you can also subscribe to my YouTube channel to stay up to date with the content I create.