Introduction
I was getting Out of Memory exceptions with my website which is hosted with M6.net. This turned out to be a result of using the Stream
class within a few of my image resizing methods. I looked into converting it to using GDI+ instead, which seems to munch on less memory. It also produces a quality resized image.
Using the code
The GetEncoder
helper method selects the most appropriate JPEG encoder. I also have the current Server
object as a static variable for convenience.
The ResizeImage
method does a few things. Firstly, it determines the proportions of the new image. After that, it creates a new bitmap object and finally creates and saves the new image. Simple.
Please note that I use ~/ relative paths in my code so you will need to tweak this if you want to use physical paths.
#region Using Directives
using System;
using System.Web;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
#endregion Using Directives
public class ImageResizer
{
#region Fields
static HttpServerUtility Server = HttpContext.Current.Server;
#endregion Fields
#region Get Encoder
public static ImageCodecInfo GetEncoder(string mimeType)
{
foreach (ImageCodecInfo codec in ImageCodecInfo.GetImageEncoders())
{
if (codec.MimeType == mimeType)
{
return codec;
}
}
return null;
}
#endregion Get Encoder
#region Resize Image
public static void ResizeImage(string originalImageLocation,
int width, int height, string newImageLocation)
{
Image originalImage = Image.FromFile(
Server.MapPath(originalImageLocation.Replace("//", "/")));
ResizeImage(originalImage, width, height, newImageLocation);
}
public static void ResizeImage(Image originalImage,
int width, int height, string newImageLocation)
{
decimal newWidth;
decimal newHeight;
if ((originalImage.Width / width) > (originalImage.Width / height))
{
newWidth = width;
newHeight = (Int32)Math.Ceiling(Convert.ToDecimal((
originalImage.Height * newWidth) / originalImage.Width));
if (newHeight > height)
{
newWidth = newWidth * (height / newHeight);
newHeight = height;
}
}
else
{
newHeight = height;
newWidth = Math.Ceiling(Convert.ToDecimal((
originalImage.Width * newHeight) / originalImage.Height));
if (newWidth > width)
{
newHeight = newHeight * (width / newWidth);
newWidth = width;
}
}
Bitmap newBitmap = new Bitmap(Convert.ToInt32(newWidth),
Convert.ToInt32(newHeight), PixelFormat.Format16bppRgb565);
Graphics g = Graphics.FromImage(newBitmap);
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.SmoothingMode = SmoothingMode.AntiAlias;
g.SmoothingMode = SmoothingMode.HighQuality;
g.DrawImage(originalImage, 0, 0, Convert.ToInt32(newWidth),
Convert.ToInt32(newHeight));
ImageCodecInfo codecEncoder = ImageResizer.GetEncoder("image/jpeg");
int quality = 98;
EncoderParameters encodeParams = new EncoderParameters(1);
EncoderParameter qualityParam = new EncoderParameter(Encoder.Quality, quality);
encodeParams.Param[0] = qualityParam;
newBitmap.SetResolution(72, 72);
newBitmap.Save(Server.MapPath(newImageLocation), codecEncoder, encodeParams);
g.Dispose();
newBitmap.Dispose();
originalImage.Dispose();
}
#endregion Resize Image
}
I hope this has been of use to you.