Apache Adobe Flex TutorialTutoriaux Adobe Flex & AIR en Français

9oct/100

Flex Library – PNGEncoder asynchrone (encodage BitmapData vers ByteArray PNG async)

Je bosse en ce moment sur une application mobile AIR pour Android (c'est pour cela que je poste peu de billets ces temps-ci, cela devrait reprendre la semaine prochaine :) ). Dans celle-ci, je permet à l'utilisateur de prendre une photo à l'aide de CameraUI avec l'appareil photo natif du téléphone.

Si vous voulez faire de même, j'ai déjà publié un article sur le code qui permet de faire cela que je vous invite à lire:

AIR pour Android – Prendre des photos / vidéos avec CameraUI

A l"issue de la prise de photo, j'obtiens donc un objet de type Bitmap que je peux afficher dans mon application. Mais dans mon cas, il me fallait envoyer cette donnée au serveur pour qu'il puisse mettre à jour une BDD. Pour cela, je dois encoder le BitmapData de mon Bitmap en PNG, le passer en Base64 (String) et l'envoyer à mon serveur.

Flex dispose d'une classe nommée mx.graphics.codec.PNGEncoder qui permet de faire l'encodage en PNG de mon BitmapData. Au passage, il y a aussi une classe qui permet d'encoder en JPEG mais qui est bien plus lente (facteur 2.5 d'après mes expérimentations).

J'ai donc essayé de réaliser l'encodage avec cette classe dans mon code et de le jouer sur Android. A ce moment-là, l'application s'est "freeze" avec un message du système Android me prévenant après quelques temps que l'application ne répondait pas (force close).

Le problème vient en fait de la qualité de l'image récupérée et de la compression. Sur un appareil photo moderne (type HTC Desire), les photos sont prises en haute résolution et sont en fait bien plus large que la surface de l'écran (ce qui leur donne une très bonne qualité sur les écrans mobiles dans les DPI sont bien plus importants).

L'encodage d'une image aussi grosse prenait donc du temps et le processus synchrone faisait fonctionner le portable à pleine puissance pendant plusieurs dizaines de secondes. Le mécanisme de vérification du statut "up" des applications Android la voyait donc comme plantée.

Réduire la taille de l'image

Dans mon cas d'utilisation, je n'ai pas besoin d'avoir une photo en qualité HD, je vais donc tout d'abord réduire la taille de l'image. Assez simple, on prend le BitmapData et on le dessine dans un BitmapData plus petit avec une Matrix:

var bmd:BitmapData = content.bitmapData;
 var factor:Number = .4;
 var mat:Matrix = new Matrix();
 mat.scale(factor, factor);
 var bd:BitmapData = new BitmapData(bmd.width * factor, bmd.height * factor, false, 0xffffff);
 // smoothing = last param
 bd.draw(bmd, mat, null, null, null, false);

A vous de choisir le facteur qui vous convient le mieux…

Encodage PNG asynchrone

La classe PNGEncoder de Flex permet donc seulement un encodage PNG synchrone. Cela signifie que l'application ne répondra plus tant que le traitement n'est pas terminé.

Heureusement, il existe une autre librairie qui permet de faire cet encodage de manière asynchrone.

Cette librairie, créée par un certain Eugène (http://blog.inspirit.ru/) est hébergée sur Google Code:

Voir le projet PNGEncoder sur Google Code

Notez que cette librairie permet aussi d'avoir d'autres fonctionnalités comme le "merge" de BitmapData en un seul PNG ou de préciser un facteur de compression ZLIB ainsi que des filtres PNG.

Autre point important, cette librairie nécessite de target Flash Player 10 et utilise Vector par exemple. Vous ne pourrez pas l'utiliser dans une application pour Flash Player 9.

Vous pouvez donc vous abonner à un évènement COMPLETE et PROGRESS pour afficher la progression en live de la compression.

Articles similaires

Commentaires (0) Trackbacks (0)

Aucun commentaire pour l'instant


Leave a comment

(required)

Aucun trackbacks pour l'instant