Go to DotNetFunda.com
 Welcome, Guest!  
LoginLogin  
Take a break and be productive! read technical jokes.
 Skip Navigation Links Home > Articles > ASP.NET > Dynamically generating thumbnail images in ASP.NET with C# without affecting initial page load time

All Articles | Submit Article |

Dynamically generating thumbnail images in ASP.NET with C# without affecting initial page load time

 Posted on: 4/29/2008 7:02:06 PM by SheoNarayan | Views: 6076 | Category: ASP.NET | Level: Intermediate | Print Article
Creating thumbnail with ASP.NET with C#. There are several ways to do that but this way I feel much better and efficient and also this doesn't affect initial page load time.

 Get Career Counseling  
DotNetFunda.Com brings you a FREE Career Counseling section where you can ask any type of career related question. Ask now!

Introduction

While working for a website or an web application, you must have came across a situation where you need to display a thumbnail images for a larger images. There are several work around for it but I am going to show how to do that in the much better and efficient way, in this way your initial page load time will not be delayed because of the thumbnail images.

Approach

My approach of creating thumbnail is to create an arrays of bytes at run time and specify the img src attribute to it. I will also display NoImage.gif if my no source is being given to the function or any error occurred while dynamically generating thumbnail images.

To do this you will have to create a simple .aspx page that contains nothing but a Page_Load event.
ShowImage.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="ShowImage.aspx.cs" Inherits="images_ShowImage" %>


<!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>Show Image</title>
</head>
<body>
<form id="form1" runat="server">
<div>

</div>
</form>
</body>
</html>

Just right click to your project and add a .aspx page with default contents mostly similar to above.

ShoeImage.ascx.cs
protected void Page_Load(object sender, EventArgs e)

{
if (!Page.IsPostBack)
{
Response.Clear();
int maxHeight = 200 // you can get from your config file;
int maxWidth = 250 // you can get from your config file;
if (Request["width"] != null)
{
maxWidth = Int32.Parse(Request["width"].ToString());
}
if (Request["height"] != null)
{
maxHeight = Int32.Parse(Request["height"].ToString());
}


string imageName = Request.QueryString["image"];
string extension = System.IO.Path.GetExtension(Server.MapPath(imageName));

byte[] pBuffer = Utility.CreateThumbnail(imageName, maxHeight, maxWidth, extension);
//set response content type: image/jpeg, image/gif, image/png, etc...
Response.ContentType = "image/" + extension;
//write the image to the output stream
Response.OutputStream.Write(pBuffer, 0, pBuffer.Length);

Response.End();
}
}

In the above Page_Load method, first I am clearing all the contents of the page by using Response.Clear() then I am getting my standard height and width of my thumbnail images. As specified you may specify it in your config file and get it here.

Again, I am checking if I am getting any width and height attributes as a querystring then I am storing them into my width and height variable. I am also getting image path from the "image" querystring, as I am trying to get thumbnail created for variety of images format so I am getting the extension of the image name too here itself.

Now I have declared a byte variable and calling my function that will actually generate the thumbnail image. You can keep the following function in any of your generic .cs file, In my case I have kept into utility.cs file.

CreateThumbnail function
/// <summary>

/// Create thumbnail of the image
/// </summary>
/// <param name="path"></param>
/// <param name="maxHeight"></param>
/// <param name="maxWidth"></param>
/// <param name="extension"></param>
/// <returns></returns>
public static byte[] CreateThumbnail(string path, int maxHeight, int maxWidth, string extension)
{
path = HttpContext.Current.Server.MapPath(path);
System.Drawing.Image img = System.Drawing.Image.FromFile(path);
extension = extension.ToLower();

byte[] buffer = null;
try
{
int width = img.Size.Width;
int height = img.Size.Height;

bool doWidthResize = (maxWidth > 0 && width > maxWidth && width > maxHeight);
bool doHeightResize = (maxHeight > 0 && height > maxHeight && height > maxWidth);

//only resize if the image is bigger than the max
if (doWidthResize || doHeightResize)
{
int iStart;
Decimal divider;
if (doWidthResize)
{
iStart = width;
divider = Math.Abs((Decimal)iStart / (Decimal)maxWidth);
width = maxWidth;
height = (int)Math.Round((Decimal)(height / divider));
}
else
{
iStart = height;
divider = Math.Abs((Decimal)iStart / (Decimal)maxHeight);
height = maxHeight;
width = (int)Math.Round((Decimal)(width / divider));
}
System.Drawing.Image newImg = img.GetThumbnailImage(width, height, null, new System.IntPtr());
try
{
using (MemoryStream ms = new MemoryStream())
{
if (extension.IndexOf("jpg") > -1)
{
newImg.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
}
else if (extension.IndexOf("png") > -1)
{
newImg.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
}
else if (extension.IndexOf("gif") > -1)
{
newImg.Save(ms, System.Drawing.Imaging.ImageFormat.Gif);
}
else // if (extension.IndexOf("bmp") > -1)
{
newImg.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
}
buffer = ms.ToArray();
}
}
finally
{
newImg.Dispose();
}
}
}
catch
{
System.Drawing.Image imNoimage = System.Drawing.Image.FromFile("/images/noimage.gif");
try
{
using (MemoryStream ms = new MemoryStream())
{
imNoimage.Save(ms, System.Drawing.Imaging.ImageFormat.Gif);
buffer = ms.ToArray();
}
}
finally
{
imNoimage.Dispose();
}
}
finally
{
img.Dispose();
}
return buffer;
}

In the above function, i am getting the actual path of the image and creating an image object from the image path parameter passed to this function. Now I am getting the width and height property of the image I got and deciding whether I need to resize my image or not to best fit based on the standard height and width I am getting from my Page_Laod method.

After I have decided the best fit height and width of the image I am creating an another image object newImg and getting thumbnail (img.GetThumbnailImage(width, height, null, new System.IntPtr());) using the GetThumbnailImage method of the above image object.

Now I have my thumbnail created as newImg, I have to save it to the MemoryStream based on the image format I have got from the Page_Laod (.gif, .jpg etc). For that I am checking the extension of the image I have got and saving the image in that format using newImg.Save(ms, System.Drawing.Imaging.ms, System.Drawing.Imaging.ImageFormat.Jpeg/png/gif););. Once I have image saved into MemoryStream, I am converting it into array of bytes by using ToArray() method of MemoryStream (ms.ToArray()).

Now what if an error occurred, in that case I need to display my NoImage,gif , for that I have written my code into Catch block in the same way I had written for my image I had got from Page_Load method (creating Image object from the noimage.gif and converting that into bytes of array).

At last this function is returning array of bytes to my Page_Load method.

Now, In Page_Load method of the ShowImage.aspx I have my thumbnail image in the form of bytes of array. The next thing I have to do is to specify the src attributes of img to this byte. For this I have written following code

// Exerts from above function
Response.ContentType = "image/" + extension;
Response.OutputStream.Write(pBuffer, 0, pBuffer.Length);
Response.End();

I am setting the response content type based on the image extension I got as source by querystring, then I am specifying OutputStream.Write method of Respose object with an array of bytes and its length as parameter ( Response.OutputStream.Write(pBuffer, 0, pBuffer.Length);). As soon as I did this I am done so I am instructing to end the response now for this page by specifying Response.End() method.

How to call

To call the above created thumbnail functionality you need to specify the src attribute of the img element to ShowImage.aspx file and specify the requeired querystring value (In my case image is must and width and height is optional)
<img src="/images/ShowImage.aspx?image=/images/sheonarayan.gif" />[


OR

<img src="/images/ShowImage.aspx?image=/images/sheonarayan.gif&width=200&height=250" />



Conclusion

When you will use above way of creating thumbnail images, you will notice that your entire pages will be loaded then one by one your thumbnail images will be generated on the fly and it will be displayed on the page so It is not affecting your initial page load time.

If you have any comment of suggestions, please write to me.

Thanks and Happy coding !!!

Interesting?   Bookmark and Share


About Sheo Narayan

Experience:6 year(s)
Home page:http://sheonarayan.myfunda.net/
Member since:Tuesday, July 08, 2008
Biography:Throughout 1st in all educational exams.
Major qualifications: HDCS, ADCA, MCA, MCTS
Location: Hyderabad, India
 Latest post(s) from SheoNarayan

   ◘ Ensuring button is clicked only once, Confirmation and Please wait message for ASP.NET Form posted on 7/3/2009 3:34:15 PM
   ◘ Setting up Start Options in Visual Studio and Visual Web Developer posted on 6/28/2009 7:53:02 AM
   ◘ Website vs Web Application - Embedded resources posted on 6/23/2009 10:10:20 PM
   ◘ Adding removing xml attribute from XML File in .NET posted on 6/21/2009 12:55:43 AM
   ◘ Working with Themes in ASP.NET posted on 6/8/2009 12:13:10 PM


Response(s) to this Article
Posted by: SheoNarayan | Posted on: 05 Aug 2008 04:11:57 AM
Just try specifying path from the root of your application.

<img src="/images/ShowImage.aspx?image=/images/sheonarayan.gif" />

Here, in this case both files ShowImage.aspx and sheonarayan.gif both are kept in images folder.

Thanks
Posted by: Sruthi | Posted on: 05 Aug 2008 02:21:34 AM
hai narayan,
its show an error taht path cannot found,i am not getting at all,i giving right path,can u help me?

 Submit Article

About Us | Contact Us | Privacy Policy | Terms of Use | Link Exchange | Members | Go Top
All rights reserved to DotNetFunda.Com. Logos, company names used here if any are only for reference purposes and they may be respective owner's right or trademarks.
(Best viewed in IE 6.0+ or Firefox 2.0+ at 1024 * 768 or higher)