[C#]使用BitmapDecoder快速取用圖檔內含的縮圖

[C#]使用BitmapDecoder快速取用圖檔內含的縮圖

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

 

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

image

 

實際的程式撰寫部份跟[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.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.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。

image

 

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

image