await

7 articles

Image depuis HTTP avec C# XAML – Comparatifs et Performances – Partie 2

Introduction

 wp_ss_20141223_0001

Cet article traite des résultats des différentes méthodes pour lire une image provenant d’un site Http.

Les différentes implémentations ont été décrites dans l’article

Image depuis http avec C# Xaml – comparatifs et performances.

Mesures

L’image étalon fait 19ko et mesure 400×240 pixels. Elle est présente notamment sur les serveurs de Bing à l’adresse suivante :

http://www.bing.com/az/hprichbg/rb/ChristmasMarketNurnberg_FR-FR11351563819_1280x768.JPG

Le premier test va charger 10 fois la même image suivante :

Poursuivre la lecture

Image depuis HTTP avec C# XAML – Comparatifs et Performances – Partie 1

Introduction

Chargement Bitmap Image en Http

Voici un article en 2 parties pour décrire les différentes implémentations possibles de la lecture d’images provenant d’un serveur en Http.
En terme de performances, il existe des différences assez conséquentes suivant les implémentations choisies.

Nous allons voir que parfois les résultats sont assez surprenants.

Charger une image depuis XAML

Le moyen le plus simple pour charger une image reste l’implémentation XAML.

<Image Source="{Binding ImageUrl}" Width="400" Height="240"/>

ImageUrl est de type Url et peut être déclarée de cette façon dans le viewModel associé à la Page.

public  Uri ImageUrl
{
    get
    {
        return new Uri(@"http://www.bing.com/az/hprichbg/rb/SnowyCP_FR-FR11972876588_400x240.jpg");
    }
}

Cette implémentation est très efficace, le contrôle XAML gère quasiment tout pour vous :

  • le chargement en asynchrone : Ne fige pas l’affichage de l’interface lors du chargement
  • la mise en cache mémoire (un seul chargement)
  • L’optimisation http (évite un échange serveur si l’image est déjà chargée)

Cependant l’image chargée en XAML sera de nouveau rechargée à chaque lancement de l’application.
Afin de mettre en place un système de cache persisté, il est nécessaire de charger le contenu de l’image et de la sauvegarder sur le téléphone dans l’Isolated Storage.

Quelles sont les méthodes possibles pour charger et afficher une image en asynchrone ?

Voici 9 façons de faire en Universal Apps (Windows Phone XAML ou Windows 8.1). Leurs temps de réponse seront mesurés sur Windows Phone 8.1 et exposés dans la 2ème partie de cet article.

Implémentations

 

1 – DataWriter

La première implémentation, la plus classique, est d’utiliser un httpClient pour récupérer le flux sous forme de Stream puis de le transférer dans le BitmapImage en passant par un DataWritter.

Windows 8 et les Universal Apps nous obligent à passer par un nouveau type de Stream le InMemoryRandomAccessStream pour l’afficher comme source dans le BitmapImage. Poursuivre la lecture

Mise en cache d’image dans l’isolated storage avec Windows XAML et SemaphoreSlim

 

Ecriture dans l’isolated Storage d’un fichier image

Ecriture Multiple dans l'Isolated Storage

Il est parfois fort utile de sauvegarder les images provenant d’un serveur HTTP dans un cache afin d’éviter de les charger à chaque fois.

En implémentant ce système de cache en asynchrone, je me suis rendu compte de plusieurs problèmes causant systématiquement un UnauthorizedAccessException: Access is denied (0x80070005).

Poursuivre la lecture

Réglage du zoom du Scrollviewer en universal app (w10, Wp8.1)

Zoom et Scrollviewer (avant)

Pour initialiser le zoom du Scrollviewer, il était possible avec Windows 8.0 de définir directement le niveau de zoom désiré avec l’instruction :

scrollViewer.ZoomToFactor(3.0F);

pour avoir un zoom de 300% par exemple.

De même pour se déplacer dans le scrollviewer, il fallait également utiliser

scrollViewer.ScrollToHorizontalOffset(100);
scrollViewer.ScrollToVerticalOffset(200);

Ces 3 méthodes sont depuis peu marquées comme deprecated, et bien que le code continue à fonctionner, il est fortement recommander d’utiliser l’instruction ChangeView à la place.

Scrollviewer_ZoomToFactorLa syntaxe est plus simple à priori :

http://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.controls.scrollviewer.changeview(v=win.10).aspx

var Succes = scrollViewer.ChangeView(100, 200, 0.3F, false);

La vue est ici positionnée avec 30% de zoom avec un scroll horizontal de 100 pixels 200 vertical.

Le dernier paramètre permet de désactiver l’animation de zoom.

L’ensemble retourne true si le zoom a eu lieu.

il est également possible de ne faire qu’un zoom sans déplacement en remplaçant les valeurs inutilsées par null

var Succes = scrollViewer.ChangeView(null, null, 0.3F, false);

Le problème

Pourtant lorsque cette instruction est utilisée dans un projet WP8.1… rien ne se passe!

Poursuivre la lecture

Isolated Storage et Images sous Windows Phone 8

Je vous propose un petit tour d’horizon sur le stockage d’images dans l’Isolated Storage.

Pour rappel, l’Isolated storage est l’emplacement réservé à votre application Windows Phone pour le stockage de fichiers.

Quelles sont les implémentations qui permettent de récupérer une image déjà stockée dans cet espace ? Quelles sont les méthodes les plus efficaces ?

L’implémentation classique (Windows Phone 7)

C’est l’implémentation standard « old school » : j’utilise GetUserStoreForApplication() et OpenFile pour lire un Stream. Le Stream est ensuite lu par le BitmapImage et renvoyé dans une Action.

public static void LoadImageFromStorage(string name, Action<BitmapImage> actionBitmap)
{
    using (IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
    {
        if (myIsolatedStorage != null && myIsolatedStorage.FileExists(name))
        {
            IsolatedStorageFileStream fileStream = myIsolatedStorage.OpenFile(name, FileMode.Open, FileAccess.Read);
            {
                Deployment.Current.Dispatcher.BeginInvoke(() =>
                {
                    BitmapImage bitmapSource = new BitmapImage();
                    bitmapSource.SetSource(fileStream);
                    if (actionBitmap != null)
                        actionBitmap(bitmapSource);
                });
            }
        }
    }
}

Remarque 1

BitmapImage nécessite de s’exécuter dans le ThreadUI principal, pour cela, on utilise

Deployment.Current.Dispatcher.BeginInvoke(() =>

Poursuivre la lecture

HTTP et images sous Windows Phone

Je continue avec l’affichage des Images et je vous propose cette fois de voir les implémentations possibles pour récupérer des images depuis le Web avec le protocole http.

L’implémentation classique :

public static void GethttpImage1(string urlImage, Action<BitmapImage> action)  
{
  var request = (HttpWebRequest)WebRequest.Create(urlImage);
  request.BeginGetResponse(result =>
  {
    using (var sr = request.EndGetResponse(result))
    {
        Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
                var image = new BitmapImage();
                image.SetSource(sr.GetResponseStream());
                if (action != null)
                    action(image);
                sr.Close();
            });
    }
  }
}

urlImage contient l’url de l’image sous forme d’une châine de caractère : exemple : http://dev.bratched.fr/download/testimage1.png

La méthode utilise un WebRequest et lit la réponse de la requête sous forme d’un stream avec le request.EndGetResponse.

La partie

Deployment.Current.Dispatcher.BeginInvoke(() =>

est très importante car elle va permettre d’utiliser le BitmapImage dans le Thread Principal même lorsque la méthode est appelée dans un Thread tournant en tâche de fond.

Poursuivre la lecture

Utilisation des Images resources avec Windows Phone

Je vous propose un petit retour d’expérience sur l’utilisation des ressources dans le développement Windows Phone dans un modèle M-V-VM.

Différentes façon de coder

L’image que l’on souhaite afficher provient des ressources et devrait pouvoir s’afficher à travers une propriété Image de type BitmapImage dans un ViewModel. A noter que le dans l’exemple ci dessous, UIThreadPool permet d’afficher cette image même lorsque celle-ci est alimentée depuis un Thread qui tourne en tâche de fond.

SynchronizationContext UIThread = SynchronizationContext.Current;

public BitmapImage Image
       {
           get { return _image; }
           set
           {
               UIThread.Post(_ =>
                   {
                       _image = value;
                       RaisePropertyChanged("Image");
                   }, null);
           }
       }

Comment afficher une image incluse dans les ressources de l’application ?

Attention les 2 premières méthodes décrites sont à proscrire et à ne surtout pas reproduire. Allez jusqu’à la fin de l’article pour voir comment implémenter correctement l’affichage d’une image ressource. Poursuivre la lecture