Click here to Skip to main content
15,867,453 members
Articles / Programming Languages / C#
Article

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

Rate me:
Please Sign up or sign in to vote.
3.00/5 (8 votes)
4 Jul 2008GPL34 min read 84.3K   26   7
Generate thumbnail on the fly without affecting page load time

Introduction

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.

Background

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

ASP.NET
<%@ 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

C#
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

<param name="""""path""""" />
C#
<summary>   /// Create thumbnail of the image
</summary>    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;
    } 
<param name="""""maxHeight""""" /><param name="""""maxWidth""""" /><param name="""""extension""""" />

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 throw these bytes of images to the page. For this I have written following code

// Exerts from Page_Load method
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 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 the optional querystring value)

ASP.NET
<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 !!!

Originally posted by me at http://www.dotnetfunda.com/articles/article63.aspx

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)


Written By
IT Funda Corporation
India India
Solution of .NET Problems - Get hundreds of .NET How to's

Comments and Discussions

 
Questioncopy of working Code Pin
ZincOianoid28-Nov-13 7:40
ZincOianoid28-Nov-13 7:40 
GeneralMy vote of 2 Pin
cpsglauco23-Oct-12 1:29
cpsglauco23-Oct-12 1:29 
QuestionDymanic Thumbnail Creation Pin
bobby200915-Jun-11 11:07
bobby200915-Jun-11 11:07 
GeneralThumbnailing images Pin
dababy2-Nov-10 0:29
dababy2-Nov-10 0:29 
General//only resize if the image is bigger than the max Pin
Marthinus Groenewald15-Dec-08 3:26
Marthinus Groenewald15-Dec-08 3:26 
GeneralImprovement Pin
EranNachum19-May-08 19:25
EranNachum19-May-08 19:25 
GeneralRe: Improvement Pin
Sheo Narayan1-Jul-08 5:01
Sheo Narayan1-Jul-08 5:01 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.