Forums Développement Multimédia

Aller au contenu

- - - - -

Optimiser mes temps de chargement de contenu

CODE AS3 STARLING

14 réponses à ce sujet

#1 draad

  • Members
  • PipPipPipPipPipPipPipPip
  • 653 messages

Posté 18 February 2015 - 22:29 PM

Salut a tous.

Je pense que j'ai un probleme d'optimisation dans ma facon de charger les assets graphiques.

Voici la classe qui me sert a charger un asset graphique :


import flash.display.BitmapData;
import flash.display.Loader;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.net.URLRequest;
import flash.system.ImageDecodingPolicy;
import flash.system.LoaderContext;
import flash.utils.getTimer;

import events.Event_Context;

import starling.events.EventDispatcher;
import starling.textures.Texture;


public class Atlas_Loader extends EventDispatcher
{
  public  var path   :String;

  public  var loader   :Loader
  public  var sheet   :BitmapData;

  private var callback  :Function;
  private var loaderContext :LoaderContext



  public function Atlas_Loader()
  {
   loaderContext = new LoaderContext();
   loaderContext.imageDecodingPolicy = ImageDecodingPolicy.ON_LOAD;
 
   loader = new Loader ();
  }

  public function load (path:String, callback:Function):void
  {
   this.callback  = callback;
 
   loader.load(new URLRequest(path), null);
   loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoaded);
   loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR,  onLoadError);
  }

  private function onLoaded (e:Event):void
  {
   e.stopPropagation();
 
   loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, onLoaded);
   loader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR,  onLoadError);
 
   sheet = new BitmapData (loader.width, loader.height, true, 0x000000);
   //sheet.copyPixels(loader.content.bitmapData, new Rectangle(0, 0, loader.width, loader.height), new Point (0,0));
   sheet.draw(loader);
   sheet.lock();
 
   loader.unload();
   loader = null;
   if (callback != null)
   {
        callback();
   }
   else
   {
        dispatchEvent(new Event_Context(Event_Context.LOADING_COMPLETE, true));
   }
  }

  private function onLoadError (e:IOErrorEvent):void
  {
   loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, onLoaded);
   loader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR,  onLoadError);
   trace ('LOADER ERROR : ' + e);
  }


  public function getTexture ():Texture
  {
   return Texture.fromBitmapData(sheet, false, true);
  }


  public function disposeView ():void
  {
   if(sheet != null)
   {
        sheet.dispose();
        sheet = null;
   }
  }
}
 


Comme vous pouvez le voir dans la fonction onLoaded, je transform le contenu de mon loader en Bitmap data par le biais de .draw()
Mais mon petit doig me dit que ca serait plus rapide et plus optimise d'utiliser un simple copyPixel, ou encore d'acceder au bitmapData directement depuis le loader, ce qui, dans mon esprit, devrait etre possible, puisque on peut afficher un loader directement a l'ecran, c'est bien qu'il a un BitmapData cache quelquepart !

Mais bon voila, j'ai beau tourner et retourner la chose je ne trouve pas comment faire cela.

J'ai bien essaye de faire quelquechose comme ceci :

var bitmap:Bitmap = new Bitmap ();
   bitmap = Bitmap(loader.content);
   sheet.copyPixels(bitmap.bitmapData, new Rectangle(0, 0, bitmap.width, bitmap.height), new Point (0,0));
 

Seulement des fois ca marche et des fois pas ... Apparement certains assets sont consideres comme etant des MovieClip ce qui me cree des erreurs de conversion...

Bref, je m'en remet a votre infinie sagess, auriez vous quelques precieux conseils pour moi ?

Merci !

#2 Monsieur Spi

  • Community Manager
  • PipPipPipPipPipPipPipPip
  • 6954 messages

Posté 20 February 2015 - 15:14 PM

Hello,

Draw me semble plus lent que copypixels (à vérifier).

Citation

Apparement certains assets sont consideres comme etant des MovieClip
Transtype ou assure toi du format de tes données.
Là je ne vois pas bien à quel moment il peut te pondre un MovieClip.... surtout si tu charge une spritesheet.

#3 draad

  • Members
  • PipPipPipPipPipPipPipPip
  • 653 messages

Posté 20 February 2015 - 15:55 PM

Coucou Monsieur Spy,

Oui c'est ce que je voulais tester, mais pour le copy pixel il me faut le bitmpaData et donc je tombe dans mon probleme.

Je telecharge mes assets depuis un serveur et je les ecrit sur le disque, il semble que ce sont ces fichiers la qui sont interpretes comme etant des movieClip.


writeFile  = new File (_targetPath);
   writeStream = new FileStream ();
   writeStream.addEventListener(OutputProgressEvent.OUTPUT_PROGRESS, onProgress);
   writeStream.openAsync(writeFile, FileMode.WRITE);
   writeStream.writeBytes(loaderInfo.bytes, 0, loaderInfo.bytes.length);
 

Le chemin fini bien en .png, est-ce que je manque quelquechose dans ma maniere d'ecrire le fichier qui ferait qu'il soit interprete en tant que MovieClip au lieu de Bitmap?

#4 draad

  • Members
  • PipPipPipPipPipPipPipPip
  • 653 messages

Posté 26 February 2015 - 15:38 PM

Je me permet de faire remonter ce sujet car je ne trouve toujours aucune solution.

#5 pol2095

  • Members
  • PipPipPipPipPipPipPipPip
  • 1682 messages

Posté 26 February 2015 - 21:57 PM

je ne comprends pas trop ton pb, mais pour accéder à un BitmapData depuis un Loader, c'est juste :

private function onLoaded (e:Event):void
{
var sheet:BitmapData = event.target.content.bitmapData;
}
 


#6 draad

  • Members
  • PipPipPipPipPipPipPipPip
  • 653 messages

Posté 27 February 2015 - 00:53 AM

Coucou pol2095,

Pour résumer le probleme :

1 - Je charge des png depuis un serveur et je les ecris sur le disque de l'usager
2 - Lorsque j'en ai besoin, je charge ces memes png depuis le disque et je les transforme en Images
3 - J'aimerais utiliser copyPixel, mais pour ça j'ai besoin d'acceder au BitmapData

Mon probleme est ici
4 - Les fichiers que je charge grace au loader sont considérés comme des MovieClip, et non comme des Bitmap, ce qui m'empeche d'acceder a un BitmapData.

#7 pol2095

  • Members
  • PipPipPipPipPipPipPipPip
  • 1682 messages

Posté 27 February 2015 - 08:54 AM

le plus simple c'est de convertir ton Bitmap en png

var file:File = new File (_targetPath);
var fileStream:FileStream = new FileStream();
fileStream.open(file, FileMode.WRITE);
var byteArray:ByteArray = new ByteArray();
event.target.content.bitmapData.encode(new Rectangle(0,0,event.target.content.width,event.target.content.height), new flash.display.PNGEncoderOptions(), byteArray);
fileStream.writeBytes(byteArray, 0, byteArray.length);
fileStream.close();
 


#8 draad

  • Members
  • PipPipPipPipPipPipPipPip
  • 653 messages

Posté 27 February 2015 - 16:39 PM

Merci pour cette info pol2095, malheureusement, cela ne va pas etre possible de cette facon ... En effet, encoder le byteArray en PNG augmente le temps de chargement enormement, un asset qui prenait environ 2sec a charger avant prends maintenant pres de 40-50 sec !

huhuhu, y'a pas moyen d'ecrire le fichier en conservant ses proprietes d'origine ? Vu que mes assets sources sont deja des PNG je ne devrais pas avoir a les reencoder si ?

Merci pour votre aide.

#9 dldler

  • Community Manager
  • PipPipPipPipPipPipPipPip
  • 4163 messages

Posté 27 February 2015 - 16:58 PM

Je n'arrive pas à bien comprendre la problématique en fait…

Si je suis bien :
- tu as des fichiers png côté serveur
- tu les load via un loader graphique
- tu veux le enregistrer en local (pour décharger la mémoire ?)
- puis les charger du local à la demande
C'est bien ça ?

Donc, si je visualise bien l'enchainement
- les données png sont sur le seveur
- chargées en mémoire locale et donc décodées en bitmapdata
- tu enregistres les données décodées (bitampdata)
- tu voudrais les rouvrir comme si c'étaient des png

A ce stade, je suis d'accord avec Pol : tu ne dois pas enregistrer les données décodées brutes mais les rencoder en png.
Et il semble que ça marche. Sauf qu'évidemment, tu te payes 2 nouveaux encodages : bitmapdata vers png puis png vers bitmapdata… Problème de lenteur.

Si j'ai une vision claire à ce stade (mais je n'en suis pas sûr), je dirais tout simplement que tu dois enregistrer le bitmapdata sans l'encoder et le recharger sans le décoder… Ça restera lent puisque tu as des accès disques, mais moins que dans la solution précédente.

A ma connaissance (flou dans ma mémoire, parce que ça fait un moment que je n'ai pas manipuler de bitmapdata) mais tu peux encoder directement une occurrence flash dans un bytearray avec les instructions writeObject() et les lire avec readObject()… Donc, l'idée, c'est de récupérer le bitmapdata du loader graphique, le stocker, le recharger et l'attribuer à n'importe quel objet Bitmap… Je ne vois pas de chemin plus court.

Ai-je fait avancer le shmilblick ou bien suis-je passé à côté d'un truc ?

#10 pol2095

  • Members
  • PipPipPipPipPipPipPipPip
  • 1682 messages

Posté 27 February 2015 - 18:09 PM

une alternative :


var path:String = "http://www.tonsite.com/img.png";
var request:URLRequest = new URLRequest(path);
var urlLoader:URLLoader = new URLLoader(request);
urlLoader.dataFormat = URLLoaderDataFormat.BINARY;
urlLoader.addEventListener(Event.COMPLETE, onLoaded);
private function onLoaded(event:Event):void {
  var bytes:ByteArray = event.target.data;
  var file:File = File.applicationStorageDirectory.resolvePath("img.png");
  var fileStream:FileStream = new FileStream();
  fileStream.open(file, FileMode.WRITE);
  fileStream.writeBytes(bytes, 0, bytes.length);
  fileStream.close();

  var loaderContext:LoaderContext = new LoaderContext();
  oaderContext.allowCodeImport = true;
  var ld:Loader = new Loader();
  ld.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoaded2);
  ld.loadBytes(bytes, loaderContext);
}
private function onLoaded2(event:Event):void {
  var sheet:BitmapData = event.target.content.bitmapData;
}
 

ensuite qaund tu relances l'application, tu te sers d'un Loader pour récupérer le png sur le disque

#11 draad

  • Members
  • PipPipPipPipPipPipPipPip
  • 653 messages

Posté 27 February 2015 - 19:46 PM

Coucou,

Pol2095 : ha! Je suis arrive au meme test que toi en decale, effectivement si j'utilise un URLLoader en mode BINARY, je peux charger et ecrire un png sur le disque sans avoir a le reencoder. C'est donc deja une tres bonne piste, merci.

Didier : Oui tu as compris l'idee, juste une precision si j'enregistre les png sur le disque c'est pour pouvoir y acceder meme lorsqu'il n'y a plus de connexion internet. J'ai commence a essayer d'implementer ton idee de writeObject()/readObject(). Au fond, si je peux grace a cette technique ecrire une Texture (classe starling) directement et y acceder directement, j'imagine que ca serait la solution la plus rapide.


Pour resumer, a priori il y aurait trois solution possibles :

a ) solution actuelle. Pas assez performante.
  • 1 - J'ecris une image via un Loader sur le disque.
  • 2 - Je charge cette image via un Loader.
  • 3 - Je copy cette image dans un bitmapData via .draw()
  • 4 - Je cree ma texture quand j'en ai besoin.
b ) solution de Pol2095. Plus performant a priori, vu qu'on n'a plus l'etape de draw().
  • 1 - J'ecris un PNG via un URLLoader sur le disque.
  • 2 - Je charge cette image via un Loader et recupere directement son bitmapdata.
  • 3 - Je cree ma texture quand j'en ai besoin.
c ) solution de Didier. A tester
  • 1 - Je charge un PNG via un Loader
  • 2 - Je transform ce PNG en texture starling.
  • 3 - J'ecris la Texture sur le disque.
  • 4 - Je charge cette texture via un un readObject() quand j'en ai besoin.


Merci pour votre aide, je vais essayer les solutions b et c et je vous dirais laquelle semble le plus performante.

#12 pol2095

  • Members
  • PipPipPipPipPipPipPipPip
  • 1682 messages

Posté 28 February 2015 - 21:57 PM

j'ai fais un petit test pour un gros fichier png sur windows, il faut 1368 ms pour enregistrer l'image avec fileStream.open(file, FileMode.WRITE), alors que la même image est enregistré dans un fichier sqlite en 244 ms.

#13 draad

  • Members
  • PipPipPipPipPipPipPipPip
  • 653 messages

Posté 28 February 2015 - 22:48 PM

Coucou pol2095.

Qu'est ce qu'un fichier Sqlite ? D'apres une recherche rapide sur le net, il s'agit d'un format de base de données.

#14 pol2095

  • Members
  • PipPipPipPipPipPipPipPip
  • 1682 messages

Posté 01 March 2015 - 00:08 AM

c'est une bdd local qui est contenu dans un fichier sur le disque sur laquelle on peut faire des requêtes, insertion... il y a un type intéressant pour enregistrer les images "blob".
Il y a un module Firefox qui permet de gérer les fichiers sqlite : "sqlite manager".

#15 draad

  • Members
  • PipPipPipPipPipPipPipPip
  • 653 messages

Posté 04 March 2015 - 15:34 PM

Juste un petit coucou pour vous dire que je ne vous oublie aps pour le resultat des tests, j'ai seulement du faire passer un autre projet en priorite, je vous tiens donc au courant quand j'aurais eu le temps de tester !

Merci encore :)

Bisoux




Répondre à ce sujet



  

1 utilisateur(s) li(sen)t ce sujet

0 membre(s), 1 invité(s), 0 utilisateur(s) anonyme(s)

authorised training centre

Centre de Formation Mediabox - Adobe et Apple Authorised Training Center.

Déclaré auprès de la Direction du Travail et de la Formation Professionnelle

Mediabox : SARL au capital de 62.000€ - Numéro d'activité : 11 75 44555 75 - SIRET : 49371646800035

MEDIABOX, 23, rue de Bruxelles, 75009 PARIS

FFP