C# 如何获取已安装位图编码器/解码器的列表(WPF世界)?

C# 如何获取已安装位图编码器/解码器的列表(WPF世界)?,c#,wpf,bitmap,C#,Wpf,Bitmap,在WindowsForms world中,您可以通过以下方式获得可用图像编码器/解码器的列表: System.Drawing.ImageCodecInfo.GetImageDecoders() / GetImageEncoders() 我的问题是,有没有一种方法可以为WPF世界做一些类似的事情,让我得到一个可用的列表 System.Windows.Media.Imaging.BitmapDecoder / BitmapEncoder 如果我错了,希望有人会纠正我,但我认为WPF中没有类似的东

在WindowsForms world中,您可以通过以下方式获得可用图像编码器/解码器的列表:

System.Drawing.ImageCodecInfo.GetImageDecoders() / GetImageEncoders()
我的问题是,有没有一种方法可以为WPF世界做一些类似的事情,让我得到一个可用的列表

System.Windows.Media.Imaging.BitmapDecoder / BitmapEncoder

如果我错了,希望有人会纠正我,但我认为WPF中没有类似的东西。但希望这是技术进步使我们习惯的做事方式变得过时的众多案例之一。比如“我怎么给我的数字手表上发条?”

据我所知,为什么ImageCodeInfo.GetImageDecoders()在System.Drawing中是必需的,这与System.Drawing本身的笨拙性质有关。Drawing本身:System.Drawing是围绕GDI+的托管包装,GDI+是围绕Win32 API的一部分的非托管包装。因此,在Windows中安装新的编解码器,而.NET本身并不知道这一点,这可能是有原因的。从GetImageDecoders()返回的只是一组字符串,这些字符串通常会传回System.Drawing/GDI+,用于查找和配置用于读取/保存图像的适当DLL

另一方面,在WPF中,标准编码器和解码器内置在框架中,如果我没有弄错的话,不要依赖于任何不能保证作为框架一部分安装的东西。以下类继承自BitmapEncoder,并随WPF一起提供:BmpBitmapEncoder、GifBitmapEncoder、JpegBitmapEncoder、PngBitmapEncoder、TiffBitmapEncoder、WmpBitmapEncoder。所有相同格式都有位图解码器,还有IconBitmapDecoder和LateBoundBitmapDecoder

您可能正在处理一个我想象不到的情况,但在我看来,如果您必须使用从BitmapEncoder继承但未包含在WPF中的类,则可能是您自己的自定义类,您将在应用程序中安装该类


希望这有帮助。如果我遗漏了图片的一个必要部分,请告诉我。

你一定喜欢.NET reflection。我曾在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
属性,可以获得更好的名称。该类将为您提供其他factoid中可读的名称

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;
                    }
                }
            }
        }
    }
}
使用系统;
使用System.Linq;
使用System.Collections.Generic;
运用系统反思;
使用System.Windows.Media.Imaging;
名称空间编解码器{
班级计划{
静态void Main(字符串[]参数){
控制台.WriteLine(“位图编码器:”);
ForEach(t=>Console.WriteLine(t.FullName));
Console.WriteLine(“\n位图解码器:”);
ForEach(t=>Console.WriteLine(t.FullName));
Console.ReadKey();
}
静态IEnumerable AllEncoderTypes{
得到{
返回所有子类(typeof(BitmapEncoder));
}
}
静态IEnumerable AllDecoderTypes{
得到{
返回所有子类(typeof(BitmapDecoder));
}
}
静态IEnumerable所有子类(类型){
var r=新反射器();
//在此处添加其他程序集
返回r.所有子类(类型);
}
}
类反射器{
列表程序集=新列表{
类型(位图解码器)。程序集
};
公共IEnumerable所有子类(超级类型){
foreach(程序集中的变量a){
foreach(a.GetExportedTypes()中的变量t){
if(t.ISUBCLASSOF(超级)){
收益率t;
}
}
}
}
}
}

我只是在研究这个问题,你错了。WPF imaging与System.Drawing完全相同:一种用于Win32的托管包装器,即WIC(Windows imaging组件)。框架中没有内置编码器/解码器,我认为永远不会有(性能和代码重用的原因,它们都在Windows中)。他们只是忘了添加功能来列出格式:(.re:“我如何给我的数字手表上弦?”他们现在生产的数字手表使用你的动作来给电池充电。因此他们可以用上弦器来制作一个。:)因此在
iWicMagingFactory.CreateComponentEnumerator
周围没有WPF包装,而在框架之后检测编解码器的唯一方法是COM互操作?