%@ WebHandler Language="C#" Class="ImageHandler" %>
using System;
using System.Web;
///
/// www.DotNetManiac.info
/// November 14 2005 - [created]
/// January 16 2005 - [revised]
/// February 22 2006 - [revised]
/// May 08 2006 - [revised]
/// August 18 2007 - [revised]
/// August 12 2009 - [revised]
/// November 24 2009 - [revised]
/// December 15 2009 - [revised]
///
/// Creates a dynamic image and returns it in the outputstream for an img src
/// This takes away the overhead of using an aspx page. Commonly used for
/// creating thumbnail images or zooming in or out of images.
/// This implimentation works with JPG images only.
///
/// Max image size is set to avoid performance issues.
///
/// If constrain proportions is set to true, then image will scale based on
/// requested width. Otherwise image will be forced to requested dimensions
/// which might produce a slightly distorted image.
///
/// Update on May 08 2006
/// Allows constrain proportions to be used. If constrain
/// proportions is set to true, then image will scale based on
/// requested width. Otherwise image will be forced to requested dimensions
/// which might produce a slightly distorted image.
///
/// Update August 18 2006 - ported to C#
/// changed the method of resizing to use a Graphics object which produces
/// a much better quality image regardless of dimensions while only having a
/// slightly larger image size than the bitmap.GetThumbnailImage method.
/// Also general code cleanup
///
/// Update August 12 2009
/// Code was reorganized for better maintainability. Use of USING blocks were added
/// for bitmap and graphic objects.
///
/// Update November 24 2009 - Added ability to rotate images 90, 180, and 270 degrees.
///
/// Update December 15 2009 - Fixed a bug that didn't resize portrait images properly.
///
public class ImageHandler : IHttpHandler
{
// incoming query string variables
private string imagePath = string.Empty; // path= virtual path required
private string imageWidth = "0"; // w= 0 means use original
private string imageHeight = "0"; // h=
private string imageQuality = "0"; // q=
private string constrainProportions = "true"; // cp= true or false
private string rotation = "0"; // r= rotation in degrees, optional, 0 is default.
private const Int32 maxQuality = 100;
private const Int32 minQuality = 30;
private const string imageNotFound = "~/App_Images/image_not_found.jpg";
private const string mimeType = "image/jpeg";
public void ProcessRequest(HttpContext context)
{
// get query string parameters
imagePath = context.Request.QueryString["path"];
imageWidth = context.Request.QueryString["w"];
imageHeight = context.Request.QueryString["h"];
imageQuality = context.Request.QueryString["q"];
constrainProportions = context.Request.QueryString["cp"];
rotation = context.Request.QueryString["r"];
// sets the HTTP MIME type of the output stream.
// jpeg is default
context.Response.ContentType = mimeType;
// clear all content output from the buffer stream
context.Response.Clear();
// response is cacheable by clients and shared (proxy) caches
context.Response.Cache.SetCacheability(HttpCacheability.Public);
// Buffer response so that page is sent
// after processing is complete.
context.Response.BufferOutput = true;
if (System.IO.File.Exists(HttpContext.Current.Server.MapPath(imagePath)))
{
imagePath = HttpContext.Current.Server.MapPath(imagePath);
}
else
{
// displays an empty image holder or make sure you have a not found image
imageQuality = "100";
imagePath = HttpContext.Current.Server.MapPath(imageNotFound);
}
Int32 originalWidth = 0;
Int32 originalHeight = 0;
Int32 newWidth = 0;
Int32 newHeight = 0;
Int64 quality = 0;
// set the quality of the jpeg image returned.. 30 (low) - 100 (high)
if (Int64.TryParse(imageQuality, out quality))
{
if (quality > maxQuality) { quality = maxQuality; }
if (quality < minQuality) { quality = minQuality; }
}
else
{ quality = maxQuality; }
// ENCODING
System.Drawing.Imaging.Encoder encoder =
System.Drawing.Imaging.Encoder.Quality;
System.Drawing.Imaging.EncoderParameter encoderParameter =
new System.Drawing.Imaging.EncoderParameter(encoder, quality);
// create an array with one parameter; quality
System.Drawing.Imaging.EncoderParameters codecParams =
new System.Drawing.Imaging.EncoderParameters(1);
codecParams.Param[0] = encoderParameter;
// Gets the codecs for this image type (jpeg)
System.Drawing.Imaging.ImageCodecInfo codecInfo = getEncoderInfo();
// Create a bitmap to hold new image, uses Bitmap.GetThumbnailImage
using (System.Drawing.Bitmap bitmapOriginal = new System.Drawing.Bitmap(imagePath))
{
originalWidth = bitmapOriginal.Width;
originalHeight = bitmapOriginal.Height;
Int32.TryParse(imageWidth, out newWidth);
Int32.TryParse(imageHeight, out newHeight);
if (newWidth > originalWidth) { newWidth = originalWidth; }
if (newHeight > originalHeight) { newHeight = originalHeight; }
// Constrain Proportions provides scaling by width
// False by default which forces width and height - when exact size required
if (!string.IsNullOrEmpty(constrainProportions)
&& constrainProportions.Equals("true", StringComparison.OrdinalIgnoreCase))
{
newWidth = Convert.ToInt32(imageWidth);
Double scaleFactor = 0.0;
// scale the image based on the width
if (originalWidth > originalHeight)
{
// landscape
Int32 largestDimension = (Math.Max(originalWidth, originalHeight));
scaleFactor = ((Double)newWidth / (Double)largestDimension);
}
else
{
// portrait
Int32 smallestDimension = (Math.Min(originalWidth, originalHeight));
scaleFactor = ((Double)newWidth / (Double)smallestDimension);
}
newHeight = Convert.ToInt32((originalHeight * scaleFactor));
}
// Create the new bitmap image
using (System.Drawing.Bitmap bitmapNew =
new System.Drawing.Bitmap(newWidth, newHeight, System.Drawing.Imaging.PixelFormat.Format24bppRgb))
{
// use the same resolution
bitmapNew.SetResolution(bitmapOriginal.HorizontalResolution, bitmapOriginal.VerticalResolution);
// Create the graphics object to draw the old bitmap on the new sized bitmap.
using (System.Drawing.Graphics graphic = System.Drawing.Graphics.FromImage(bitmapNew))
{
// resize using the highest possible quality for best results
graphic.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
graphic.DrawImage(bitmapOriginal,
new System.Drawing.Rectangle(0, 0, newWidth, newHeight), // destination
new System.Drawing.Rectangle(0, 0, originalWidth, originalHeight), //source
System.Drawing.GraphicsUnit.Pixel); //using pixels
}
// Rotate the bitmap
switch (Convert.ToInt32(rotation))
{
case 90:
bitmapNew.RotateFlip(System.Drawing.RotateFlipType.Rotate90FlipNone);
break;
case 180:
bitmapNew.RotateFlip(System.Drawing.RotateFlipType.Rotate180FlipNone);
break;
case 270:
bitmapNew.RotateFlip(System.Drawing.RotateFlipType.Rotate270FlipNone);
break;
default:
// always show as original
bitmapNew.RotateFlip(System.Drawing.RotateFlipType.RotateNoneFlipNone);
break;
}
// context.Response.OutputStream enables binary output to the outgoing HTTP content body.
// codecInfo is the image type (jpeg)
// codecParams is the quality
bitmapNew.Save(context.Response.OutputStream, codecInfo, codecParams);
}
}
}
///
/// Return the codec info for jpeg images
///
///
///
private System.Drawing.Imaging.ImageCodecInfo getEncoderInfo()
{
System.Drawing.Imaging.ImageCodecInfo[] encoders;
encoders = System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders();
Int32 i = 0;
while (i < encoders.Length)
{
if (encoders[i].MimeType == mimeType)
{
return encoders[i];
}
i++;
}
return null;
}
public bool IsReusable
{ get { return false; } }
}