November 6, 2014

High performance image processing with Image Resizer and Azure

If you need to dynamically transform images, save yourself some time and use Image Resizer.

Image Resizer is an open source ASP.NET library and image server that performs high performance image processing. With its query string API, transforming images is as simple as changing the URL; from resizing to sophisticated image adjustment.

In this post I cover how to set up a high performance image processing service using Image Resizer and Microsoft Azure.

Getting started

In Visual Studio, create a new empty ASP.NET Project.

Create a new empty ASP.NET Project in Visual Studio

Install Image Resizer through NuGet

PM> Install-Package ImageResizer.WebConfig

You can serve your images from anywhere in your site. I’ve created an /images directory and copied in a test image.

Launch the application and browse to /images/test.jpg?width=100.

Dynamically resized image with Image Resizer

If you get a resized version of your source image then Image Resizer is working its magic.

Let’s get a bit more adventurous. Browse to:

/images/test.jpg?width=150&height=150&mode=crop&rotate=90&borderWidth=5&borderColor=black.

Advanced transformations with Image Resizer

We now have an image processing server ready to go.

Deploy to Azure

Go to the Azure Portal and create a new website. I’ve given mine the URL resizer.azurewebsites.net.

Create a new website in Azure

You can deploy the web application by downloading a publish profile from the portal or connecting directly to Azure from within Visual Studio:

Publishing a website to Azure

Connecting to Azure from Visual Studio

With the site published, browse to your azure URL and perform the same tests you did locally:

Transforming images from Azure Websites

Storing images in Azure Blob Storage

To make the media server truly scalable I want to store my images within Azure Blob Storage. I have a different web application that manages the uploading of images so the distributed nature of Azure Blob Storage makes it perfect for this scenario.

So far I’ve only scratched the surface of Image Resizer’s functionality. It has a rich plugin ecosystem for doing all kinds of stuff - including a plugin for reading source images from Azure Blob Storage.

In the Azure Portal create a storage account to store your media:

Creating an Azure Storage Account for image storage

Now install the Azure Reader plugin for Image Resizer:

PM> Install-Package ImageResizer.Plugins.AzureReader2

Note: There is an issue with the current nuget package as it references a newer version of the Azure libraries than those installed by the package. To fix this, just update the Azure packages from NuGet.

Open up web.config and configure the plugin with your storage account connection string:

<resizer>
  <plugins>
    <add name="AzureReader2" 
         connectionString="DefaultEndpointsProtocol=https;AccountName={accountName};AccountKey={accountKey}]" 
         endpoint="http://{{accountName}}.blob.core.windows.net/" 
         prefix="~/" />
  </plugins>
</resizer>

In this example I’ve set the prefix setting so that all requests from the root of the site will be routed to my Azure storage account; For example, a request to http://resizer.azurewebsites.net/images/test.jpg will look for test.jpg from the images container. If you’re installing Image Resizer in an existing site you may want to specify a sub directory (the default is ~/azure).

From the portal create a container to store your images. Note that the access is set to Public Blob. If no querystring modifiers are provided the Azure Reader plugin will automatically redirect to the Azure blob URL.

Create a new blob container

Next upload some images from Visual Studio’s server explorer. Alternatively, check out Azure Storage Explorer.

Uploading to Azure Storage from Visual Studio

Re-deploy the updated site and browse to your image once more. This time it will be loaded from blob storage and then transformed by Image Resizer.

Transforming images stored in Blob Storage

Caching

Image processing can be very resource intensive, especially when dealing with large images. Add to that the fact that we are loading the source images from Azure storage and you’ll understand why we don’t want to perform this processing on every request.

Image Resizer has us covered again with the Disk Cache plugin. This caches the transformed images to the local file system.

This works well in many scenarios, but if you’re handling large volumes of media or running multiple instances of your application there is a better option.

Azure CDN

Rather than caching the transformed images where Image Resizer is hosted, what if you could cache them at the location closest to the client (your web site visitors)?

This is precisely what the Azure CDN enables. When a resource is requested for the first time it is loaded from the origin server (the media server in our case) and then cached in the CDN. Subsequent requests will be served directly from the CDN (built on top of blob storage).

Within the portal add a new CDN and point it to the address of your Azure Website.

Creating an Azure CDN endpoint

You need to make sure you enable Query Strings otherwise all resources with the same filename will be considered the same file, even if the querystrings differ.

Enabling query strings in Azure CDN

Once created you can use the CDN URL to access your images. So instead of requesting http://resizer.azurewebsites.net/images/test.jpg, to serve the images through the CDN change the URL to http://az684817.vo.msecnd.net/images/test.jpg.

Serving transformed images from Azure CDN

Note that it can take some time before the CDN becomes available (1 hour in my case) so be patient

The final thing to do is to set the HTTP Expires header so that the CDN knows not to keep requesting the images from the origin server. This is done by setting the clientcache settings of Image Resizer:

<resizer>
  <clientcache minutes="1440" />
  <plugins>
...
  </plugins>
</resizer>

Without writing a line of code we have a scalable, high performance image processing server hosted in Azure.

For further details on hosting Image Resizer in the cloud, please see the official Image Resizer Cloud Architecture Guide.

Demo images courtesy of the talented Tim Jarvis.

© 2022 Ben Foster