Сведения о вопросе

Htmlщик

17:09, 15th August, 2020

Теги

c#   wpf   bitmap    

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

Просмотров: 416   Ответов: 2

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

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

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

System.Windows.Media.Imaging.BitmapDecoder / BitmapEncoder



  Сведения об ответе

davran

03:30, 25th August, 2020

Вы должны любить .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;
                    }
                }
            }
        }
    }
}


  Сведения об ответе

#hash

00:07, 4th August, 2020

Надеюсь, кто-нибудь поправит меня, если я ошибаюсь, но я не думаю, что в WPF есть что-то подобное. Но, надеюсь, это один из многих случаев, когда прогресс в технологии сделал устаревшим то, как мы привыкли делать вещи. Как "how do I wind my digital watch?"

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

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

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

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


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться