Thursday, October 16, 2008

Thumbnailer HTTP Handler

The implementation was to create an image optimizer control that would scale and optimize the quality of the original uploaded image and store the results to a data store (in this case a hard disk), and create an HTTP handler that would create thumbnail images of the optimized images on the fly, at runtime, and in memory (no physical disk space to store the temporary thumbnail file). Following is the code, which displays images either from database or from session.


<%@ WebHandler Language="C#" Class="Handler.Thumbnailer" %>
using System;
using System.Web;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Web.UI;
using System.Drawing.Imaging;
using System.Reflection;
using System.Drawing;
using System.Net;
using System.Web.SessionState;
namespace Handler
{
public class Thumbnailer : IHttpHandler, IRequiresSessionState
{
#region Enumerations
///


/// An internal enumeration defining the thumbnail sizes.
///

internal enum ThumbnailSizeType
{
Small = 72,
Medium = 144,
Large = 288
}
#endregion Enumerations
#region Fields
// Declare and define global constants
private const string IMG_PARAM = "img"; // image parameter
private const string SIZE_PARAM = "size"; // size parameter
// Declare and define default values to class member variables
private ThumbnailSizeType _sizeType = ThumbnailSizeType.Small;
#endregion Fields
#region Methods

///
/// Sets the size of the thumbnail base on the size parameter.
///

/// The size parameter.
private void SetSize(string size)
{
int sizeVal;
if (!Int32.TryParse(size.Trim(), System.Globalization.NumberStyles.Integer, null, out sizeVal))
sizeVal = (int)ThumbnailSizeType.Small;
try
{
this._sizeType = (ThumbnailSizeType)sizeVal;
}
catch
{
this._sizeType = ThumbnailSizeType.Small;
}
}

///
/// Processs the incoming HTTP request.
///

/// Context.
public void ProcessRequest(HttpContext context)
{
if (string.IsNullOrEmpty(context.Request.QueryString[SIZE_PARAM]))
this._sizeType = ThumbnailSizeType.Small;
int _imageId = 0;
if (context.Request.QueryString["img"] != null)
_imageId = Convert.ToInt32(context.Request.QueryString["img"]);



if (_imageId != 0)
{
//Fetch your data from database containing byte array
Byte[] b=your data;
System.Drawing.Image img = System.Drawing.Image.FromStream(new System.IO.MemoryStream(b));
context.Response.ContentType = "image/jpeg";
if (string.IsNullOrEmpty(context.Request.QueryString[SIZE_PARAM]))
{
img.Save(context.Response.OutputStream, ImageFormat.Jpeg);
img.Dispose();
}
else
{
using (System.Drawing.Image tn = this.CreateThumbnail(img))
{
tn.Save(context.Response.OutputStream, ImageFormat.Jpeg);
}
}
}
else
{
//Show image from memory.
if (context.Session["Photo"] != null)
{
System.Drawing.Image img = System.Drawing.Image.FromStream(new System.IO.MemoryStream(context.Session["Photo"] as Byte[]));
context.Response.ContentType = "image/jpeg";
using (System.Drawing.Image tn = this.CreateThumbnail(img))
{
tn.Save(context.Response.OutputStream, ImageFormat.Jpeg);
}
}
}

}
///
/// This method generates the actual thumbnail.
///

///
/// Thumbnail image
private System.Drawing.Image CreateThumbnail(System.Drawing.Image src)
{
int maxSize = (int)this._sizeType;
int w = src.Width;
int h = src.Height;
if (h <> 1024) { h = 768; w = 1024; }
if (h <> 800) { h = 800; w = 600; }
if (w > maxSize)
{
h = (h * maxSize) / w;
w = maxSize;
}
if (h > maxSize)
{
w = (w * maxSize) / h;
h = maxSize;
}

Bitmap bitmap = new Bitmap(w, h);
using (Graphics g = Graphics.FromImage(bitmap))
{
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.DrawImage(src, 0, 0, bitmap.Width, bitmap.Height);
}
return bitmap;
// The third parameter is required and is of type delegate. Rather then create a method that
// does nothing, .NET 2.0 allows for anonymous delegate (similar to anonymous functions in other languages).
//return src.GetThumbnailImage(w, h, delegate() { return false; }, IntPtr.Zero);
}

#endregion Methods


public bool IsReusable
{
get { return true; }
}
}
}

Using This Code:

1.Copy and paste this code in Thumbnailer.ashx file

2. You can display image either from Session or from database by passing img as querystring.

a. Using Session

Session["Photo"]=Array of Image Bytes();

Image1.ImageURL="~/Thumbnailer.ashx";

b. Using img as querystring

Image1.ImageURL="~/Thumbnailer.ashx?img=1"; // where 1 is id of image table containing image data

Happy Coding!!!