Chargement des images

17:49 modifié dans API UIKit #1
Bonjour à  tous,

Je travail actuellement sur un remake de "Photos" pour iPhone.
Je suis confronté à  un gros problème -> le chargement des photos. Pour l'instant je bosse en fullscreen donc ce que je fais c'est que je charge au maximum 3 images : la précedente, l'acutelle, et la suivante.
Ouaip.. mais c'est super lent quand meme. Plutôt acceptable dans le simulateur, mais sur un vrai iPhone c'est la catastrophe.
Est-ce qu'il y a une solution plus simple ? Déjà  que je suis étonné qu'Apple ne propose pas un mode slideshow du meme genre que Photos, et encore plus pour le mode quadrillage des photos...

Merci,
Louka.

Réponses

  • CeetixCeetix Membre
    17:49 modifié #2
    Salut Louka, sur ta question je ne peux t'aider, par contre j'aimerai rajouter un point, il semble que l'iphone n'affiche que des images en dessous d'une certaine résolution. Si l'image est trop grande eh bien, rien n'apparaà®t (alors que sur le simulateur tout fonctionne). Donc méfiez-vous si vous n'avez que le simulateur pour tester.
  • Philippe49Philippe49 Membre
    17:49 modifié #3
    Chapitre 11 du livre d'Erica Sadun
  • Philippe49Philippe49 Membre
    17:49 modifié #4
    ou chapitre 12 du bouquin de chez O'Reilly
  • 17:49 modifié #5
    Il est dispo en téléchargement numérique ? J'en avais acheté un comme ça sur CoreAnimation.

    Sinon j'ai baissé la résolution (c'était des fond d'écran au départ pour tester) et j'ai enregistré en PNG car une rumeur circule comme quoi ça charge plus vite en PNG.. mouaip on dirait aussi après un test sur mon iPhone.
    Pour l'instant je charge les images dès le lancement de l'application. Le seule problème c'est que j'ai peur pour la RAM après.
    Tous les examples de slideshow que j'ai pu trouver utilisait la méthode de tout charger direct.

    Au départ j'avais fait un fullscreen qui ne charge que les images qui se trouvent à  côté de celle qu'on visionne, le problème c'était que dès qu'on change d'image, fallait en charger une nouvelle, et ça faisait un petit lag très court sur le simulateur (à  peine visible), mais assez visible sur l'iPhone.

    Il y a un moyen simple de suivre la consommation de RAM avec le simulateur iPhone ? ou meme avec un test sur iPhone direct ?
  • AliGatorAliGator Membre, Modérateur
    17:49 modifié #6
    Heu le chargement des images précédentes/suivantes quand tu changes de photo, tu le fais bien dans un thread dédié au moins ? L'idéal étant d'avoir une sorte de "gestion de cache" pour que tant que tu n'as pas besoin de libérer de la RAM, ça garde en mémoire les images déjà  préchargées...
    L'idée est de garder en mémoire les images déjà  chargées plutôt que de les supprimer, et d'utiliser la notification que l'iPhone t'envoie quand il a besoin de libérer la mémoire (didReceiveMemoryWarning) pour faire le ménage des images trop loin de l'image actuellement visionnée quand il y a besoin de libérer de la RAM.
  • 17:49 modifié #7
    dans 1237202387:

    Heu le chargement des images précédentes/suivantes quand tu changes de photo, tu le fais bien dans un thread dédié au moins ? L'idéal étant d'avoir une sorte de "gestion de cache" pour que tant que tu n'as pas besoin de libérer de la RAM, ça garde en mémoire les images déjà  préchargées...
    L'idée est de garder en mémoire les images déjà  chargées plutôt que de les supprimer, et d'utiliser la notification que l'iPhone t'envoie quand il a besoin de libérer la mémoire (didReceiveMemoryWarning) pour faire le ménage des images trop loin de l'image actuellement visionnée quand il y a besoin de libérer de la RAM.


    Ouaip j'ai pensé au thread mais j'ai pas encore l'habitude de dev sur iPhone, pour moi dans ma tête ça reste super limité en fait.
    Bon je vais faire comme ça, ça sera mieux.
    Mais je suis quand meme dégouté qu'Apple ne propose pas au moins un mode quadrillage pour les photos... bouuuhhh (iPhone OS 3 ptete :D )
  • 17:49 modifié #8
    Bon j'ai threadé et c'est nickel 
  • 17:49 modifié #9
    Bon je comprend pas, j'ai une fuite mémoire pourtant je charge que 3 images maxi à  chaque fois.
    J'ai un singleton "SharedPhotos" qui se charge d'initialiser les photos. C'est lui qui contient la array "mPhotos" qui sont les 3 photos maxi actuelles, ainsi que "mData" qui est une array qui contient simplement les noms des images à  charger.

    Voilà  comment je procède. Lorsque je charge ma vue qui fait le fullscreen pour la navigation, je récupère les index les plus proche (au début c'est index 0 et 1 de mData vu que -1 est impossible). puis j'envoie une array qui contient donc les 2 premières photos à  charger :

    (bon j'ai un peu déliré sur la variable booléenne "isBossing" :p )
    - (void)loadPhotos:(NSArray*)photos<br />{<br />	if(isBossing)<br />		return;<br />	<br />	isBossing=YES;<br />	[NSThread detachNewThreadSelector:@selector(getPhotos:) toTarget:self withObject:photos];<br />}<br />- (void)getPhotos:(NSArray*)photos<br />{<br />	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];<br />	<br />	NSEnumerator* e = [photos objectEnumerator];<br />	id photo;<br />	<br />	NSMutableArray* newPhotos = [NSMutableArray array];<br />	while(photo = [e nextObject]){<br />		UIImage* myPhoto = [UIImage imageNamed:photo];<br />		if(myPhoto!=nil) [newPhotos addObject:myPhoto];<br />		<br />	}<br />	<br />	if(mPhotos!=newPhotos){<br />		[mPhotos release];<br />		mPhotos = [newPhotos retain];<br />	}<br />	[self performSelectorOnMainThread:@selector(photosLoaded) withObject:nil waitUntilDone:YES];<br />	[pool release];<br />}<br /><br />- (void)photosLoaded<br />{<br />	isBossing=NO;<br />	[[NSNotificationCenter defaultCenter] postNotificationName:@&quot;PhotosDidFinishLoad&quot; object:nil];<br />}<br /><br />- (NSArray*)photos<br />{<br />	return [[mPhotos retain] autorelease];<br />}<br />
    


    Après j'envoie la notification à  ma vue et elle commence à  initialiser les UIImageView avec les images chargées. Mon controlleur peut récupérer la array mPhoto quand il veut.
    Pour initialiser les UIImageView, je supprime toutes les subviews de ma scrollview, puis je les réinitialise avec la array mPhoto.

    <br />- (void)reloadSubviews<br />{<br />NSEnumerator* e = [[scrollView subviews] objectEnumerator];<br />	id subview;<br />	while(subview = [e nextObject])<br />		[subview removeFromSuperview];<br /><br />	// Exemple avec l&#39;initialisation de UIImageView pour la photo visionnée actuellement<br />	UIImageView* imageView;<br />		imageView = [[UIImageView alloc] initWithImage:[[sharedPhotos photos] objectAtIndex:0]];<br />		imageView.contentMode = UIViewContentModeScaleAspectFit;<br />		CGRect rect = imageView.frame;<br />		rect.size.height = scrollView.frame.size.height;<br />		rect.size.width = scrollView.frame.size.width;<br />		rect.origin.x=scrollView.frame.size.width*(currentIndex-1);<br />		imageView.frame = rect;<br />		imageView.tag = currentIndex;	<br />		[scrollView addSubview:imageView];<br /><br />		[imageView release];<br />	}<br /><br />// Chargement des deux autres : précédente et suivante<br />// ...<br /><br />}<br />
    


    Pour moi ça peut fuir que de là ... mais alors où... je sais pas du tout.
  • 17:49 modifié #10
    Apparemment ça vient de l'initialisation de UIImage. Il semble toujours garder en cache les UIImage. Mais dans ce cas comment vider ce cache ? Puisque le fait de releaser la array mPhotos ça ne change rien.
    Je suis passé sur initWithContentsOfFile: sauf que l'initialisation est plus longue.. zut.
  • AliGatorAliGator Membre, Modérateur
    17:49 modifié #11
    Images and Memory Management

    In low-memory situations, image data may be purged from a UIImage object to free up memory on the system. This purging behavior affects only the image data stored internally by the UIImage object and not the object itself. When you attempt to draw an image whose data has been purged, the image object automatically reloads the data from its original file. This extra load step, however, may incur a small performance penalty.

    You should avoid creating UIImage objects that are greater than 1024 x 1024 in size. Besides the large amount of memory such an image would consume, you may run into problems when using the image as a texture in OpenGL ES or when drawing the image to a view or layer. This size restriction does not apply if you are performing code-based manipulations, such as resizing an image larger than 1024 x 1024 pixels by drawing it to a bitmap-backed graphics context. In fact, you may need to resize an image in this manner (or break it into several smaller images) in order to draw it to one of your views.
  • 17:49 modifié #12
    dans 1237243289:

    Images and Memory Management

    In low-memory situations, image data may be purged from a UIImage object to free up memory on the system. This purging behavior affects only the image data stored internally by the UIImage object and not the object itself. When you attempt to draw an image whose data has been purged, the image object automatically reloads the data from its original file. This extra load step, however, may incur a small performance penalty.

    You should avoid creating UIImage objects that are greater than 1024 x 1024 in size. Besides the large amount of memory such an image would consume, you may run into problems when using the image as a texture in OpenGL ES or when drawing the image to a view or layer. This size restriction does not apply if you are performing code-based manipulations, such as resizing an image larger than 1024 x 1024 pixels by drawing it to a bitmap-backed graphics context. In fact, you may need to resize an image in this manner (or break it into several smaller images) in order to draw it to one of your views.



    Oui j'ai vu ça en cherchant le pourquoi du comment \o/
Connectez-vous ou Inscrivez-vous pour répondre.