我的iPad应用程序必须能够创造就是前面我的应用程序生成的图像4096x2992瓷砖..大型图像处理(ARC)主内存泄漏
4096x2992的图像不是很复杂(我正在测试什么),当以png格式写入文件时大约有600kb ...
在模拟器上,这段代码似乎工作正常,但是当我在更严格的内存条件下运行应用程序时iPad)的过程中,因为它耗尽内存...
我一直在应用程序中使用相同的代码以前什么工作正常(只有C然而,对于3072x2244的图像)...
要么我必须做一些愚蠢的错误或我@ autoreleasepool的reating砖不工作,因为他们应该(我想我提到使用ARC),即时通讯......当仪器运行我可以看到使用的内存爬到了〜500mb,然后崩溃!
我分析的代码,也没有发现有关我的应用程序,所以我真的很困惑,为什么这是对我崩溃的这部分单个内存泄漏......
只是一点点历史上我的函数如何被调用,所以你知道发生了什么......该应用程序使用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)产生约40MB的图像。处理,当然,需要一个输入和输出缓冲区......这是一大堆内存! – bbum
啊,我看到我可能不得不寻找其他方式来做到这一点。 – liamnichols
方法实现中有什么resizedImage:scale:?另外,请在for循环中创建autorelease池。 –