<?xml version="1.0" encoding="utf-8"?><rss version="2.0"><channel><title>c2i.fr - IO</title><link>http://www.c2i.fr:80/Tags/IO</link><description>c2i.fr - IO</description><item><title>Comment redimensionner une image avec WinRT : plusieurs solutions</title><link>http://www.c2i.fr:80/articles/comment-redimensionner-une-image-avec-winrt-plusieurs-solutions</link><description>&lt;p&gt;J'ai particip&amp;eacute; hier &amp;agrave; une session du Tour de France Windows 8 &amp;agrave; Bordeaux. Session tr&amp;egrave;s sympathique avec de charmants co-d&amp;eacute;veloppeurs.&lt;/p&gt;
&lt;p&gt;J'en ai profit&amp;eacute; pour m'avancer sur mon projet d'application WinRT et de me pencher plus avant sur la probl&amp;eacute;matique suivante :&lt;/p&gt;
&lt;p&gt;J'ai des nombreuses images dans mon application qui sont de taille "importante" (sup&amp;eacute;rieure &amp;agrave;&amp;nbsp;1024*768). Or il se trouve que ces images peuvent &amp;ecirc;tre utilis&amp;eacute;es pour la vignette de mon application. J'ai donc soit le choix de cr&amp;eacute;er "&amp;agrave; la main" une version light de mes images, soit ajouter la fonctionnalit&amp;eacute; &amp;agrave; mon application de redimensionnement d'images (pour info, le poids&amp;nbsp;des images affich&amp;eacute;es dans les vignettes est limit&amp;eacute;e, 150Ko je crois de m&amp;eacute;moire).&lt;/p&gt;
&lt;p&gt;La solution que j'ai trouv&amp;eacute;e &amp;eacute;tait la suivante :&lt;/p&gt;
&lt;h2&gt;Une solution "pas simple"&lt;/h2&gt;
&lt;p&gt;La premi&amp;egrave;re &amp;eacute;tape consiste &amp;agrave; r&amp;eacute;cup&amp;eacute;rer la premi&amp;egrave;re frame de l'image &amp;agrave; partir du fichier :&lt;/p&gt;
&lt;pre class="brush: csharp;"&gt;// imageFilename 
//      C'est le nom du fichier. 
//      Ici, c'est un fichier image que l'on a plac&amp;eacute; dans notre projet en tant que Contenu
//      (r&amp;eacute;pertoire Assets dans le projet template de MS) 
//      Il se trouve donc dans le InstalledLocation
//      r&amp;eacute;cup&amp;eacute;ration du fichier, StorageFile
// fileName
//      nom du fichier que l'on veut sauvegarder
// width, height
//      largeur et hauteur de l'image finale d&amp;eacute;sir&amp;eacute;e

var file = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFileAsync(imageFilename);
// r&amp;eacute;cup&amp;eacute;ration du flux du fichier
var baseStream = RandomAccessStreamReference.CreateFromFile(file);
// d&amp;eacute;codeur de l'image &amp;agrave; partir du flux ouvert en lecture
var fileDecoder = await Windows.Graphics.Imaging.BitmapDecoder.CreateAsync(await baseStream.OpenReadAsync());
// r&amp;eacute;cup&amp;eacute;ration de la premi&amp;egrave;re frame de l'image
var bitmapFrame = await fileDecoder.GetFrameAsync(0);&lt;/pre&gt;
&lt;p&gt;Ensuite, on r&amp;eacute;cup&amp;egrave;re les pixels de notre image en sp&amp;eacute;cifiant la taille de l'image finale :&lt;/p&gt;
&lt;pre class="brush: csharp;"&gt;// on veut une image de la taille width*height
var bitmapTransform = new BitmapTransform { ScaledWidth = width, ScaledHeight = height };
// r&amp;eacute;cup&amp;eacute;ration des pixels
var pixelDatas =
    await bitmapFrame.GetPixelDataAsync(
        bitmapFrame.BitmapPixelFormat,
        bitmapFrame.BitmapAlphaMode,
        bitmapTransform,
        ExifOrientationMode.IgnoreExifOrientation,
        ColorManagementMode.DoNotColorManage);&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Enfin, on cr&amp;eacute;e le fichier final et on &amp;eacute;crit les pixels dedans :&lt;/p&gt;
&lt;pre class="brush: csharp;"&gt;// le fichier ou l'on souhaite enregistrer l'image redimensionn&amp;eacute;e.
// On la place dans le LocalFolder de l'application
var targetFile =
    await Windows.Storage.ApplicationData.Current.LocalFolder.CreateFileAsync(
        fileName,
        CreationCollisionOption.ReplaceExisting)
        .AsTask&amp;lt;storagefile&amp;gt;();

// ouverture du flux pour &amp;eacute;crire dans le fichier
using (var fileStream = await targetFile.OpenAsync(FileAccessMode.ReadWrite))
{
    // l'encodeur de notre nouveau fichier image
    var newBitmapEncoder = 
        await Windows.Graphics.Imaging.BitmapEncoder.CreateAsync(
            BitmapEncoder.JpegEncoderId, 
            fileStream);
    // on &amp;eacute;crit les pixels dans notre nouveau fichier en respectant les infos d'origine (dpi, alpha, etc.)
    newBitmapEncoder.SetPixelData(
        bitmapFrame.BitmapPixelFormat, 
        bitmapFrame.BitmapAlphaMode, 
        bitmapTransform.ScaledWidth, 
        bitmapTransform.ScaledHeight, 
        bitmapFrame.DpiX, 
        bitmapFrame.DpiY, 
        pixelDatas.DetachPixelData());

    // on s'assure que l'on vide bien tout
    await newBitmapEncoder.FlushAsync();
    await fileStream.FlushAsync();
}&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Ce n'est pas vraiment simple, mais ca marche.&lt;/p&gt;
&lt;h2&gt;Une solution plus simple&lt;/h2&gt;
&lt;p&gt;Montrant ce code &amp;agrave; notre cher GO, aka Benoit Laut de Bewise, il me dit : "Mais non, esp&amp;egrave;ce d'abruti, y'a beaucoup plus simple :!".&lt;/p&gt;
&lt;p&gt;Bon, OK, il m'a pas dit ca comme ca exactement ;-). Je pr&amp;eacute;cise pour ceux qui comprendrait pas le second degr&amp;eacute;. Il m'a dit tr&amp;egrave;s gentillement qu'il pensait qu'il y avait plus simple, notamment avec les m&amp;eacute;thodes GetThumbnails du framework. Il a donc recherch&amp;eacute; et quelques temps plus tard, il m'a trouv&amp;eacute; le code suivant :&lt;/p&gt;
&lt;pre class="brush:csharp;"&gt;var file = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFileAsync(imageFilename);
// on veut une vignette de type image de largeur width et redimensionn&amp;eacute;e
var thumbnail = await file.GetThumbnailAsync(
    Windows.Storage.FileProperties.ThumbnailMode.PicturesView, 
    width, 
    Windows.Storage.FileProperties.ThumbnailOptions.ResizeThumbnail);

// on cr&amp;eacute;e le fichier cible
var storageFile = await Windows.Storage.ApplicationData.Current.LocalFolder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
// ATTENTION : Ajoutez System.IO qui comprend ces m&amp;eacute;thodes d'extensions
// le flux ou l'on souhaite &amp;eacute;crire
var writer = await storageFile.OpenStreamForWriteAsync(); 
var outputStream = writer.AsOutputStream();

// sauvegarde dans le flux de la vignette
await RandomAccessStream.CopyAndCloseAsync(thumbnail, outputStream);&lt;/pre&gt;
&lt;p&gt;Il y a quand m&amp;ecirc;me beaucoup moins de ligne de code, et ca &amp;agrave; l'air plus simple.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;MAIS&lt;/h2&gt;
&lt;p&gt;Car souvent avec moi, il y a un MAIS. J'ai donc voulu voir le r&amp;eacute;sultat de ces deux possibilit&amp;eacute;s. Concr&amp;egrave;tement, on obtient bien une vignette avec la taille d&amp;eacute;sir&amp;eacute;e (dans le deuxi&amp;egrave;me cas, on ne peut pas sp&amp;eacute;cifier la largeur ET la hauteur, mais ce n'est pas grave dans notre cas). Les deux images sont bien g&amp;eacute;n&amp;eacute;r&amp;eacute;es :&lt;/p&gt;
&lt;p&gt;&lt;img width="733" height="236" alt="" src="/Media/Default/BlogPost/articles/comment-redimensionner-une-image-avec-winrt-plusieurs-solutions/redimImage.JPG" /&gt;&lt;/p&gt;
&lt;p&gt;J'ai bien mes patates redimensionn&amp;eacute;es et on peut constater que le temps d'ex&amp;eacute;cution est sensiblement le m&amp;ecirc;me.&lt;/p&gt;
&lt;p&gt;Mais concernant le poids des fichiers, ce n'est pas du tout la m&amp;ecirc;me histoire.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Le fichier d'origine fait 250Ko.&lt;/li&gt;
&lt;li&gt;Le ficher avec la m&amp;eacute;thode complexe fait 36Ko&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Le fichier avec la m&amp;eacute;thode simple fait 250Ko !!!&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;C'est bizarre (et si vous avez une explication, je suis preneur). Mais toujours est-il que je vas donc utiliser la m&amp;eacute;thode "complexe" dans mon application.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Tout comme dans le framework .NET "normal", pour faire une m&amp;ecirc;me op&amp;eacute;ration, on a de multiples possibilit&amp;eacute;s. Mais l'avantage avec le framework normal, c'est que gr&amp;acirc;ce &amp;agrave; des d&amp;eacute;compilateurs, on peut savoir pourquoi. Peux &amp;ecirc;tre que sur des images beaucoup plus lourde, la solution complexe est beaucoup plus rapide, peux &amp;ecirc;tre qu'avec la version finale, le poid de l'image finale sera optimis&amp;eacute;e.&lt;/p&gt;
&lt;p&gt;Mais comme on n'a pas acc&amp;egrave;s &amp;agrave; des d&amp;eacute;compilateurs pour voir le code qui est r&amp;eacute;ellement ex&amp;eacute;cut&amp;eacute;, on est encore dans le flou, et seul des tests permettent de savoir ce qu'il faut utiliser.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description><pubDate>Fri, 11 May 2012 13:48:33 GMT</pubDate><guid isPermaLink="true">http://www.c2i.fr:80/articles/comment-redimensionner-une-image-avec-winrt-plusieurs-solutions</guid></item></channel></rss>