2012-05-10 21 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]; 
} 

}