System.Drawing.Imaging裡面的GetEncoder在哪?

當你要用.NET Framework對JPEG進行壓縮率的最佳化時,你會大量的使用到System.Drawing.Imaging這個命名空間裡面的各式類別,但是當你網路爬文爬到MSDN裡面的文章How to: Set JPEG Compression Level時,你會發現他的Sample Code裡面有一個很詭異的函式(或者是方法),他的名字叫GetEncoder()。

說是眼盲也好,說是命名空間惹的禍也好,總之在找資料的當下,很多程式設計師沒有辦法在當下得知GetEncoder()表達的意思是什麼,答案其實就寫在MSDN該頁面的下方。

原程式碼段落如下:

private void VaryQualityLevel()
{
	// Get a bitmap.
	Bitmap bmp1 = new Bitmap(@"c:\TestPhoto.jpg");
	ImageCodecInfo jgpEncoder = GetEncoder(ImageFormat.Jpeg);

	// Create an Encoder object based on the GUID 
	// for the Quality parameter category.
	System.Drawing.Imaging.Encoder myEncoder = System.Drawing.Imaging.Encoder.Quality;

	// Create an EncoderParameters object. 
	// An EncoderParameters object has an array of EncoderParameter 
	// objects. In this case, there is only one 
	// EncoderParameter object in the array.
	EncoderParameters myEncoderParameters = new EncoderParameters(1);

	EncoderParameter myEncoderParameter = new EncoderParameter(myEncoder, 50L);
	myEncoderParameters.Param[0] = myEncoderParameter;
	bmp1.Save(@"c:\TestPhotoQualityFifty.jpg", jgpEncoder, myEncoderParameters);

	myEncoderParameter = new EncoderParameter(myEncoder, 100L);
	myEncoderParameters.Param[0] = myEncoderParameter;
	bmp1.Save(@"c:\TestPhotoQualityHundred.jpg", jgpEncoder, myEncoderParameters);

	// Save the bitmap as a JPG file with zero quality level compression.
	myEncoderParameter = new EncoderParameter(myEncoder, 0L);
	myEncoderParameters.Param[0] = myEncoderParameter;
	bmp1.Save(@"c:\TestPhotoQualityZero.jpg", jgpEncoder, myEncoderParameters);
}

傳說中的GetEncoder其實就寫在該頁下方

private ImageCodecInfo GetEncoder(ImageFormat format)
{
	ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders();
	foreach (ImageCodecInfo codec in codecs)
	{
		if (codec.FormatID == format.Guid)
		{
			return codec;
		}
	}
	return null;
}

事後發現我寫的其實與MSDN雷同

下面這些程式碼是我自己之前眼盲沒有看到,翻了很多網路文章才去推測出來的寫法。只不過MSDN的寫法是用物件ID比對,我寫的寫法是用字串比對。這對於不會用ImageFormat.Jpeg比對的人來說,下面這段程式碼或者多有幫助。

/// <summary>
/// 尋訪編碼器
/// </summary>
/// <param name="cTemp">編碼器字串</param>
/// <returns>回傳編碼器(Codec)</returns>
private System.Drawing.Imaging.ImageCodecInfo getEncoder(string cTemp)
{
	System.Drawing.Imaging.ImageCodecInfo[] oCoders = System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders();
	foreach (var oCoder in oCoders)
	{
		//如果有找到Codec的話,就直接將編碼器傳回
		if (oCoder.MimeType.ToLower() == cTemp.ToLower())
		{ return oCoder; }
	}
	//如果沒有找到任何的Codec的話,就傳回null
	return null;
}

結論:下次看MSDN要捲到最下面,一定要確定人家下面已經沒有Sample Code了,這樣可以省下自己大量的時間。與透過網路找到我這篇文章的人共勉之。

System.Drawing.Imaging GetEncoder Encoder JPEGCompressionLevel