Encontré varios patrones para optimizar el manejo de mapas de bits en WPF. Sin embargo, no entiendo cuándo usar cada patrón. Como creo que este es un problema común, resumí lo que entiendo y lo que supongo y le pido su ayuda. Si se puede añadir patrones , explicar cómo se diferencian, explique si utilizan la CPU o la GPU , y enseñar cuándo utilizar cada y cómo combinarlos, que sería una gran ayuda !Patrones de optimización del rendimiento de mapa de bits
Contexto - Las imágenes "cuadrícula" Escenario:
Mi aplicación tiene que mostrar muchas imágenes de mapa de bits. Las imágenes se muestran en la pantalla en una organización cuadriculada de filas y columnas (no necesariamente las clases Grid o UniformGrid, piense en la vista Album de Window Media Player). Las imágenes pueden moverse entre diferentes celdas de la grilla. Algunas imágenes en celdas arbitrarias pueden ser reemplazadas por otras. Se debe poder hacer clic en las imágenes, proporcionar un menú contextual, seleccionarlas, arrastrarlas, etc. En otras palabras, "combinar los pequeños insectores en un gran mapa de bits" no es aplicable, al menos no ingenuamente.
Patrón 0: El Hack
Combino los pequeños bichos en un mapa de bits, y usar esto como el fondo (cómo dibujar contexto??). Superponga esto con imágenes con contenido vacío que manejará los hits, menús contextuales, eventos, etc.
La ventaja es que aquí solo hablamos de dos mapas de bits: el que se muestra actualmente y el que debería reemplazarlo. Esto debería ser realmente rápido. Sin embargo, mis años de experiencia levantan la bandera roja de peligro. ¿Tus comentarios?
Patrón 1: Reducir el tamaño de la imagen
Ésta es una obviedad cuando se sabe de antemano el tamaño de la imagen para cambiar el tamaño a, y cuando estás dispuesto a perder detalles (color) para la prestación del servicio:
- Reducir el tamaño de mapa de bits utilizando BitmapImage.DecodePixelWidth
- Reducir la información de color usando FormatConvertedBitmap.DestinationFormat
- Establecer comportamiento de la escala del control de s etting Image.Stretch to Stretch.None
- Establezca SetBitmapScalingMode para la imagen en LowQuality.
- congelar el cabrón
Ver código here.
Patrón 2: Antecedentes de solicitud previa
Este patrón es aplicable cuando se piensa que puede tomar ventaja de que el usuario mirando las imágenes en la pantalla, y se prepara con anticipación las siguientes imágenes para mostrar. Las desventajas de su proyecto, además de la sobrecarga de memoria, es que tiene que admitir el objetivo de .Net Framework 4 y no solo el perfil del cliente, por lo que puede incurrir en una instalación en el cliente. Usted mismo tendrá que sufrir el dolor de la programación asincrónica.
En este patrón, crea exactamente el número requerido de controles de imagen. Cuando se deben agregar, mover o eliminar mapas de bits, solo se modifican los 'BitmapSource (s)' de los controles de imagen. Una tarea de BackgroundWorker es responsable de la precarga de los BitmapSource (s) (posiblemente usando el patrón "Reducir el tamaño de imagen" arriba) y de insertarlos en MemoryCache.
Para que esto funcione, debe establecer CacheOption de BitmapImage en OnLoad, para que el trabajo se descargue al trabajador en segundo plano.
Patrón 3: Dibujo Contexto
Esto fue sugerido por Sheldon Ziao de soporte técnico de Microsoft en el foro de MSDN WPF here. Consulte la página 494, Capítulo 15 "Gráficos 2D" en Adam Nathan's WPF 4 Unleashed para obtener una descripción de DrawingContext. No puedo decir que lo entiendo De acuerdo con la respuesta here, supongo que esto mejoraría el manejo de los dibujos de Geometría, no mapas de bits. A continuación, no creo que esto respalde los requisitos de enfoque y eventos para las imágenes (mi mal por no explicar mejor los requisitos en el foro). Además, estoy preocupado por la oración de resumen del libro: "Tenga en cuenta que el uso de DrawingContext no cambia el hecho de que está operando dentro de un sistema de modo retenido. El dibujo especificado no ocurre inmediatamente; los comandos son persistentes por WPF hasta que sean necesarios. "Esto significa que una vez que nuestro manejador par es re no podemos aprovechar el paralelismo como en" Anteproducción de fondo ".
Patrón 4: puede ser escrito mapas de bits
La documentación de MSDN here lo describe como un sistema de doble tampón: Su hilo de interfaz de usuario se actualiza la memoria intermedia; el hilo de renderizado de WPF mueve esto a la memoria de video.
El uso previsto (ver here) es para mapas de bits que cambian mucho en una película de video como la pantalla. No estoy seguro, pero es posible que se haya pirateado y se haya combinado con el patrón Pre-fetch de fondo y se haya utilizado en el escenario de la cuadrícula.
Patrón 5: mapa de bits en caché
No hay mucha información sobre el MSDN (here). En el archivo del foro WPF (here) se explica que "La API BitmapCache está diseñada para almacenar en caché su contenido (cuando se procesa en hardware) en la memoria de video, lo que significa que permanece residente en su GPU. Esto le ahorra el costo de volver a procesar ese contenido cuando lo dibuja en la pantalla. "Esto parece una gran idea. No estoy seguro, sin embargo, cuáles son las trampas y cómo usarlo.
Patrón 6: RenderTargetBitmap
El RenderTargetBitmap convierte un Visual a un mapa de bits. No estoy seguro de si es relevante aquí. Ver here.
Editar: En relación con la pregunta de Paul Hoenecke: He escrito que "Mi aplicación tiene que mostrar muchos mapas de bits". No mencioné que necesito mostrar aproximadamente 800 imágenes al mismo tiempo.
Uno puede leer acerca de los problemas de rendimiento que participan en mis SO preguntas WPF Bitmap performance y How can I make displaying images on WPF more “snappy”?
He modificado la descripción del patrón 1 para resaltar el concepto de que los controles de imagen no se crean o se eliminan (a menos que queramos para mostrar una grilla más grande o más pequeña). Solo sus orígenes están configurados en BitmapSources diferentes, nuevos o nulos.
Editar: This question as posted on the WPF support forum, con algunas respuestas del personal de MS.
¿Cuántas imágenes anticipas? He hecho una aplicación que muestra una grilla de miles de imágenes antes. Usamos un cuadro de lista de modo virtual; a medida que el usuario se desplaza hacia abajo, las imágenes se cargan en una secuencia de fondo, se congelan y se establecen en la fuente de la imagen. Claramente, ha pensado mucho en esto ... pero, tal vez sea mejor saber más sobre exactamente lo que quiere lograr. Por ejemplo, ¿qué problemas ha tenido que optimizan esa prioridad? –
@PaulHoenecke Hola, Paul, gracias por tu respuesta. Las colecciones virtuales lo ayudan cuando quiere mostrar una pequeña cantidad de elementos de una gran colección. Aquí, quiero mostrar aproximadamente 1K elementos al mismo tiempo. Además, no estoy seguro de que exista una grilla de virtualización. Por último, el patrón 1 esencialmente se está virtualizando: agregaré en edit. – Avi
Avi, su pregunta parece inapropiada para el problema descrito. Es posible que desee mejorar la relación de compresión por alguna razón, pero luego debe saber exactamente qué tipo de imágenes está mostrando. O, por otro lado, es posible que desee darle al usuario una impresión de todas las imágenes disponibles, luego puede definir algunos conjuntos y visualizar miniaturas o similares. Pero ambas cosas no necesariamente tienen que ver entre sí. ¿Tal vez desee algo así como una métrica de similitud para definir conjuntos de imágenes similares? –