5,442,164 members and growing! (15,453 online)
Email Password   helpLost your password?
Web Development » ASP.NET » General License: The GNU General Public License (GPL)

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

By Sheo Narayan

Generate thumbnail on the fly without affecting page load time
C# (C# 1.0, C# 2.0, C# 3.0, C#)

Posted: 11 May 2008
Updated: 4 Jul 2008
Views: 8,262
Bookmarked: 16 times
Announcements
Want a new Job?



Search    
Advanced Search
Sitemap
6 votes for this Article.
Popularity: 2.26 Rating: 2.91 out of 5
0 votes, 0.0%
1
2 votes, 33.3%
2
2 votes, 33.3%
3
2 votes, 33.3%
4
0 votes, 0.0%
5
Note: This is an unedited contribution. If this article is inappropriate, needs attention or copies someone else's work without reference then please Report This Article

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

<%@ 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

   /// Create thumbnail of the image
    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 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)

<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 (GPL)

About the Author

Sheo Narayan


Working in Microsoft technologies for last 6 years
Occupation: Software Developer (Senior)
Company: http://www.DotNetFunda.com
Location: India India

Other popular ASP.NET articles:

Article Top
Sign Up to vote for this article
You must Sign In to use this message board.
FAQ FAQ Noise ToleranceSearch Search Messages 
 Layout  Per page   
 Msgs 1 to 2 of 2 (Total in Forum: 2) (Refresh)FirstPrevNext
Subject  Author Date 
GeneralImprovementmemberEranNachum20:25 19 May '08  
GeneralRe: ImprovementmemberSheo Narayan6:01 1 Jul '08  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 4 Jul 2008
Editor:
Copyright 2008 by Sheo Narayan
Everything else Copyright © CodeProject, 1999-2008
Web17 | Advertise on the Code Project