Resizing images in .NET

by Tom on April 23, 2007

There are lots of examples on the Interweb about how to do image resizing in .NET – unfortunately none of these quite hit the mark where we were concerned.

The problem is that you generally need to know both the height and width of a thumbnail so that your XHTML CSS developer doesn’t get too upset and can do a nice layout without having to distort your images.

The following is the start of some C# code I’ve written to do various different resizing of images as follows:

  • ToLargest – the largest dimension is shrunk to the specified size – not yet found a use for this!
  • ToWidth – shrinks the width down to the specified size and makes the height the correct aspect ration, useful for vertical scrolling lists of images.
  • ToHeight – same as width but shrinks the height to the specified size and changes the width, useful for horizontal scrolling lists.
  • ToSquareCanvas – squares the image to the specified dimension and places a correctly shrunk image in to the middle.
  • ToSquareImage – squares the image exactly and doesn’t worry about distorting the original.

The main function ResizeImage takes an image parameter to make it as useful as possible. For example, it’s easy to get an image object from an uploaded file using something like the following:

Dim msr As New MemoryStream(file.FileBytes)
Dim uploadedImage As Image = New Bitmap(msr)

Here is the entire class for resizing images. Note the public enum which gives the available sizing methods. Also, you can pass the function a hex color e.g. ff0000 which will change the colour of the canvas.

public class ImageManager
{
/// <summary>
/// How we want to size our new image.
/// </summary>
public enum SizeToMethod
{
ToLargest,
ToWidth,
ToHeight,
ToSquareCanvas,
ToSquareImage
}

/// <summary>
/// Takes an IO stream (assumed to be an image! :) and resizes it.
/// </summary>
/// <param name=”sizeTo”></param>
public Image ResizeImage(Image imgOriginal, int size, SizeToMethod sizeTo, string canvasColor)
{

int newWidth = imgOriginal.Width;
int newHeight = imgOriginal.Height;
int canvasWidth = 0;
int canvasHeight = 0;

//Determine the new size of height and width.
if (sizeTo == SizeToMethod.ToLargest || sizeTo == SizeToMethod.ToSquareCanvas)
{
//If width of the original is greater than the height
if (imgOriginal.Width > imgOriginal.Height)
{
resizeSecondDimension(ref newWidth, ref newHeight, size, ref canvasWidth, ref canvasHeight);
}
else //Height is greater than width
{
resizeSecondDimension(ref newHeight, ref newWidth, size, ref canvasHeight, ref canvasWidth);
}

//If the result is to be a square image we want it in the middle.
if (sizeTo == SizeToMethod.ToSquareCanvas)
{
canvasWidth = size;
canvasHeight = size;
}
}
else if (sizeTo == SizeToMethod.ToWidth)
{
resizeSecondDimension(ref newWidth, ref newHeight, size, ref canvasWidth, ref canvasHeight);
}
else if (sizeTo == SizeToMethod.ToHeight)
{
resizeSecondDimension(ref newHeight, ref newWidth, size, ref canvasHeight, ref canvasWidth);
}
else if (sizeTo == SizeToMethod.ToSquareImage)
{
newHeight = size;
newWidth = size;
canvasHeight = size;
canvasWidth = size;
}

Single xPos = 0; //X position on canvas.
Single yPos = 0; //Y position on canvas.

//Put the image on the right place on the canvas.
if (newWidth < canvasWidth)
{
xPos = Convert.ToSingle((size – newWidth) / 2);
}

if (newHeight < canvasHeight)
{
yPos = Convert.ToSingle((size – newHeight) / 2);
}

Image bmpOutput = new Bitmap(canvasWidth, canvasHeight);
Graphics g = Graphics.FromImage(bmpOutput);
SolidBrush b = new SolidBrush(Color.White);

//Change the colour of the canvas if required.
if(!string.IsNullOrEmpty(canvasColor) && canvasColor.Length==6)
{
int cr = Convert.ToInt32(canvasColor.Substring(0,2), 16);
int cg = Convert.ToInt32(canvasColor.Substring(2,2), 16);
int cb = Convert.ToInt32(canvasColor.Substring(4,2), 16);

b = new SolidBrush(Color.FromArgb(100, cr,cg,cb));
}

g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.FillRectangle(b, 0, 0, canvasWidth, canvasHeight);
g.DrawImage(imgOriginal, xPos, yPos, newWidth, newHeight);
g.Dispose();
imgOriginal.Dispose();
GC.Collect();

return bmpOutput;
}

/// <summary>
/// Takes two dimensions and uses the first, in conjunction with a size to resize the second.
/// </summary>
/// <param name=”resizeByAxis”></param>
/// <param name=”resizeAlternativeAxis”></param>
/// <param name=”newSize”></param>
/// <returns></returns>
private decimal resizeSecondDimension(ref int resizeByLength, ref int resizeAlternativeLength, int size,
ref int canvasLength, ref int canvasAlternativeLength)
{

decimal ratio = 1;
ratio = (Decimal)resizeAlternativeLength / (Decimal)resizeByLength;

//Don’t bother resizing if the dimension is smaller than what’s requested.
if (resizeByLength <= size)
{
canvasLength = size;
}
else
{
resizeByLength = size;
canvasLength = resizeByLength;

//Resize the other dimension.
resizeAlternativeLength = Convert.ToInt32(resizeByLength * ratio);
}

//The other canvas size is always the size of the other length.
canvasAlternativeLength = resizeAlternativeLength;

return ratio;
}

}

Hope this is helpful to someone, if you have any comments or suggestions let me know

{ 1 comment… read it below or add one }

Brian June 25, 2008 at 6:56 pm

This worked great. Best I have found so far.

Leave a Comment

Previous post:

Next post: