J'essaie de merge un certain nombre de petites images en une plus grande. L'application se bloque car elle manque de memory, mais je n'arrive pas à comprendre comment libérer la memory une fois qu'elle est utilisée, elle continue donc à se développer jusqu'à ce que l'application tombe en panne.
Les routines addImageToImage et resizeImage semblent être à l'origine du crash car je ne peux pas libérer de memory une fois que ce n'est plus nécessaire. J'utilise le comptage automatique des references dans ce projet. J'ai essayé de mettre l'image à zéro mais cela n'arrête pas le crash.
testImages fait partie d'une class appelée depuis le ViewController principal, tandis que addImageToImage et resizeImage se trouvent dans une autre class appelée ImageUtils.
Quelqu'un peut-il regarder ce code et m'expliquer comment libérer correctement la memory allouée par ces deux routines. Je ne peux pas appeler la libération sur les images puisque le projet utilise ARC et les mettre à zéro n'a aucun effet.
+ (void)testImages { const int IMAGE_WIDTH = 394; const int IMAGE_HEIGHT = 150; const int PAGE_WIDTH = 1275; const int PAGE_HEIGHT = 1650; const int COLUMN_WIDTH = 30; const int ROW_OFFSET = 75; CGSize imageSize = CGSizeMake(PAGE_WIDTH, PAGE_HEIGHT); UIGraphicsBeginImageContextWithOptions(imageSize, YES, 0); CGContextRef context = UIGraphicsGetCurrentContext(); CGContextFillRect(context, CGRectMake(0, 0, imageSize.width, imageSize.height)); UIImage *psheet = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); CGSize collageSize = CGSizeMake(IMAGE_WIDTH, IMAGE_HEIGHT); UIGraphicsBeginImageContextWithOptions(collageSize, YES, 0); CGContextRef pcontext = UIGraphicsGetCurrentContext(); CGContextFillRect(pcontext, CGRectMake(0, 0, collageSize.width, collageSize.height)); UIImage *collage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); float row = 1; float column = 1; int index = 1; int group = 1; for (int i = 0; i < 64; i++) { NSLog(@"processing group %i - file %i ", group, index++); psheet = [ImageUtils addImageToImage:psheet withImage2:collage andRect:CGRectMake((IMAGE_WIDTH*(column-1)) + (COLUMN_WIDTH * column), (IMAGE_HEIGHT * (row-1)) + ROW_OFFSET, IMAGE_WIDTH, IMAGE_HEIGHT) withImageWidth:PAGE_WIDTH withImageHeight:PAGE_HEIGHT]; column++; if (column > 3) { column = 1; row++; } if (index == 15) { group++; index = 1; row = 1; column = 1; UIImage *editedImage = [ImageUtils resizeImage:psheet withWidth:PAGE_WIDTH * 2 withHeight:PAGE_HEIGHT * 2]; editedImage = nil; } } }
Méthodes ImageUtils
+(UIImage *) addImageToImage:(UIImage *)sheet withImage2:(UIImage *)label andRect:(CGRect)cropRect withImageWidth:(int) width withImageHeight:(int) height { CGSize size = CGSizeMake(width,height); UIGraphicsBeginImageContext(size); CGPoint pointImg1 = CGPointMake(0,0); [sheet drawAtPoint:pointImg1]; CGPoint pointImg2 = cropRect.origin; [label drawAtPoint: pointImg2]; UIImage* result = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return result; } + (UIImage*)resizeImage:(UIImage*)image withWidth:(CGFloat)width withHeight:(CGFloat)height { CGSize newSize = CGSizeMake(width, height); CGFloat widthRatio = newSize.width/image.size.width; CGFloat heightRatio = newSize.height/image.size.height; if(widthRatio > heightRatio) { newSize=CGSizeMake(image.size.width*heightRatio,image.size.height*heightRatio); } else { newSize=CGSizeMake(image.size.width*widthRatio,image.size.height*widthRatio); } UIGraphicsBeginImageContextWithOptions(newSize, NO, 0.0); [image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)]; UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return newImage; }
Peut-être que vos images ne sont pas désaffectées mais déplacées vers le pool autorelease .
De nombreux programmes créent des objects temporaires qui sont auto-libérés. Ces objects s'ajoutent à l'empreinte memory du programme jusqu'à la fin du bloc. Dans de nombreux cas, l'accumulation d'objects temporaires jusqu'à la fin de l'itération de la boucle d'events actuelle n'entraîne pas de surcharge excessive; Cependant, dans certaines situations, vous pouvez créer un grand nombre d'objects temporaires qui ajoutent beaucoup à l'empreinte memory et que vous souhaitez éliminer plus rapidement. Dans ces derniers cas, vous pouvez créer votre propre bloc de pool autorelease. A la fin du bloc, les objects temporaires sont libérés, ce qui entraîne généralement leur désallocation, réduisant ainsi l'empreinte memory du programme.
Essayez d'insert du code dans la boucle avec @autoreleasepool {}
:
for (int i = 0; i < 64; i++) { @autoreleasepool { NSLog(@"processing group %i - file %i ", group, index++); psheet = [ImageUtils addImageToImage:psheet withImage2:collage andRect:CGRectMake((IMAGE_WIDTH*(column-1)) + (COLUMN_WIDTH * column), (IMAGE_HEIGHT * (row-1)) + ROW_OFFSET, IMAGE_WIDTH, IMAGE_HEIGHT) withImageWidth:PAGE_WIDTH withImageHeight:PAGE_HEIGHT]; column++; if (column > 3) { column = 1; row++; } if (index == 15) { group++; index = 1; row = 1; column = 1; UIImage *editedImage = [ImageUtils resizeImage:psheet withWidth:PAGE_WIDTH * 2 withHeight:PAGE_HEIGHT * 2]; editedImage = nil; } } }