Optimizar el rendimiento: Imágenes y gráficos 2D

WPF proporciona una amplia gama de gráficos 2D y funcionalidad de creación de imágenes que se puede optimizar para los requisitos de la aplicación. Este tema proporciona información acerca de la optimización del rendimiento en esas áreas.

Dibujo y formas

WPF proporciona objetos Drawing y Shape para representar el contenido de los dibujos gráficos. Sin embargo, los objetos Drawing son construcciones más sencillas que los objetos Shape y ofrecen mejores características de rendimiento.

Un Shape permite dibujar una forma gráfica en la pantalla. Como derivan de la clase FrameworkElement, los objetos Shape pueden utilizarse dentro de los paneles y de la mayoría de los controles.

WPF ofrece varias capas de acceso a gráficos y servicios de representación. En la capa superior, los objetos Shape son fáciles de usar y proporcionan numerosas características útiles, como el control de diseños y eventos. WPF proporciona un número de objetos de forma listos para usar. Todos los objetos de forma heredan de la clase Shape. Los objetos de forma disponibles incluyen Ellipse, Line, Path, Polygon, Polyline, y Rectangle.

Los objetos Drawing, por el contrario, no derivan de la clase FrameworkElement y proporcionan una implementación más ligera para representar formas, imágenes y texto.

Hay cuatro tipos de objetos Drawing:

El objeto GeometryDrawing se utiliza para representar el contenido geométrico. La clase Geometry y las clases concretas que derivan de ella, como CombinedGeometry, EllipseGeometry y PathGeometry, proporcionan un medio para representar gráficos 2D y proporcionar soporte para pruebas de impacto y recorte. Los objetos geométricos se pueden usar para definir la región de un control, por ejemplo, o para definir la región de recorte que se aplicará a una imagen. Los objetos geométricos pueden ser regiones simples, como rectángulos y círculos, o regiones compuestas creadas a partir de dos o más objetos geométricos. Se pueden crear regiones geométricas más complejas combinando objetos derivados de PathSegment, como ArcSegment, BezierSegment y QuadraticBezierSegment.

A primera vista, la clase Geometry y la clase Shape son similares. Ambos se utilizan en la representación de gráficos 2D y ambos tienen clases concretas similares que derivan de ellos, por ejemplo, EllipseGeometry y Ellipse. Sin embargo, hay diferencias importantes entre estos dos conjuntos de clases. Por un lado, la clase Geometry carece de algunas de las funciones de la clase Shape, como la capacidad de dibujarse a sí misma. Para dibujar un objeto geométrico, debe usarse otra clase, como la clase DrawingContext, la clase de dibujo o de trazado (merece la pena indicar que un trazado es una forma) para realizar la operación de dibujo. Las propiedades de representación como relleno, trazo y grosor del trazo, se encuentran en la clase que dibuja el objeto geométrico, mientras que un objeto de forma contiene estas propiedades. Una forma de acordarse de esta diferencia es que un objeto geométrico define una región, por ejemplo, un círculo, mientras que un objeto de forma define una región, define cómo es el relleno y el contorno de esa región y participa en el sistema de diseño.

Dado que los objetos Shape derivan de la clase FrameworkElement, su uso puede añadir un consumo de memoria significativamente mayor en su aplicación. Si realmente no necesita las características FrameworkElement para su contenido gráfico, considere el uso de los objetos Drawing de menor peso.

Para obtener más información sobre objetos Drawing, vea Información general sobre los objetos de dibujo.

Objetos StreamGeometry

El objeto StreamGeometry es una alternativa ligera a PathGeometry para crear formas geométricas. Use un StreamGeometry cuando necesite describir una geometría compleja. StreamGeometry está optimizado para controlar muchos objetos PathGeometry y tiene un mejor rendimiento en comparación con el uso de muchos objetos individuales PathGeometry.

En el siguiente ejemplo, se usa la sintaxis de atributo para crear un objeto StreamGeometry triangular en XAML.

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <StackPanel>
  
    <Path Data="F0 M10,100 L100,100 100,50Z" 
      StrokeThickness="1" Stroke="Black"/>

  </StackPanel>
</Page>

Para obtener más información sobre los objetos StreamGeometry, consulte Crear una forma usando StreamGeometry.

Objetos DrawingVisual

El objeto DrawingVisual es una clase de dibujo ligera que se utiliza para representar formas, imágenes o texto. Esta clase se considera ligera porque no proporciona control de diseño ni evento, lo que mejora su rendimiento. Por esta razón, los dibujos son ideales para fondos e imágenes prediseñadas. Para más información, consulte Usar objetos DrawingVisual.

Imágenes

La creación de imágenes de WPF ofrece una mejora considerable sobre las capacidades de creación de imágenes en versiones anteriores de Windows. Las funciones de creación de imágenes, como mostrar un mapa de bits o usar una imagen en un control común, se administraban principalmente mediante la Interfaz de dispositivo gráfico de Microsoft Windows (GDI) o la interfaz de programación de aplicaciones (API) de Windows GDI+. Estas API proporcionan funciones de creación de imágenes de línea base, pero carecían de algunas características, como la compatibilidad con la extensibilidad de códec y con imágenes de alta fidelidad. WPF Imaging API se rediseñó para superar las limitaciones de GDI y GDI+ y proporcionar un nuevo conjunto de API para mostrar y usar imágenes en las aplicaciones.

Al usar imágenes, tenga en cuenta las siguientes recomendaciones para obtener un mejor rendimiento:

  • Si su aplicación necesita mostrar imágenes en miniatura, considere la posibilidad de crear una versión en tamaño reducido de la imagen. De forma predeterminada, WPF carga la imagen y la descodifica a su tamaño completo. Si solo quiere una versión en miniatura de la imagen, WPF descodifica innecesariamente la imagen en su tamaño completo y, a continuación, la escala a un tamaño de miniatura. Para evitar esta sobrecarga innecesaria, puede solicitar que WPF descodifique la imagen en un tamaño de miniatura o que WPF cargue una imagen en miniatura.

  • Descodifique siempre la imagen en el tamaño deseado y no en el tamaño predeterminado. Como se mencionó anteriormente, solicite que WPF descodifique la imagen en el tamaño deseado y no en el tamaño completo predeterminado. No solo reducirá el espacio de trabajo de la aplicación, sino también la velocidad de ejecución.

  • Si es posible, combine las imágenes en una sola imagen, como una tira de película compuesta de varias imágenes.

  • Para obtener más información, consulte Información general sobre imágenes.

BitmapScalingMode

Al animar la escala de un mapa de bits, el algoritmo para volver a muestrear la imagen de alta calidad predeterminada puede consumir suficientes recursos del sistema para que se produzca una degradación de la velocidad de fotogramas, lo que causa que las animaciones parpadeen. Estableciendo la propiedad BitmapScalingMode del objeto RenderOptions a LowQuality, puede crear una animación más suave al escalar un mapa de bits. El modo LowQuality indica al motor de representación WPF que se cambie de un algoritmo optimizado de calidad a un algoritmo optimizado de velocidad al procesar imágenes.

El siguiente ejemplo muestra cómo establecer el BitmapScalingMode para un objeto de imagen.

// Set the bitmap scaling mode for the image to render faster.
RenderOptions.SetBitmapScalingMode(MyImage, BitmapScalingMode.LowQuality);
' Set the bitmap scaling mode for the image to render faster.
RenderOptions.SetBitmapScalingMode(MyImage, BitmapScalingMode.LowQuality)

CachingHint

Por defecto, WPF no almacena en caché el contenido renderizado de los objetos TileBrush, como DrawingBrush y VisualBrush. En escenarios estáticos donde el contenido o el uso del TileBrush en la escena no están cambiando, esto tiene sentido, ya que conserva la memoria de vídeo. No tiene tanto sentido cuando un TileBrush con contenido estático se utiliza de forma no estática; por ejemplo, cuando un DrawingBrush o VisualBrush estático se asigna en la superficie de un objeto 3D que gira. El comportamiento por defecto de WPF es volver a renderizar todo el contenido de DrawingBrush o VisualBrush en cada fotograma, aunque el contenido no cambie.

Si se establece la propiedad CachingHint del objeto RenderOptions como Cache, se puede aumentar el rendimiento mediante el uso de versiones en caché de los objetos de pincel de diseño en mosaico.

Los valores de las propiedades CacheInvalidationThresholdMinimum y CacheInvalidationThresholdMaximum son valores de tamaño relativos que determinan cuándo debe regenerarse el objeto TileBrush debido a los cambios de escala. Por ejemplo, al establecer la propiedad CacheInvalidationThresholdMaximum en 2.0, la caché para TileBrush solo necesita regenerarse cuando su tamaño excede el doble del tamaño de la caché actual.

El siguiente ejemplo muestra cómo utilizar la opción de sugerencia de almacenamiento en caché para un DrawingBrush.

DrawingBrush drawingBrush = new DrawingBrush();

// Set the caching hint option for the brush.
RenderOptions.SetCachingHint(drawingBrush, CachingHint.Cache);

// Set the minimum and maximum relative sizes for regenerating the tiled brush.
// The tiled brush will be regenerated and re-cached when its size is
// 0.5x or 2x of the current cached size.
RenderOptions.SetCacheInvalidationThresholdMinimum(drawingBrush, 0.5);
RenderOptions.SetCacheInvalidationThresholdMaximum(drawingBrush, 2.0);
Dim drawingBrush As New DrawingBrush()

' Set the caching hint option for the brush.
RenderOptions.SetCachingHint(drawingBrush, CachingHint.Cache)

' Set the minimum and maximum relative sizes for regenerating the tiled brush.
' The tiled brush will be regenerated and re-cached when its size is
' 0.5x or 2x of the current cached size.
RenderOptions.SetCacheInvalidationThresholdMinimum(drawingBrush, 0.5)
RenderOptions.SetCacheInvalidationThresholdMaximum(drawingBrush, 2.0)

Vea también