在 WindowsForms 世界中,您可以获得可用的图像编码器/解码器列表
System.Drawing.ImageCodecInfo.GetImageDecoders() / GetImageEncoders()
我的问题是,有没有办法为 WPF 世界做一些类似的事情,让我得到一个可用的列表
System.Windows.Media.Imaging.BitmapDecoder / BitmapEncoder
您必须喜欢 .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;
}
}
}
}
}
}
如果我错了,希望有人能纠正我,但我认为 WPF 中没有类似的东西。但希望这是技术进步使我们习惯于做事的方式变得过时的众多案例之一。比如“我如何给我的数字手表上弦?”
据我了解,在 System.Drawing 中需要 ImageCodecInfo.GetImageDecoders() 的原因与 System.Drawing 本身的笨拙性质有关:System.Drawing 是围绕 GDI+ 的托管包装器,它是围绕一部分的非托管包装器Win32 API。因此,在 .NET 本身不知道的情况下,可能会在 Windows 中安装新的编解码器是有原因的。GetImageDecoders() 返回的只是一堆字符串,通常会传回 System.Drawing/GDI+,用于查找和配置适当的 DLL 以读取/保存图像。
另一方面,在 WPF 中,标准编码器和解码器内置在框架中,如果我没记错的话,不要依赖任何不能保证作为框架一部分安装的东西。以下类继承自 BitmapEncoder,并且可与 WPF 一起使用:BmpBitmapEncoder、GifBitmapEncoder、JpegBitmapEncoder、PngBitmapEncoder、TiffBitmapEncoder、WmpBitmapEncoder。所有相同格式都有 BitmapDecoder,还有 IconBitmapDecoder 和 LateBoundBitmapDecoder。
您可能正在处理我无法想象的情况,但在我看来,如果您必须使用从 BitmapEncoder 继承但 WPF 未包含的类,则可能是您要安装的您自己的自定义类与您的应用程序。
希望这可以帮助。如果我错过了图片的必要部分,请告诉我。