如何获取已安装BitmapEncoders / Decoders的列表(WPF世界)?
在WindowsForms世界中,我们可以通过以下方式获取可用的图像编码器/解码器的列表:
System.Drawing.ImageCodecInfo.GetImageDecoders() / GetImageEncoders()
我的问题是,是否有一种方法可以做一些与WPF世界类似的事情,从而使我可以获得可用的列表。
System.Windows.Media.Imaging.BitmapDecoder / BitmapEncoder
解决方案
回答
希望有人会纠正我,如果我错了,但是我认为WPF中没有类似的东西。但是希望这是许多技术进步使我们习惯做事的方式过时的情况之一。就像"我如何上弦电子表吗?"
据我了解,在System.Drawing中需要ImageCodecInfo.GetImageDecoders()的原因与System.Drawing本身的糊涂性质有关:System.Drawing是围绕GDI +的托管包装,它是围绕GDI +的一部分的非托管包装Win32 API。因此,可能有原因会在Windows中没有.NET固有了解的情况下安装新的编解码器。从GetImageDecoders()返回的只是一串字符串,这些字符串通常传递回System.Drawing / GDI +,并用于查找和配置用于读取/保存图像的适当DLL。
另一方面,在WPF中,标准的编码器和解码器内置在框架中,并且,如果我没有记错的话,请不要依赖任何不能保证作为框架一部分安装的内容。以下类继承自BitmapEncoder,并且可与WPF一起使用:BmpBitmapEncoder,GifBitmapEncoder,JpegBitmapEncoder,PngBitmapEncoder,TiffBitmapEncoder,WmpBitmapEncoder。有用于所有相同格式的BitmapDecoder,以及IconBitmapDecoder和LateBoundBitmapDecoder。
我们可能正在处理一个我没有想到的情况,但是在我看来,如果我们必须使用从BitmapEncoder继承但不包含在WPF中的类,则可能是我们自己安装的自定义类与应用程序。
希望这可以帮助。如果我缺少图片的必要部分,请告诉我。
回答
我们必须喜欢.NET反射。我曾在WPF团队工作过,无法想出什么更好的方法。以下代码在我的计算机上生成此列表:
Bitmap Encoders: System.Windows.Media.Imaging.BmpBitmapEncoder System.Windows.Media.Imaging.GifBitmapEncoder System.Windows.Media.Imaging.JpegBitmapEncoder System.Windows.Media.Imaging.PngBitmapEncoder System.Windows.Media.Imaging.TiffBitmapEncoder System.Windows.Media.Imaging.WmpBitmapEncoder Bitmap Decoders: System.Windows.Media.Imaging.BmpBitmapDecoder System.Windows.Media.Imaging.GifBitmapDecoder System.Windows.Media.Imaging.IconBitmapDecoder System.Windows.Media.Imaging.LateBoundBitmapDecoder System.Windows.Media.Imaging.JpegBitmapDecoder System.Windows.Media.Imaging.PngBitmapDecoder System.Windows.Media.Imaging.TiffBitmapDecoder System.Windows.Media.Imaging.WmpBitmapDecoder
代码中有注释,用于在其中添加其他程序集(例如,如果我们支持插件)。另外,我们将要过滤解码器列表以将其删除:
System.Windows.Media.Imaging.LateBoundBitmapDecoder
可以使用构造函数模式匹配进行更复杂的过滤,但是我不想编写它。 :-)
我们现在要做的就是实例化编码器和解码器以使用它们。同样,通过获取编码器解码器的CodecInfo属性,可以获得更好的名称。该类将为我们提供易于理解的名称,包括其他事实。
using System; using System.Linq; using System.Collections.Generic; using System.Reflection; using System.Windows.Media.Imaging; namespace Codecs { class Program { static void Main(string[] args) { Console.WriteLine("Bitmap Encoders:"); AllEncoderTypes.ToList().ForEach(t => Console.WriteLine(t.FullName)); Console.WriteLine("\nBitmap Decoders:"); AllDecoderTypes.ToList().ForEach(t => Console.WriteLine(t.FullName)); Console.ReadKey(); } static IEnumerable<Type> AllEncoderTypes { get { return AllSubclassesOf(typeof(BitmapEncoder)); } } static IEnumerable<Type> AllDecoderTypes { get { return AllSubclassesOf(typeof(BitmapDecoder)); } } static IEnumerable<Type> AllSubclassesOf(Type type) { var r = new Reflector(); // Add additional assemblies here return r.AllSubclassesOf(type); } } class Reflector { List<Assembly> assemblies = new List<Assembly> { typeof(BitmapDecoder).Assembly }; public IEnumerable<Type> AllSubclassesOf(Type super) { foreach (var a in assemblies) { foreach (var t in a.GetExportedTypes()) { if (t.IsSubclassOf(super)) { yield return t; } } } } } }