如何获取已安装的BitmapEncoders/Decoders列表(WPF世界)?

10 c# wpf bitmap

在WindowsForms世界中,您可以获得可用的图像编码器/解码器列表

System.Drawing.ImageCodecInfo.GetImageDecoders() / GetImageEncoders()
Run Code Online (Sandbox Code Playgroud)

我的问题是,有没有办法为WPF世界做类似的事情,这将允许我获得可用的列表

System.Windows.Media.Imaging.BitmapDecoder / BitmapEncoder
Run Code Online (Sandbox Code Playgroud)

Fra*_*ger 5

您一定会喜欢 .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
Run Code Online (Sandbox Code Playgroud)

代码中有一条注释,用于添加其他程序集(例如,如果您支持插件)。此外,您还需要过滤解码器列表以删除:

System.Windows.Media.Imaging.LateBoundBitmapDecoder
Run Code Online (Sandbox Code Playgroud)

使用构造函数模式匹配进行更复杂的过滤是可能的,但我不想编写它。:-)

您现在需要做的就是实例化编码器和解码器来使用它们。此外,您可以通过检索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;
                    }
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Kev*_*ley 1

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

据我了解,为什么 ImageCodecInfo.GetImageDecoders() 在 System.Drawing 中是必需的,这与 System.Drawing 本身的混乱本质有关:System.Drawing 是 GDI+ 的托管包装器,而 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 中的类,那么您可能需要安装您自己的自定义类与您的申请。

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

  • 我只是在研究这个问题,你错了。WPF 成像与 System.Drawing 相同:Win32 内容的托管包装器,即 WIC(Windows 成像组件)。框架中没有内置编码器/解码器,我认为永远不会有(性能和代码重用原因,它们在 Windows 中都有)。他们只是忘记添加列出格式的功能:(。 (3认同)