Мой IPad приложение, которое я создаю должен быть в состоянии создать плитки для более 4096x2992 изображение, которое генерируется в начале моего приложения ..Large Image Processing (ARC) Основные утечки памяти
4096x2992 изображение не очень сложный (что я тестирую), и когда он записывается в файл в формате png, составляет приблизительно 600kb ...
В симуляторе этот код работает нормально, однако, когда я запускаю приложение в более жестких условиях памяти (на моем iPad), процесс завершается, потому что у него закончилась память ...
Я уже использовал тот же код в приложении, который работал нормально (был только c повторные плитки для изображений 3072x2244, однако) ...
Либо я должен делать что-то глупое, или мой @ autoreleasepool не работает так, как должен (я думаю, что я упомянул, что im использует ARC) ... При работе в инструментах Я могу просто увидеть, что используемая память поднимается вверх до ~ 500 мб, где она падает!
Я проанализировал код и он не нашел утечку одного памяти, связанные с этой частью моего приложения, так что я действительно путают о том, почему это происходит сбой на меня ...
Просто немного историю о том, как моя функция вызывается, чтобы вы знали, что происходит ... Приложение использует CoreGraphics для рендеринга UIView (4096x2992) с некоторым UIImageView внутри него, затем отправляет эту ссылку UIImage в мою функцию buildFromImage:
(ниже), где начинается резка/изменение размера изображения для создания файла ...
Вот код buildFromImage:
... проблемы с памятью создаются из основного цикла под NSLog(@"LOG ------------> Begin tile loop ");
...
-(void)buildFromImage:(UIImage *)__image {
NSLog(@"LOG ------------> Begin Build ");
//if the __image is over 4096 width of 2992 height then we must resize it! (stop crashes ect)
if (__image.size.width > __image.size.height) {
if (__image.size.width > 4096) {
__image = [self resizeImage:__image toSize:CGSizeMake(4096, (__image.size.height * 4096/__image.size.width))];
}
} else {
if (__image.size.height > 2992) {
__image = [self resizeImage:__image toSize:CGSizeMake((__image.size.width * 2992/__image.size.height), 2992)];
}
}
//create preview image (if landscape, no more than 748 high... if portrait, no more than 1004 high) must keep scale
NSString *temp_archive_store = [[NSString alloc] initWithFormat:@"%@/%i-temp_imgdat.zip",NSTemporaryDirectory(),arc4random()];
NSString *temp_tile_store = [[NSString alloc] initWithFormat:@"%@/%i-temp_tilestore/",NSTemporaryDirectory(),arc4random()];
//create the temp dir for the tile store
[[NSFileManager defaultManager] createDirectoryAtPath:temp_tile_store withIntermediateDirectories:YES attributes:nil error:nil];
//create each tile and add it to the compressor once its made
//size of tile
CGSize tile_size = CGSizeMake(256, 256);
//the scales that we will be generating the tiles too
NSMutableArray *scales = [[NSMutableArray alloc] initWithObjects:[NSNumber numberWithInt:1000],[NSNumber numberWithInt:500],[NSNumber numberWithInt:250],[NSNumber numberWithInt:125], nil]; //scales to loop round over
NSLog(@"LOG ------------> Begin tile loop ");
@autoreleasepool {
//loop through the scales
for (NSNumber *scale in scales) {
//scale the image
UIImage *imageForScale = [self resizedImage:__image scale:[scale intValue]];
//calculate number of rows...
float rows = ceil(imageForScale.size.height/tile_size.height);
//calulate number of collumns
float cols = ceil(imageForScale.size.width/tile_size.width);
//loop through rows and cols
for (int row = 0; row < rows; row++) {
for (int col = 0; col < cols; col++) {
NSLog(@"LOG ------> Creating Tile (%i,%i,%i)",col,row,[scale intValue]);
//build name for tile...
NSString *tile_name = [NSString stringWithFormat:@"%@_%i_%i_%i.png",@"image",[scale intValue],col,row];
@autoreleasepool {
//build tile for this coordinate
UIImage *tile = [self tileForRow:row column:col size:tile_size image:imageForScale];
//convert image to png data
NSData *tile_data = UIImagePNGRepresentation(tile);
[tile_data writeToFile:[NSString stringWithFormat:@"%@%@",temp_tile_store,tile_name] atomically:YES];
}
}
}
}
}
}
Вот мои изменения размера/обрезки функции тоже, поскольку они также могут быть причиной проблемы ..
-(UIImage *)resizeImage:(UIImage *)inImage toSize:(CGSize)scale {
@autoreleasepool {
CGImageRef inImageRef = [inImage CGImage];
CGColorSpaceRef clrRf = CGColorSpaceCreateDeviceRGB();
CGContextRef ctx = CGBitmapContextCreate(NULL, ceil(scale.width), ceil(scale.height), CGImageGetBitsPerComponent(inImageRef), CGImageGetBitsPerPixel(inImageRef)*ceil(scale.width), clrRf, kCGImageAlphaPremultipliedFirst);
CGColorSpaceRelease(clrRf);
CGContextDrawImage(ctx, CGRectMake(0, 0, scale.width, scale.height), inImageRef);
CGImageRef img = CGBitmapContextCreateImage(ctx);
UIImage *image = [[UIImage alloc] initWithCGImage:img scale:1 orientation:UIImageOrientationUp];
CGImageRelease(img);
CGContextRelease(ctx);
return image;
}
}
- (UIImage *)tileForRow: (int)row column: (int)col size: (CGSize)tileSize image: (UIImage*)inImage
{
@autoreleasepool {
//get the selected tile
CGRect subRect = CGRectMake(col*tileSize.width, row * tileSize.height, tileSize.width, tileSize.height);
CGImageRef inImageRef = [inImage CGImage];
CGImageRef tiledImage = CGImageCreateWithImageInRect(inImageRef, subRect);
UIImage *tileImage = [[UIImage alloc] initWithCGImage:tiledImage scale:1 orientation:UIImageOrientationUp];
CGImageRelease(tiledImage);
return tileImage;
}
}
Теперь я никогда не использую, чтобы быть хорошим, что с управлением памятью, так что я потратил время, чтобы прочитать его, а также преобразовал мой проект в ARC, чтобы узнать, может ли это решить мои проблемы (это было давно), но из результатов, которые я получаю после профилирования его в инструментах, я должен делать что-то НЕПОСРЕДСТВЕННО неправильно для память течет так же плохо, как и она, но я просто не вижу, что я делаю неправильно.
Если кто-нибудь может указать на что-нибудь, что я могу делать неправильно, было бы здорово!
Благодаря
Лиам
(дайте мне знать, если вам нужно больше информации)
4096 * 2992 * 4 (RGBA) дает изображение вокруг 40Мб. Обработка, конечно, требует входного и выходного буфера ... это тонна памяти! – bbum
Ahh Я вижу, что мне, возможно, придется изучить другие способы сделать это. – liamnichols
Что находится в реализации метода resizedImage: scale :? Кроме того, создайте пул автозапуска внутри цикла for. –