我的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池。 –