c# - tutorial - ¿Cómo obtener la lista de BitmapEncoders/Decoders instalados(el mundo de WPF)?
wpf presentacion (2)
En el mundo de WindowsForms puede obtener una lista de codificadores / decodificadores de imágenes disponibles con
System.Drawing.ImageCodecInfo.GetImageDecoders() / GetImageEncoders()
Mi pregunta es, ¿hay alguna manera de hacer algo análogo para el mundo de WPF que me permita obtener una lista de los disponibles?
System.Windows.Media.Imaging.BitmapDecoder / BitmapEncoder
Espero que alguien me corrija si me equivoco, pero no creo que haya nada como eso en WPF. Pero esperamos que este sea uno de los muchos casos en que los avances en la tecnología han quedado obsoletos de la manera en que estamos acostumbrados a hacer las cosas. Me gusta "¿cómo enrollo mi reloj digital?"
A mi entender, la razón por la que ImageCodecInfo.GetImageDecoders () es necesario en System.Drawing tiene que ver con la naturaleza kludgy de System.Drawing itself: System.Drawing es un contenedor gestionado alrededor de GDI +, que es un contenedor no administrado alrededor de una parte de la API Win32. Así que podría haber una razón por la cual un códec nuevo se instalaría en Windows sin que .NET lo supiera inherentemente. Y lo que devuelve GetImageDecoders () es simplemente un conjunto de cadenas que normalmente se pasan a System.Drawing / GDI + y se usan para buscar y configurar el archivo DLL apropiado para leer / guardar su imagen.
Por otro lado, en WPF, los codificadores y decodificadores estándar están integrados en el marco, y, si no me equivoco, no depende de nada que no esté garantizado para ser instalado como parte del marco. Las siguientes clases heredan de BitmapEncoder y están disponibles de fábrica con WPF: BmpBitmapEncoder, GifBitmapEncoder, JpegBitmapEncoder, PngBitmapEncoder, TiffBitmapEncoder, WmpBitmapEncoder. Hay BitmapDecoders para todos los mismos formatos, además de IconBitmapDecoder y LateBoundBitmapDecoder.
Puede que estés lidiando con un caso que no estoy imaginando, pero me parece que si tienes que usar una clase que hereda de BitmapEncoder pero no fue incluida con WPF, es probable que sea tu propia clase personalizada la que instales con tu aplicación.
Espero que esto ayude. Si me falta una parte necesaria de la imagen, házmelo saber.
Tienes que amar la reflexión .NET. Trabajé en el equipo de WPF y no puedo pensar en nada mejor de lo que pensaba. El siguiente código produce esta lista en mi máquina:
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
Hay un comentario en el código donde agregar ensamblajes adicionales (si admite complementos, por ejemplo). Además, querrá filtrar la lista de decodificadores para eliminar:
System.Windows.Media.Imaging.LateBoundBitmapDecoder
Es posible un filtrado más sofisticado utilizando la coincidencia de patrones del constructor, pero no tengo ganas de escribirlo. :-)
Todo lo que necesita hacer ahora es crear instancias de los codificadores y decodificadores para usarlos. Además, puede obtener mejores nombres recuperando la propiedad CodecInfo
de los decodificadores del codificador. Esta clase le dará nombres legibles entre otros factoids.
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;
}
}
}
}
}
}