Warning : This page has been marked as an archive because the author consider that its content is no longer relevant.

Récemment j’ai voulu baisser la qualité d’une image JPEG dans Windows Phone. J’ai donc recupéré l’image que l’utilisateur souhaite compresser grâce à une PhotoChooserTask et utilisé une manière classique de compresser l’image : passer par un WriteableBitmap et d’utiliser les méthodes d’extensions JPEG (System.Windows.Media.Imaging.Extensions) pour compresser l’image. Une fois ceci fait on sauvegarde le MemoryStream dans un fichier du stockage local et le tour est joué.

private async void photoTask_Completed(object sender, PhotoResult e)
{
    if (e.TaskResult == TaskResult.OK)
    {
        try
        {
            var filename = "test.jpg";
            var bi = new BitmapImage();

            // Récupération de l'image choisie par l'utilisateur
            bi.SetSource(e.ChosenPhoto);

            string filePath = null;

            // Création du Stream qui contiendra l'image compressée
            using (var ms = new MemoryStream())
            {
                // Initialisation du WriteableBitmap
                var wb = new WriteableBitmap(bi);

                // Compression de l'image à 40%
                wb.SaveJpeg(ms, wb.PixelWidth, wb.PixelHeight, 0, 40);

                // filePath représente le chemin absolu de l'image sur le stockage du téléphone.
                var file = await ApplicationData.Current.LocalFolder.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting);

                // Ecriture du Stream sur le disque.
                using (var stream = await file.OpenStreamForWriteAsync())
                {
                     await ms.CopyToAsync(stream);
                }
                filePath = file.Path;
            }
        }
        catch (Exception ex)
        {
             // TODO : Gérer les exception
        }
    }
}

Enfin ça c’est la théorie, si on ne fait pas un minimum attention dans la pratique on oublie un élément important : certaines méthodes peuvent changer la position actuelle du Stream lors de son traitement. C’est le cas de la méthode SaveJpeg qui le positionne à la fin. Du coup, si on essaie d’écrire le MemoryStream sur le disque on a un beau fichier vide à la place de notre image.

Afin de sauvegarder notre image il faut bien penser à remettre le Stream au début avant de l’écrire sur le disque.

private async void photoTask_Completed(object sender, PhotoResult e)
{
    if (e.TaskResult == TaskResult.OK)
    {
        try
        {
            var filename = "test.jpg";
            var bi = new BitmapImage();

            // Récupération de l'image choisie par l'utilisateur
            bi.SetSource(e.ChosenPhoto);

            string filePath = null;

            // Création du Stream qui contiendra l'image compressée
            using (var ms = new MemoryStream())
            {
                // Initialisation du WriteableBitmap
                var wb = new WriteableBitmap(bi);

                // Compression de l'image à 40%
                wb.SaveJpeg(ms, wb.PixelWidth, wb.PixelHeight, 0, 40);

                // On rembobine le Stream
                ms.Seek(0, SeekOrigin.Begin);

                // filePath représente le chemin absolu de l'image sur le stockage du téléphone.
                var file = await ApplicationData.Current.LocalFolder.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting);

                // Ecriture du Stream sur le disque.
                using (var stream = await file.OpenStreamForWriteAsync())
                {
                     await ms.CopyToAsync(stream);
                }
                filePath = file.Path;
            }
        }
        catch (Exception ex)
        {
             // TODO : Gérer les exception
        }
    }
}

Avec le code ci-dessus la sauvegarde se passe correctement.

En résumé, faîtes bien attention à la position actuelle de vos Streams lorsque vous les utilisez.

Comments