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
- AIR pour Android – Enregistrer une image dans la galerie avec CameraRoll et addBitmapData
- AIR pour Android – Récupérer une image issue de la galerie Caméra avec CameraRoll (browseForImage)
- AIR pour Android – Utilisation de l'Accelerometer dans une application Air
- AIR pour Android – Prendre des photos / vidéos avec CameraUI
- AIR Mobile – Utilisation de CameraUI (Appareil photo) sous Android, iOS et BlackBerry Tablet OS
Aucun trackbacks pour l'instant





