Loupe

#Windows Apps : attention à votre carte graphique lorsque vous utilisez le RenderTargetBitmap

Petit article de blog sur une fonctionnalité sympathique du RenderTargetBitmap dans une application Windows. Le downscaling automatique pour s’adapter à votre machine.

Le RenderTargetBitmap est un composant très pratique car il permet de faire le rendu sous forme d’image d’un composant XAML.

Pour faire ce rendu, il utilise sous le capot une surface DirectX et cela provoque un comportement à connaitre : le rendu de l’image aura au maximum la taille maximum des surfaces DirectX supportées par la carte graphique de la machine ou est exécutée l’application. (4096 par exemple sur ma Surface Pro 3). Par contre, le ratio de l’image reste bien respecté (pas de soucis à se faire donc).

Cela n’a pas en général de conséquences graves mais cela peut provoquer un crash lorsque vous permettez à un utilisateur de faire un crop sur ce rendu : la taille de la sélection peut dépasser la taille de l’image rendu.

Pour détecter ce cas, il suffit finalement de calculer le ratio entre la taille voulue et la taille finalement rendue par le RenderTargetBitmap. Cette dernière information étant retournée par la propriété PixelWidth du RenderTargetBitmap après le rendu.

//Rendu de l'élément
await renderTargetBitmap
   .RenderAsync(elementDontJeVeuxLeRendu, elementWidth, elementHeight);
   
// récupération des pixels
var pixels = await renderTargetBitmap.GetPixelsAsync();
   
// ratio de rendu - 1 normalement mais peut être changé par le rendu
var finalRatioW = renderTargetBitmap.PixelWidth / elementDontJeVeuxLeRendu.ActualWidth;
var finalRatioH = renderTargetBitmap.PixelHeight / elementDontJeVeuxLeRendu.ActualHeight;

//Création de l'encoder d'image
var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, target);

// utilisation des ratios pour découper l'image
encoder.BitmapTransform.Bounds = new BitmapBounds
{
    X = 0,
    Y = 0,
    Width = (uint)( widthSelection* finalRatioW),
    Height = (uint)(heightSelection * finalRatioH ),
};

//Utilisation de l'encoder
encoder.SetPixelData(
     BitmapPixelFormat.Bgra8,
     BitmapAlphaMode.Ignore,
     (uint)renderTargetBitmap.PixelWidth,
     (uint)renderTargetBitmap.PixelHeight,
     96, 96, bytes);
     
     
// Avant cela crashait ici
await encoder.FlushAsync();

 

La documentation MSDN est bien à jour : https://msdn.microsoft.com/fr-fr/library/windows/apps/dn298557

 

Bon dev !

 

PS: oui j’ai résisté à faire la blague évidente sur ce genre de problème  :)

Photo de profil

Ces billets pourraient aussi vous intéresser

Vous nous direz ?!

Commentaires

comments powered by Disqus