2012-05-10 19 views
0
,我創建

我的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,以查看是否可以解決我的問題(這是前一段時間),但是從我在儀器中分析後得到的結果中,我必須做一些愚蠢的錯誤內存泄漏一樣糟糕,但我只是不明白我做錯了什麼。

如果有人能指出任何我可能會做錯的事情,那就太棒了!

感謝

利亞姆

(讓我知道如果你需要更多的信息)

+3

4096 * 2992 * 4(RGBA)產生約40MB的圖像。處理,當然,需要一個輸入和輸出緩衝區......這是一大堆內存! – bbum

+0

啊,我看到我可能不得不尋找其他方式來做到這一點。 – liamnichols

+0

方法實現中有什麼resizedImage:scale:?另外,請在for循環中創建autorelease池。 –

回答

0

我用 「的UIImage +調整大小」。在@autoreleasepool {}中,它可以在循環中正常工作。

https://github.com/AliSoftware/UIImage-Resize

-(void)compress:(NSString *)fullPathToFile { 
@autoreleasepool { 
    UIImage *fullImage = [[UIImage alloc] initWithContentsOfFile:fullPathToFile]; 
    UIImage *compressedImage = [fullImage resizedImageByHeight:1024]; 
    NSData *compressedData = UIImageJPEGRepresentation(compressedImage, 75.0); 
    [compressedData writeToFile:fullPathToFile atomically:NO]; 
} 

}