Posted
Posted 2/8/2010 11:58:46 PM
Creating a thumbnail in C# is fun and easy! Unfortunately, creating one with any halfway decent quality is a huge pain in the ass. Especially if you want to write it to a File instead of a Stream. Cutting to the chase, here's how you do it:
/// <summary>Creates a thumbnail of a given image.</summary>
/// <param name="inFile">Fully qualified path to file to create a thumbnail of</param>
/// <param name="outFile">Fully qualified path to created thumbnail</param>
/// <param name="x">Width of thumbnail</param>
/// <returns>flag; result = is success</returns>
public static bool CreateThumbnail(string inFile, string outFile, int x)
{
// Validation - assume 16x16 icon is smallest useful size. Smaller than that is just not going to do us any good anyway. I consider that an "Exceptional" case.
if (string.IsNullOrEmpty(inFile)) throw new ArgumentNullException("inFile");
if (string.IsNullOrEmpty(outFile)) throw new ArgumentNullException("outFile");
if (x < 16) throw new ArgumentOutOfRangeException("x");
if (!File.Exists(inFile)) throw new ArgumentOutOfRangeException("inFile", "File does not exist: " + inFile);
// Mathematically determine Y dimension
int y;
using (Image img = Image.FromFile(inFile)) {
double xyRatio = (double)x / (double)img.Width;
y = (int)((double)img.Height * xyRatio); }
// All this crap could have easily been Image.Save(filename, x, y)... but nooooo....
using (Bitmap bmp = new Bitmap(inFile))
using (Bitmap thumb = new Bitmap((Image)bmp, new Size(x, y)))
using (Graphics g = Graphics.FromImage(thumb)) {
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
System.Drawing.Imaging.ImageCodecInfo codec = System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders()[1];
System.Drawing.Imaging.EncoderParameters ep2 = new System.Drawing.Imaging.EncoderParameters(1);
ep2.Param[0] = new System.Drawing.Imaging.EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 100L);
g.DrawImage(bmp, new Rectangle(0,0,thumb.Width, thumb.Height));
try {
thumb.Save(outFile, codec, ep2);
return true; }
catch { return false; } }
}
This example creates a 400KB thumbnail of a 5MB file (4000x3000 to 900x675) within about a second. Reduce quality, remove antialiasing, or crappify the interpolation mode if you want your implementation to go faster. Personally, I'm patient enough to wait one second.
On a sufficiently related note (and totally uninteresting to most Googlers), the Gallery page now handles automatic thumbnail generation. Figured not everyone wants to bother downloading my 5MB 12.1 Megapixel images nor my 30-100 Megapixel panoramas.
Project Codename MV8
Copyright © 2010 Kevin Connolly. All rights reserved.
Your request ate 44 of my milliseconds.