Как получить список установленных BitmapEncoders / Decoders (мир WPF)?

В мире WindowsForms вы можете получить список доступных кодировщиков / декодеров изображений с

System.Drawing.ImageCodecInfo.GetImageDecoders() / GetImageEncoders()

У меня вопрос, есть ли способ сделать что-то аналогичное для мира WPF, которое позволило бы мне получить список доступных

System.Windows.Media.Imaging.BitmapDecoder / BitmapEncoder
18.08.2008 18:17:12
2 ОТВЕТА

Надеюсь, кто-нибудь исправит меня, если я ошибаюсь, но я не думаю, что в WPF есть что-то подобное. Но, надеюсь, это один из многих случаев, когда достижения в технологии устарели, когда мы привыкли что-то делать. Как "как мне заводить мои цифровые часы?"

Насколько я понимаю, причина, по которой ImageCodecInfo.GetImageDecoders () необходима в System.Drawing, связана с хитрой природой самого System.Drawing: System.Drawing - это управляемая оболочка вокруг GDI +, которая является неуправляемой оболочкой вокруг части Win32 API. Таким образом, может быть причина, по которой новый кодек будет установлен в Windows, но .NET по сути не знает об этом. И то, что возвращается из GetImageDecoders (), это просто набор строк, которые обычно передаются обратно в System.Drawing / GDI + и используются для поиска и настройки соответствующей DLL для чтения / сохранения вашего изображения.

С другой стороны, в WPF стандартные кодеры и декодеры встроены в фреймворк, и, если я не ошибаюсь, не зависят от того, что не гарантировано будет установлено как часть фреймворка. Следующие классы наследуются от BitmapEncoder и доступны "из коробки" с WPF: BmpBitmapEncoder, GifBitmapEncoder, JpegBitmapEncoder, PngBitmapEncoder, TiffBitmapEncoder, WmpBitmapEncoder. Существуют BitmapDecoders для всех тех же форматов, плюс IconBitmapDecoder и LateBoundBitmapDecoder.

Вы можете иметь дело с делом, которое я не представляю, но мне кажется, что если вам нужно использовать класс, который наследуется от BitmapEncoder, но не включен в WPF, то, вероятно, вы установили бы свой собственный класс с вашим приложением.

Надеюсь это поможет. Если мне не хватает необходимой части изображения, пожалуйста, дайте мне знать.

0
18.08.2008 23:41:57
Я просто исследую эту проблему, а вы ошибаетесь. Создание образов WPF аналогично System.Drawing: управляемая оболочка для Win32, а именно WIC (Windows Imaging Component). Никакой кодер / декодер не встроен в структуру, и я думаю, что никогда не будет (причины производительности и повторного использования кода, у них есть все это в Windows). Они просто забыли добавить функциональность в список форматов :(.
fejesjoco 7.04.2011 16:55:13
Re: "Как мне заводить мои цифровые часы?" Теперь они делают цифровые часы, которые используют ваше движение для зарядки батареи. Таким образом, они могли бы сделать один с моталки. :)
Jesse Chisholm 27.10.2014 18:42:25

Вы должны любить .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;
                    }
                }
            }
        }
    }
}
4
20.08.2008 06:03:18