L’AS3 à permis d’ouvrir la porte à pas mal de choses dont 2 intéressantes : la gestion native de ByteArray et le chargement dynamique de SWF à partir de données contenu dans un ByteArray.
Dit comme ça, ça n’a pas forcément d’intérêt immédiat. Seulement, le fait de pouvoir modifier/générer les données binaires d’un SWF et de les charger pour les récuperer sous forme native, ça change pas mal de choses !
Image, vidéo ou vectoriel bon ça on peut déjà le faire nativement avec BitmapData et Video ou Shape. Mais on peux aussi le faire pour du son, du code ActionScript, ou pour une police embarquée. C’est ce dernier point, qui m’intéresse et qui n’a pas encore vraiment été exploré.
Pour ce faire, j’ai appris à lire les données brut du format SWF : demo, sources
Attention les logs générés sont assez lourds ~1Mo pour un SWF d’environ 30Ko contenant seulement une police embarqué.
Ca lit les données global d’un SWF (dimensions, couleur de fond, bibliothèque) ainsi que tout la partie qui gère les polices (le nom de la police, les données de dessins des glyphs …). Il faudra ensuite que je fasse l’opération inverse : génerer les données nécéssaire à l’intégration d’une police dans un SWF.
Liens :
Un problème auquel j’ai été confronté récemment, c’est le poids que font des PNG 32bits de taille moyen ~ 400px * 500px pour ~ 200Ko. En passant par PNGOUT on gagne une ou deux dizaine de kilooctet au maximum.
Seulement, ces images au nombre d’une vingtaine était utilisé simultanément (ou presque). Rien qu’une image au poids de 200Ko dépasse largement le poids normal conseillé d’une page HTML (JS + CSS + images compris).
Pourtant je devais absolument disposer d’images transparente. Hélas seul le format acceptable dans ce cas est le PNG. Le BMP, TIFF ou encore TGA étant encore plus lourd, de plus non géré nativement dans Flash. Comment réduire le poid (compression lossy ?) et tout en conservant la transparence (une palette gris ?) tout ça en utilisant un containers supportés par Flash ou en passant par une librairies (si faut pas la faire une sois même) ?
Je suis pas allé très loin pour trouver la solution : utiliser 2 images au lieu d’une. Un JPEG pour les canneaux rouge, vert, bleu, plus un PNG 8bits (voir moins) en palette de gris pour la transparence. Restait plus qu’a les gérer dans flash.
var rgb:BitmapData = myRGBBitmapData; var alpha:BitmapData = myAlphaBitmapData; //Loaded JPEG BitmapData are not transparent argb = new BitmapData(rgb.width, rgb.height, true, 0x00000000); //Copy RGB argb.copyPixels ( rgb, new Rectangle(0, 0, rgb.width, rgb.height), new Point(0, 0) ) //Apply alpha channel argb.copyChannel ( alpha, new Rectangle(0, 0, alpha.width, alpha.height), new Point(0, 0), BitmapDataChannel.RED,//r = g = b = gray BitmapDataChannel.ALPHA ); //ARGB is ready to use argb;
Le réslutat :
RGB (JPEG) (32 024 octets) + Alpha (PNG8) (12 037 octets) = 44 061 octets vs. Result (PNG32) (58 618 octets). Soit un gain de 25% par rapport à l’original. On peut même atteindre un gain de 90%.
On pourrai aller encore plus loin en les compressant dans un fichier 7zip. Dans notre cas celui ci permet de gagner encore 10 422 octets, soit au final 57% de la taille originale.
Dans tout ça, le problème après, c’est le temps de calcul nécessaire à la lecture et la décompression du(des) fichier(s) chargé(s) plus le temps de calcul pour que Flash fasse la fusion des 2 images.
Les sources :
Mais sinon pourquoi pas ?
Some classes name from ABC data :
//Inverse Kinematics fl.ik:IKBone fl.ik:IKJoint fl.ik:IKNode fl.ik:IKLink fl.ik:IKSubTree fl.ik:IKArmature fl.ik:IKShapeTree fl.ik:IKShapeNode fl.ik:IKUtils fl.ik:Contour fl.ik:ContourPoint fl.ik:ConnectionData fl.ik:IKSymbolNode fl.ik:IKManager //Vector Data Type __AS3__.vec.Vector //Maybe not new ? GraphicsPath IGraphicsData //Custom Filters and Effects Shader flash.filters:ShaderFilter flash.display:ShaderParameter //? com.adobe.astrobox.events:FaceEvent com.adobe.astrobox.events:Tween3DEvent com.adobe.astrobox.events:TrackEvent com.adobe.astrobox.transitions:Tween3D com.adobe.astrobox.managers:FaceManager com.adobe.astrobox.display:Face com.adobe.astrobox.views:Main//Use for Main.swf //Text vellum_flash //FOV property access <DisplayObject>.transform.perspectiveProjection.fieldOfView = 50