Image Resizing & Cropping on the fly in .NET - high quality
While developing a CMS for small gallery websites, I decided to store only the original uploaded image and not to create a thumbnail upon uploading.
So, this works, and works pretty well.
I didn't want, of course, to use the html resizing feature, especially not while uploading high res images.
Instead, I created a generic handler that creates the thumbnail image on the fly.
Not only this handler knows how to resize the image, but also to crop it, in case I want all the images to be on a fixed ratio of width and height.
So, how is it done?
There are many blog posts of resizing images on the fly.
where you'll find a code similar to this:
public static Bitmap CreateThumbnail(Bitmap loBMP, int lnWidth, int lnHeight) {
System.Drawing.Bitmap bmpOut = null; try { ImageFormat loFormat = loBMP.RawFormat;
decimal lnRatio; int lnNewWidth = 0; int lnNewHeight = 0;
//*** If the image is smaller than a thumbnail just return it
if (loBMP.Width <> return loBMP;
if (loBMP.Width > loBMP.Height) { lnRatio = (decimal)lnWidth / loBMP.Width; lnNewWidth = lnWidth; decimal lnTemp = loBMP.Height * lnRatio; lnNewHeight = (int)lnTemp; } else { lnRatio = (decimal)lnHeight / loBMP.Height; lnNewHeight = lnHeight; decimal lnTemp = loBMP.Width * lnRatio; lnNewWidth = (int)lnTemp; }
// *** This code creates cleaner (though bigger) thumbnails and properly // *** and handles GIF files better by generating a white background for // *** transparent images (as opposed to black) bmpOut = new Bitmap(lnNewWidth, lnNewHeight); Graphics g = Graphics.FromImage(bmpOut); g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;g.DrawImage(loBMP, 0, 0, lnNewWidth, lnNewHeight);
loBMP.Dispose(); } catch { return null; }
return bmpOut; }
And as for the cropping?
For that there is no other way but to use twice the
g.DrawImage(bmpTemp, new Rectangle(0, 0, width, height));
once for the size, and another time for the cropping...
And last, but not least, THE QUALITY of the jpeg is determined while outputing the image like here:
context.Response.ContentType = "image/jpeg";
EncoderParameters eps = new EncoderParameters(1);
eps.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 100L);
ImageCodecInfo ici = GetEncoderInfo("image/jpeg");
bmp.Save(context.Response.OutputStream, ici, eps);
so there you have it.
cropping, resizing, and good quality output, on the fly.
now, when doing these actions, the server has to 'work hard' on it for every photo, so a good way will be to cache it REAL GOOD...
context.Response.Cache.SetExpires(DateTime.Now.AddYears(1));
context.Response.CacheControl = "public";
context.Response.Expires = 20160; // two weeks
context.Response.Cache.SetCacheability(HttpCacheability.Public);
context.Response.Cache.SetMaxAge(new TimeSpan(1, 0, 0));
context.Response.Cache.SetValidUntilExpires(true);
well, that's it.
enjoy the code...
Comments