J'ai un problème déconcertant en essayant de remplir un NSMutableArray avec UIImages.

CGBitmapInfo bitmapInfo = kCGBitmapByteOrderMask;
CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

while(...)     // <--- Iterates through data sets
{

          CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, data, numBytes, NULL);
          CGImageRef cImage = CGImageCreate(iw, ih, 8, 32, 4 * iw, colorSpace, bitmapInfo, provider, NULL, NO, renderingIntent);
          UIImage *finalImage = [UIImage imageWithCGImage:cImage];


          [images addObject:finalImage]; // <--- Declared and instantiated earlier

          [delegate sendImage:finalImage];

          CGImageRelease(cImage);
          CGDataProviderRelease(provider);
}

CGColorSpaceRelease(colorSpace);

[delegate operationCompletedWithImages:images];

C'est comme ça que j'ai le code qui s'exécute. J'ai donc essentiellement une fonction exécutée dans l'instruction while qui renvoie le prochain ensemble de données bitmap, je crée ensuite une UIImage et la stocke dans le tableau mutable.

J'ai testé cela en écrivant chaque fichier sur le disque, puis en y accédant, ce qui donne le bon ensemble d'images. Le problème est que lors de l'utilisation du tableau pour conserver les données en mémoire, en accédant à n'importe quel objet image du tableau, j'obtiens exactement la même image encore et encore. L'image est aussi toujours la dernière image de l'ensemble.

J'ai essayé de tester le contenu en définissant le tableau comme un tableau d'animation UIImageView et en utilisant un NSTimer pour faire défiler le contenu. De toute façon, c'est juste la même image (la dernière image tirée) encore et encore.

J'ai cette opération en cours d'exécution dans un objet NSOperation sous-classé afin qu'elle ne bloque pas l'interface. Un autre aspect intéressant ici est que lorsque le tableau d'images envoyé avec operationCompletedWithImages me donnait le tableau d'images en double, j'ai essayé d'utiliser le message sendImage et de stocker les images dans un tableau différent à l'intérieur l'objet délégué (en pensant que c'était peut-être un problème de thread). Cela m'a donné les mêmes résultats.

Cela fait plus d'une semaine que je suis bloqué dessus sans aucun progrès. Je n'ai jamais rien vu de tel et je ne trouve personne d'autre qui a eu un problème similaire. Je serais heureux de fournir des informations supplémentaires si quelqu'un pense que cela aiderait à résoudre ce problème.

Si quelqu'un pouvait apporter de l'aide, je l'apprécierais grandement.

0
Matthew McGoogan 24 janv. 2010 à 04:19

3 réponses

Meilleure réponse

Compris le problème. S'est avéré être un problème avec le pointeur de sauvegarde data.

Là où auparavant j'accédais aux données à chaque fois en pensant qu'elles seraient itérées et écrasées avec de nouveaux contenus, et que les nouveaux contenus seraient branchés sur mon CGDataProviderRef. Ce n'était pas le cas, j'ai fini par fournir un pointeur vers les mêmes données de sauvegarde pour le fournisseur. La solution consistait à copier les données dans un objet NSData et à utiliser cette copie pour le DataProvider.

Donc au lieu de:

CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, data, numBytes, NULL);

Ce serait:

NSData *pxData = [[NSData alloc] initWithBytes:pFrameRGB->data length:numBytes];
CGDataProviderRef provider = CGDataProviderCreateWithCFData((CFDataRef)pxData);
0
Matthew McGoogan 25 févr. 2010 à 19:12

Je ne sais pas si c'est le problème, mais vous devriez probablement informer votre délégué des modifications sur le thread principal, et non sur le thread sur lequel l'opération NSO s'exécute.

[delegate performSelectorOnMainThread:@selector(sendImage:) withObject:finalImage waitUntilDone:YES];

Et de même pour le dernier message. Si le délégué modifie quoi que ce soit en rapport avec UIKit, il doit être invoqué sur le thread principal !

0
PfhorSlayer 24 janv. 2010 à 04:25
Merci! c'est certainement un pas dans la bonne direction. Lorsque j'exécute le sélecteur sendImage sur le fil principal, j'obtiens définitivement les images appropriées. Maintenant, j'ajoute ces images à un tableau dans l'objet délégué (fil principal). Le problème est qu'une fois qu'ils sont tous ajoutés et que j'essaie de les revoir, ils sont tous les mêmes. Très étrange. Je reçois donc les images appropriées du fil d'arrière-plan, mais le tableau ne fait que stocker des copies de la dernière image reçue ...
 – 
Matthew McGoogan
24 janv. 2010 à 05:48
Qu'entends-tu par "tous pareils" ? Toutes les images ont-elles le même contenu ou sont-elles exactement la même instance ? Vérifiez les valeurs de pointeur stockées dans votre tableau !
 – 
PfhorSlayer
25 janv. 2010 à 02:14
Les rendus sont les mêmes. La chose intéressante est que bien que les pointeurs UIImage & CGImageRef soient uniques dans le tableau, l'adresse NSObject -> ISA pour chaque UIImage dans le tableau est la même. Je ne sais pas ce que cela signifie, mais c'est le seul lien que j'ai pu trouver jusqu'à présent. J'ai également essayé de déclarer 10 variables d'instance UIImage et d'y stocker un ensemble de dix images. Cela a fonctionné ! Le problème semble donc se produire uniquement lors du stockage des images dans un tableau (j'ai essayé un tableau NSArray, CFArray et C - UIImage *images[...]).
 – 
Matthew McGoogan
25 janv. 2010 à 04:37

On pourrait supposer que le NSMutableArray gérerait la gestion de la mémoire de l'objet qui lui est ajouté, mais peut-être parce que vous avez affaire aux assistants Quartz / wrappers Core de niveau C, cela peut ne pas être le cas.

Dans d'autres méthodes de manipulation d'images que j'ai expérimentées, elles sont généralement encapsulées dans un pool de libération automatique si elles sont impliquées dans des threads.

Avez-vous essayé d'expérimenter avec release/autorelease sur l'image finale ?

0
David Sowsy 24 janv. 2010 à 05:58
J'ai joué avec la modification du nombre de retenues en vain. J'ai pensé que c'était de toute façon un tir dans le noir car je ne pouvais pas comprendre pourquoi cela provoquerait les objets en double dans le tableau. Qu'est-ce qui me fait vraiment tourner la tête avec cela - dans l'objet délégué (sur le fil principal), j'ai essayé de tirer un CGImageRef de chaque UIImage car ils ont été envoyés via sendImage et d'attribuer une nouvelle UIImage avec le CGImageRef pour obtenir une nouvelle copie avant d'ajouter à le tableau. J'obtiens TOUJOURS un tableau de la même image encore et encore (toujours la dernière image ajoutée).
 – 
Matthew McGoogan
24 janv. 2010 à 11:53