原文:http://www.thebrainparasite.com/post/Creating-great-thumbnails-in-ASPNET.aspx
使用ASP.NET內建的功能建立縮圖是非常方便和容易實現的。
int width = 190;
int height = 190;
Bitmap source = new Bitmap("c:\someimage.gif");
System.Drawing.Image thumb = source.GetThumbnailImage(width,height,null,IntPtr.Zero);
(31.7k)
麻煩的是,它生產的縮圖品質相對較差且產生的檔案過大。該方法產生的縮圖往往看起來非常汙濁,或許很多情況下這對你所需要的來說已經足夠好。
一個選擇
我常用的一個方法是使用 System.Drawing.Graphics 庫 重畫映像,這實現起來非常簡單,但是卻有非常好的效果。下面是我用來產生縮圖的一個樣本函數
public static Bitmap CreateThumbnail(Bitmap source, int thumbWi, int thumbHi, bool maintainAspect)
{
// return the source image if it's smaller than the designated thumbnail
if (source.Width < thumbWi && source.Height < thumbHi) return source;
System.Drawing.Bitmap ret = null;
try
{
int wi, hi;
wi = thumbWi;
hi = thumbHi;
if (maintainAspect)
{
// maintain the aspect ratio despite the thumbnail size parameters
if (source.Width > source.Height)
{
wi = thumbWi;
hi = (int)(source.Height * ((decimal)thumbWi / source.Width));
}
else
{
hi = thumbHi;
wi = (int)(source.Width * ((decimal)thumbHi / source.Height));
}
}
// original code that creates lousy thumbnails
// System.Drawing.Image ret = source.GetThumbnailImage(wi,hi,null,IntPtr.Zero);
ret = new Bitmap(wi, hi);
using (Graphics g = Graphics.FromImage(ret))
{
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.FillRectangle(Brushes.White, 0, 0, wi, hi);
g.DrawImage(source, 0, 0, wi, hi);
}
}
catch
{
ret = null;
}
return ret;
}
(10.5k)
這個函數是很方便的,因為的它的一個參數用來標識是否維在產生縮圖的時候維持映像的長寬比。這個縮圖魔法發生在下面的代碼中
using (Graphics g = Graphics.FromImage(ret))
{
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.FillRectangle(Brushes.White, 0, 0, wi, hi);
g.DrawImage(source, 0, 0, wi, hi);
}
這個方法有點慢但是卻讓人難以捨棄,從下面的插圖的對比可見:
(31.7k) (10.5k)
我想說這是檔案和映像品質都非常棒的實現,但是……
我們可以做的更好
現在我門可以混入 JPEG壓縮來真正的最佳化結果, 我不想假裝完全瞭解JPEG壓縮的代碼如何工作的,但它確實扭轉了乾坤。
//Configure JPEG Compression Engine
System.Drawing.Imaging.EncoderParameters encoderParams = new System.Drawing.Imaging.EncoderParameters();
long[] quality = new long[1];
quality[0] = 75;
System.Drawing.Imaging.EncoderParameter encoderParam = new System.Drawing.Imaging.EncoderParameter(System.Drawing.Imaging.Encoder.Quality, quality);
encoderParams.Param[0] = encoderParam;
System.Drawing.Imaging.ImageCodecInfo[] arrayICI = System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders();
System.Drawing.Imaging.ImageCodecInfo jpegICI = null;
for (int x = 0; x < arrayICI.Length; x++)
{
if (arrayICI[x].FormatDescription.Equals("JPEG"))
{
jpegICI = arrayICI[x];
break;
}
}
這段代碼設定了儲存經過壓縮的縮圖所需的 encoderParameters 參數,quality[0] 的值設定壓縮的層級,我曾經針對某些應用設定像40這麼低的值也成功了,俺是當品質要求比較高的時候 ,我發現設定為75非常好。使用這段代碼你能夠在產生縮圖之前使用 JPEG 壓縮演算法,當儲存的時候把 encoderParamaters 作為參數,例如:
System.Drawing.Image myThumbnail = CreateThumbnail(myBitmap,Width,Height,false);
//Configure JPEG Compression Engine
System.Drawing.Imaging.EncoderParameters encoderParams = new System.Drawing.Imaging.EncoderParameters();
long[] quality = new long[1];
quality[0] = 75;
System.Drawing.Imaging.EncoderParameter encoderParam = new System.Drawing.Imaging.EncoderParameter(System.Drawing.Imaging.Encoder.Quality, quality);
encoderParams.Param[0] = encoderParam;
System.Drawing.Imaging.ImageCodecInfo[] arrayICI = System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders();
System.Drawing.Imaging.ImageCodecInfo jpegICI = null;
for (int x = 0; x < arrayICI.Length; x++)
{
if (arrayICI[x].FormatDescription.Equals("JPEG"))
{
jpegICI = arrayICI[x];
break;
}
}
myThumbnail.Save(Path.Combine(SavePathThumb, fileName), jpegICI, encoderParams);
myThumbnail.Dispose();
(2.39k)
2.39K 大小 看起來依然很棒
結論和最後比較
這是最後三張縮圖從檔案大小最大到最小的效果對比
最大 = 31.7k
未壓縮重繪 = 10.5k (67% smaller)
壓縮重繪 = 2.39k (92% smaller)
難以捨棄的結果啊,縮圖產生函數和JPEG壓縮的原始碼 在下邊 :
ThumbnailGenerator.cs (1.97 kb)
JPEGCompressionConfig.cs (969.00 bytes)