[C#]使用BitmapDecoder快速讀取圖檔的大小

  • 17529
  • 0
  • C#
  • 2012-09-07

[C#]使用BitmapDecoder快速讀取圖檔的大小

一般我們想要讀取圖檔的大小,通常在Windows Form中都是直接載入成Bitmap,再去讀取Bitmap物件的長、寬、或是大小屬性,像是像下面這樣撰寫:

using (var image = Bitmap.FromFile(file))
{
	var size = image.Size;
	...
}
...

 

但這樣做會有個問題就是效率會比較差,因為必須將整個圖檔先行載入,圖檔越大就越久,記憶體也吃的兇。

 

比較好的作法應該是直接讀取檔案的檔頭,圖檔的大小資訊再圖檔的檔頭就有了,所以不需要將整個圖檔載入就可以得知,效率也會因此有所增進。比較簡單的作法就是直接使用WPF的功能,若是Window Form程式的話我們可以額外將PresentationCore.dll、System.Xaml、與WindowsBase.dll加入參考。

image

 

並引用System.Windows.Media命名空間。

 

實際撰寫我們可以用BitmapDecoder.Create將要讀取的圖檔位置帶入,然後取得第一個Frame,裡面的PixelWidth與PixelHeight就是我們所要擷取的圖檔大小。

var decoder = BitmapDecoder.Create(new Uri(file), BitmapCreateOptions.DelayCreation, BitmapCacheOption.None);
var frame = decoder.Frames.FirstOrDefault();
			
var size = new Size(frame.PixelWidth, frame.PixelHeight);
...

 

完整的測試範例如下:

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.IO;
using System.Drawing.Imaging;
using System.Windows.Threading;
using System.Windows.Media;
using System.Diagnostics;

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

		private long StopwatchMethod(Action act, int testCount, Boolean returnAverageValue = false)
		{
			var sw = Stopwatch.StartNew();
			for (int i = 0; i < testCount;++i )
				act();

			sw.Stop();
			var elapsedMilliseconds = sw.ElapsedMilliseconds;
			return (returnAverageValue) ? elapsedMilliseconds / testCount : elapsedMilliseconds; 
		}

		public Size GetImageSize1(string file)
		{
			var decoder = BitmapDecoder.Create(new Uri(file), BitmapCreateOptions.DelayCreation, BitmapCacheOption.None);
			var frame = decoder.Frames.FirstOrDefault();
			
			return new Size(frame.PixelWidth, frame.PixelHeight);
		}

		public Size GetImageSize2(string file)
		{
			using (var image = Bitmap.FromFile(file))
			{
				return image.Size;
			}
		}

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

				GetImageSize1(file);
				GetImageSize2(file);

				textBox1.Clear();
				textBox1.Text += "BitmapDecoder" + Environment.NewLine;
				textBox1.Text += StopwatchMethod(() => GetImageSize1(file), 10).ToString() + Environment.NewLine;

				textBox1.Text += Environment.NewLine;
				textBox1.Text += "Bitmap" + Environment.NewLine;				
				textBox1.Text += StopwatchMethod(() => GetImageSize2(file), 10).ToString() + Environment.NewLine;
			}
		}
	}
}

 

實際運行時筆者帶入大概4~5 MB的圖檔,可以看到光運行十次在效能上就有很大的差異。

image

 

Link