Dynamically Resize Image in .Net

In .Net this is almost a complete non-event.  The functionality in System.Drawing.Graphicsand System.Drawing.Bitmapdoes all the heavy lifting.

Here's the annotated source code to resize an image.

 Scaled images are sent straight to the client, thumbnailed ones are placed in the ASP.NET Cache object.

Imports System.Web.UI
Imports System.Drawing
Public Class Scaler
'
' Written by Richard Howells - Dynamisys Ltd - richard@dynamisys.co.uk
'
' This class expects quite a bit of context. Call it from an
' aspx page's Load event - it expects a QueryString that includes
' filename=<ImageFileName>[&width=<desiredWidth>]
 ' Use ThumbnailImage for thumbnails and ScaleImage for all other scaling.
' ThumbnailImage knows how to extract an embedded thumbnail image if there
' is one.
 ' Thumbnails are cached in the Cache object, scaled images are not.

 Private Function LoadImageFromDisk(ByVal serverPath As String, ByVal filename As String) As Image
Dim objImage As System.Drawing.Image = Nothing
 'Load an image from the file. Use the standard error.gif if file won't open
Try
objImage = Image.FromFile(serverPath & filename)
Catch ex As IO.FileNotFoundException
objImage = Image.FromFile(serverPath & "error.gif")
End Try
 Return objImage
 End Function
 Private Function GetRequiredSize(ByVal objImage As Image) As Size
Dim width, height As Short
' Retrieve width from query string
If HttpContext.Current.Request.QueryString("width") = Nothing Then
width = objImage.Width
ElseIf HttpContext.Current.Request.QueryString("width") < 1 Then
width = 100
Else
width = HttpContext.Current.Request.QueryString("width")
End If
' Work out a proportionate height from width
height = objImage.Height / (objImage.Width / width)
Return New Size(width, height)
End Function
 Public Sub ScaleImage()
Dim objImage As System.Drawing.Image = Nothing
Try
objImage = LoadImageFromDisk(HttpContext.Current.Server.MapPath("images\"), HttpContext.Current.Request.QueryString("filename"))
 Dim imageSize As Size = GetRequiredSize(objImage)
 ' Create resized image
Using objBitmap As New Bitmap(imageSize.Width, imageSize.Height)
Using objGraphics As Graphics = Graphics.FromImage(objBitmap)
 objGraphics.DrawImage(objImage, 0, 0, imageSize.Width, imageSize.Height)
 ' Send down to client
HttpContext.Current.Response.ContentType = "image/jpeg"
objBitmap.Save(HttpContext.Current.Response.OutputStream, Imaging.ImageFormat.Jpeg)
' Tidy up
End Using
End Using
Finally
If objImage IsNot Nothing Then
objImage.Dispose()
End If
End Try
 End Sub
 Public Sub ThumbnailImage()
Dim objImage As Image = Nothing
Dim objThumbnail As Image = Nothing
Try
objThumbnail = CType(HttpContext.Current.Cache(HttpContext.Current.Request.Url.Query), Image)
If objThumbnail Is Nothing Then
objImage = LoadImageFromDisk(HttpContext.Current.Server.MapPath("images\"), HttpContext.Current.Request.QueryString("filename"))
 Dim imageSize As Size = GetRequiredSize(objImage)
' Create thumbnail
objThumbnail = objImage.GetThumbnailImage(imageSize.Width, _
imageSize.Height, Nothing, System.IntPtr.Zero)
 'The cache dependancy used here is only to the filename and not the full path
HttpContext.Current.Cache.Insert(HttpContext.Current.Request.Url.Query, objThumbnail, _
New CacheDependency(HttpContext.Current.Server.MapPath("images\") & HttpContext.Current.Request.QueryString("filename")))
End If
' Send down to client
HttpContext.Current.Response.ContentType = "image/jpeg"
objThumbnail.Save(HttpContext.Current.Response.OutputStream, Imaging.ImageFormat.Jpeg)
' Tidy up
Finally
If objImage IsNot Nothing Then
objImage.Dispose()
End If
'DO NOT CALL Dispose on objThumbnail. It's meant to be in the Cache. If you dispose it then
'the next user trying to use it from the cache will get a nasty shock.
End Try
 End Sub
End Class

 

How to use the class

The class above assumes that all images lie in a subdirectory of the main site named images

Create a couple of aspx pages to serve up the scaled images.  I call them ImageScaler.aspx and ThumbnailScaler.aspx.  They only need code in the Page_Load event and it looks like this (for ImageScaler).

 Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim scaler As New Scaler
scaler.ScaleImage()
End Sub

 

 

When another page of the site needs to serve a dynamically sized image, it uses an image control and sets the ImageURL property to (say) imagescaler.aspx?filename=img_2074.jpg&width=1000.
Of course the ImageURL property value may be built in code if required.

The same technique works with ThumbnailScaler.aspx.  Typically there may be several thumbnails on a page and that is the reason behind caching the thumbnail sized objects.  In the site I maintain for Wootton
Bassett Volleyball Club
the original images are about 1-2Mb in size and it is a noticeable hit on the server to scale the images.  It's tolerable for one image, but for a page of thumbnails it takes a while.

Sample Code for an ASPX page

 


<%@ Page Language="VB" AutoEventWireup="false" CodeFile="Default.aspx.vb" Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Image ID="Image1" runat="server" ImageUrl="imagescaler.aspx?filename=img_2074.jpg&width=1000" /></div>
</form>
</body>
</html>

Sample code for an HTML page


 

It is not required that the scalers are called from ASPX pages.  The ASPX URL can be used as an image request from any kind of web page. 

Copyright 2002-15 by Dynamisys Ltd