Uploading of images and resizing (scaling) of them is a very common utility application. Various applications for this function are - Photo thumbnails, profile photos, stock photograph images like Flickr, etc. The System.Drawing namespace provides a built-in thumbnail creation function, but here is a code snippet to resize images preserving its original aspect ratio, maintaining high quality, and limiting the image sizes within prescribed maximum values.
This article explains two concepts - 1. Uploading an image to the server, 2. Resizing the image to a preset maximum width and height.
User Interface
The user interface should contain a FileUpload control to upload image files. To display the resized image, there should be an Image control. A button is used here to start uploading and resizing.
<div style="margin:10px;padding:10px;border:1px solid #CFCFCF;width:500px;">
<h3 style="margin:0px;padding:0px;">Select a picture file to upload:</h3>
<asp:FileUpload runat="server" ID="photoUpload" Width="500px" Height="25px" />
<div style="text-align:center;padding:5px;">
<asp:Button runat="server" ID="btnUpload" Text=" Upload & Resize "
Height="30px" Font-Bold="true" onclick="btnUpload_Click" />
</div>
<div style="text-align:center;padding:10px;" runat="server" id="imageContainer" visible="false">
<asp:Image runat="server" ID="picture" />
</div>
</div>
Image Uploading
When you upload a file using the FileUpload control, at the server side, you have to check for two necessary validations.
- The uploaded file is not blank
- The uploaded file has one of the permitted extensions, or should not have any of the prohibited extensions.
The content details of the uploaded file can be read using the FileBytes, FileName, FileContent properties of the FileUpload control. There is another property PostedFile which also provides similar details about the uploaded file. The FileContent or PostedFile.InputStream properties allows reading the uploaded file as System.IO.Stream. This would help constructing a System.Drawing.Bitmap object for the uploaded image without saving the image on the server.
protected void btnUpload_Click(object sender, EventArgs e)
{
// Validate the uploaded file
// 1. The uploaded file should not be a blank file
if (photoUpload.FileBytes.Length == 0)
return;
// 2. The uploaded file should be having one of the allowed extensions
string ext = System.IO.Path.GetExtension(photoUpload.FileName).TrimStart(".".ToCharArray()).ToLower();
if ((ext != "jpeg") && (ext != "jpg") && (ext != "png") && (ext != "gif") && (ext != "bmp"))
{
return;
}
// Validation successful
// Load the image into Bitmap Object
Bitmap uploadedImage = new Bitmap(photoUpload.FileContent);
// Set the maximum width and height here.
// You can make this versatile by getting these values from
// QueryString or textboxes
int maxWidth = 480;
int maxHeight = 0;
// Resize the image
Bitmap resizedImage = GetScaledPicture(uploadedImage, maxWidth, maxHeight);
//Save the image
String virtualPath = "~/temp/" + System.Guid.NewGuid().ToString() + "." + ext;
String tempFileName = Server.MapPath(virtualPath);
resizedImage.Save(tempFileName, uploadedImage.RawFormat);
// Load the resized image on the browser
picture.ImageUrl = virtualPath;
imageContainer.Visible = true;
}
Scaling of the uploaded image
The scaling technique used here preserves the original aspect ratio of the uploaded picture and resizes the image to stay within a given maximum width and height. The scaling logic checks the following conditions:
- If the image size is smaller than the maximum width and height, the original image is returned.
- If the dimensions exceeds the maximum bounds, the new scales are calculated, which is directly proportional of the actual size.
- If only one of the maximum bounds are provided, ie., either width or height, then that image is scaled down proportionally to use that value for corresponding dimension.
- If maximum bounds are not provided, ie., in the sample code if there are zeros, then the actual image is returned.
protected Bitmap GetScaledPicture(Bitmap source, int maxWidth, int maxHeight)
{
int width, height;
float aspectRatio = (float)source.Width / (float)source.Height;
if ((maxHeight > 0) && (maxWidth > 0))
{
if ((source.Width < maxWidth) && (source.Height < maxHeight))
{
//Return unchanged image
return source;
}
else if (aspectRatio > 1)
{
// Calculated width and height,
// and recalcuate if the height exceeds maxHeight
width = maxWidth;
height = (int)(width / aspectRatio);
if (height > maxHeight)
{
height = maxHeight;
width = (int)(height * aspectRatio);
}
}
else
{
// Calculated width and height,
// and recalcuate if the width exceeds maxWidth
height = maxHeight;
width = (int)(height * aspectRatio);
if (width > maxWidth)
{
width = maxWidth;
height = (int)(width / aspectRatio);
}
}
}
else if ((maxHeight == 0) && (source.Width > maxWidth))
{
// If MaxHeight is not provided (unlimited), and
// the source width exceeds maxWidth,
// then recalculate height
width = maxWidth;
height = (int)(width / aspectRatio);
}
else if ((maxWidth == 0) && (source.Height > maxHeight))
{
// If MaxWidth is not provided (unlimited), and the
// source height exceeds maxHeight, then
// recalculate width
height = maxHeight;
width = (int)(height * aspectRatio);
}
else
{
//Return unchanged image
return source;
}
Bitmap newImage = GetResizedImage(source, width, height);
return newImage;
}
Resizing Images with High Quality Rendering
The resizing of the original image is done using the System.Drawing.Graphics object and it's methods. Various properties of the graphics object help to render the high quality resized.
protected Bitmap GetResizedImage(Bitmap source, int width, int height)
{
//This function creates the thumbnail image.
//The logic is to create a blank image and to
// draw the source image onto it
Bitmap thumb = new Bitmap(width, height);
Graphics gr = Graphics.FromImage(thumb);
gr.InterpolationMode = InterpolationMode.HighQualityBicubic;
gr.SmoothingMode = SmoothingMode.HighQuality;
gr.PixelOffsetMode = PixelOffsetMode.HighQuality;
gr.CompositingQuality = CompositingQuality.HighQuality;
gr.DrawImage(source, 0, 0, width, height);
return thumb;
}
