為了記憶體的佔用或是速度上面的考量,有的時候我們會有為圖檔產生縮圖的需求。產生縮圖的方法很多,多半都需要耗費一點時間,所以有時候我們可能會考慮直接取用圖檔本身就內含的縮圖。

這邊一樣是用WPF內的BitmapDecoder來取用圖檔內含的縮圖。若是Window Form程式的話我們必須額外將PresentationCore.dll、System.Xaml、與WindowsBase.dll加入參考。

實際的程式撰寫部份跟[C#]使用BitmapDecoder快速讀取圖檔的大小這篇類似,用BitmapDecoder.Create將要讀取的圖檔位置帶入,然後取得第一個Frame,裡面的Thumbnail就是我們所需要的縮圖圖檔。這邊要注意到的是,Thumbnail屬性的型態是BitmapSource,若是在Window Form程式中使用必須將BitmapSource轉換成Bitmap才能使用。

… public static Bitmap GetBitmap(this BitmapSource bitmapsource) { Bitmap bitmap; using (MemoryStream outStream = new MemoryStream()) { BitmapEncoder enc = new BmpBitmapEncoder(); enc.Frames.Add(BitmapFrame.Create(bitmapsource)); enc.Save(outStream); bitmap = (new Bitmap(outStream)).Clone() as Bitmap; } return bitmap; } …

public Image GetThumbnail(string file) { var decoder = BitmapDecoder.Create(new Uri(file), BitmapCreateOptions.DelayCreation, BitmapCacheOption.None); var frame = decoder.Frames.FirstOrDefault();

return (frame.Thumbnail == null) ? null : frame.Thumbnail.GetBitmap();

} …

完整的程式範例如下:

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Windows.Media.Imaging; using System.Diagnostics;

namespace WindowsFormsApplication33 { public partial class Form1 : Form { public Form1() { InitializeComponent(); }

	public Image GetThumbnail(string file)
	{
		var decoder = BitmapDecoder.Create(new Uri(file), BitmapCreateOptions.DelayCreation, BitmapCacheOption.None);
		var frame = decoder.Frames.FirstOrDefault();

		return (frame.Thumbnail == null) ? null : frame.Thumbnail.GetBitmap();
	}

	private void button1_Click(object sender, EventArgs e)
	{
		if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
		{
			var file = openFileDialog1.FileName;

			var sw = Stopwatch.StartNew();
			pictureBox1.Image = GetThumbnail(file);
			toolStripStatusLabel1.Text = String.Format("Elapsed {0} ms", sw.ElapsedMilliseconds.ToString());
		}
	}
}

}

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows.Media.Imaging; using System.Drawing; using System.IO;

public static class BitmapSourceExtension { public static Bitmap GetBitmap(this BitmapSource bitmapsource) { Bitmap bitmap; using (MemoryStream outStream = new MemoryStream()) { BitmapEncoder enc = new BmpBitmapEncoder(); enc.Frames.Add(BitmapFrame.Create(bitmapsource)); enc.Save(outStream); bitmap = (new Bitmap(outStream)).Clone() as Bitmap; } return bitmap; } }

程式運作起來會像下面這樣,可以看到抓取4-5 MB的圖檔只需花費43ms。

以這張圖片來說縮圖的大小也有160X120。