in

dotnet.org.za

South African .NET Developer Portal

The Bumpy Blog

Bumpy's Bedside Story

Creating Thumbnails on the fly

Haven't been blogging now for awhile.  Been doing a few websites for pocket money and some free ones.
The last free one I did was for the Christian Motorcyclists Association.  They gave me photo's (by the hundreds) of sizes ranging from 1Mb to 5Mb in size.  I needed to create a gallery and I wasn't feeling up to creating thumbnails for every image. 

I looked around for some code and found a way to resize the images to 300px width and about 300kb in size.  That was still way to big for a way too little pixel size / quality.  After some time of playing around I got to this.  It works great. 
Have a look at it http://www.cmasa.org.za/gallery.aspx?IF=events/memorialrun/2005/images.

So...  Whats the code:
To get the thumbnails, I just set a parameter "IF" - Image Folder, when calling gallery.aspx:

        private void Page_Load(object sender, System.EventArgs e)
        {
            System.Text.StringBuilder sb = 
new System.Text.StringBuilder();
            
if (!this.IsPostBack)
            {
                
string imagefolder = "images/";
                
int _page = 1;

                
if (Request["IF"] != null)
                    imagefolder = Request["IF"].ToString();
                
if (Request["P"] != null)
                    _page = Convert.ToInt32(Request["P"]);

                
string[] files =
System.IO.Directory.GetFiles(Server.MapPath(imagefolder));
                sb.Append("<br>&nbsp;&nbsp;");
                
int cnt = 0;

                
int interval = 25;
                
int start = (_page - 1) * interval;
                
int stop = start + interval;
                
if (start >= files.Length) start = 0;
                
if (stop >= files.Length) stop = files.Length - 1;

                
for (int lp = start; lp < stop; lp++)
                {
                    
if (files[lp].ToLower().IndexOf(".lck") == -1)
                        
if ((files[lp].ToLower().IndexOf(".jpg") > -1)
|| (files[lp].ToLower().IndexOf(".jpeg") > -1) || (files[lp].ToLower().IndexOf(".gif") > -1)
|| (files[lp].ToLower().IndexOf(".bmp") > -1))
                        {
                            
// Calling getimage.aspx with Thumbnail width of 100px
                            
sb.Append("<img src=\"getimage.aspx?f=" + imagefolder + "/"
+ files[lp].Substring(files[lp].LastIndexOf("\\") + 1)
 + "&w=100\" alt=\"Click image to enlarge\" border=\"0\" onClick=\"return enlarge('"
+ imagefolder + "/" + files[lp].Substring(files[lp].LastIndexOf("\\")
 + 1) + "',event,'center',500,453)\">&nbsp;&nbsp;");
                            cnt++;

                            
if (cnt == 5)
                            {
                                cnt = 0;
                                sb.Append("<br>&nbsp;&nbsp;");
                            }
                        }
                }
                Double validator = (Double)files.Length / (Double)interval;

                sb.Append("<br><strong>Page: [</strong>");
                
if (_page > 1)
                    sb.Append("&nbsp<a href=\"gallery.aspx?IF="
+ imagefolder + "&amp;P=" + Convert.ToString(_page - 1) + "\">&lt;&lt;</a>");
                
else
                    
sb.Append("&nbsp&lt;&lt;");
                
for (int lp = 0; lp < Math.Ceiling(validator); lp++)
                {
                    
if (_page == lp + 1)
                        sb.Append("&nbsp" + Convert.ToString(lp + 1));
                    
else
                        
sb.Append("&nbsp<a href=\"gallery.aspx?IF="
+ imagefolder + "&amp;P="
+ Convert.ToString(lp + 1) + "\">" + Convert.ToString(lp + 1) + "</a>");
                }
                
if (_page < Math.Ceiling(validator))
                    sb.Append("&nbsp<a href=\"gallery.aspx?IF="
+ imagefolder + "&amp;P="
+ Convert.ToString(_page + 1) + "\">&gt;&gt;</a>");
                
else
                    
sb.Append("&nbsp&gt;&gt;");

                sb.Append("<strong>]</strong><br><br>");
                litImages.Text = sb.ToString();
            }
        }

        
private System.Drawing.Image ResizeImage(string file, int width)
        {
            
int factor = 2;
            System.Drawing.Image original = System.Drawing.Image.FromFile(file);
            factor = original.Width / width;

            Size nSize = 
new Size(original.Width / factor, original.Height / factor);
            
return ResizeImage(file, nSize);

        }
        
private System.Drawing.Image ResizeImage(string file, Size nSize)
        {
            System.Drawing.Image original = System.Drawing.Image.FromFile(file);
            System.Drawing.Image gdi = 
new Bitmap(nSize.Width, nSize.Height);
            Graphics grfx = Graphics.FromImage(gdi);

            grfx.InterpolationMode = InterpolationMode.HighQualityBicubic;
            grfx.DrawImage(original,
                
new Rectangle(new Point(0, 0), nSize),
new 
Rectangle(new Point(0, 0), original.Size),
                GraphicsUnit.Pixel);

            grfx.Dispose();
            
return gdi;
        }

This then calls the getimage.aspx with a W param to indicate the width of the thumbnail.

        private void Page_Load(object sender, System.EventArgs e)
        {
            
string file = Request["f"];
            
int width = int.Parse(Request["w"]);

            Response.ContentType = "image/jpeg";

            FileStream fs = File.OpenRead(Server.MapPath(file));
            BinaryReader br = 
new BinaryReader(fs);
                            
            
byte[] imgbytes = new byte[fs.Length];
            imgbytes = br.ReadBytes(imgbytes.Length);

            ImageConverter ic = 
new ImageConverter();
            System.Drawing.Image img = (System.Drawing.Image)ic.ConvertFrom(imgbytes);

            
            Decimal picwidth = img.Width;
            Decimal finalwidth = width;
            Decimal tmp = finalwidth / picwidth;
                            
            
int picHeight = (int)((Decimal)img.Height * tmp);

            
if (picHeight > finalwidth)
            {
                
// Image is Portrait
                
img.RotateFlip(RotateFlipType.Rotate90FlipNone);

                picwidth = img.Width;
                finalwidth = width;
                tmp = finalwidth / picwidth;
                            
                picHeight = (
int)((Decimal)img.Height * tmp);
            }

            System.Drawing.Image thumbnailImage = img.GetThumbnailImage((
int)finalwidth, picHeight,
new 
System.Drawing.Image.GetThumbnailImageAbort(ThumbnailCallback), IntPtr.Zero);

            Graphics oGraphic =  Graphics.FromImage(thumbnailImage);

            oGraphic.CompositingQuality = CompositingQuality.HighQuality ;

            oGraphic.SmoothingMode = SmoothingMode.HighQuality ;

            oGraphic.InterpolationMode = InterpolationMode.HighQualityBicubic ;

            Rectangle oRectangle = 
new Rectangle(0, 0, (int)finalwidth, picHeight);

            oGraphic.DrawImage(img, oRectangle);

            MemoryStream imageStream = 
new MemoryStream();
            thumbnailImage.Save(imageStream, System.Drawing.Imaging.ImageFormat.Jpeg);
            
// make byte array the same size as the image
            
byte[] imageContent = new Byte[imageStream.Length];
            
// rewind the memory stream
            
imageStream.Position = 0;
            
// load the byte array with the image
            
imageStream.Read(imageContent, 0, (int)imageStream.Length);


            br.Close();
            
//byte[] bytes = System.Text.ASCIIEncoding.ASCII.GetBytes(DATA);
            
Response.BinaryWrite(imageContent);
            
        }

I think it works pretty nice.  The major breakthrough came when I did this:

            System.Drawing.Image thumbnailImage = img.GetThumbnailImage((int)finalwidth, picHeight,
new System.Drawing.Image.GetThumbnailImageAbort(ThumbnailCallback), IntPtr.Zero);

            Graphics oGraphic =  Graphics.FromImage(thumbnailImage);

            oGraphic.CompositingQuality = CompositingQuality.HighQuality ;

            oGraphic.SmoothingMode = SmoothingMode.HighQuality ;

            oGraphic.InterpolationMode = InterpolationMode.HighQualityBicubic ;

            Rectangle oRectangle = 
new Rectangle(0, 0, (int)finalwidth, picHeight);

            oGraphic.DrawImage(img, oRectangle);

This made the same image go from the 2Mb image to a 700px width image with a filesize of 50Kb.
I then take this 50kb file and make a thumbnail with the same code and get a 1 - 3 kb file to display.

powered by IMHO 1.3

Published May 30 2006, 03:57 PM by deonvs
Filed under: ,

Comments

No Comments

Leave a Comment

(required)  
(optional)
(required)  

Enter the numbers above:
Add
Powered by Community Server (Commercial Edition), by Telligent Systems