2014-02-26 147 views
0

我收到内存错误。由于内存使用量呈指数增长,因此出现内存错误。很明显,我没有发布什么,有什么想法可能是什么?访问ALAssetsLibrary时出现内存错误

这是我的方法来确定在UI图像中呈现的红色像素。它返回计数。

- (NSUInteger)getRedPixelCount:(UIImage*)image 
{ 
NSUInteger numberOfRedPixels = 0; 

struct pixel* pixels = (struct pixel*) calloc(1, image.size.width * image.size.height * sizeof(struct pixel)); 
if (pixels != nil) 
{ 
    CGContextRef context = CGBitmapContextCreate((void *) pixels, 
               image.size.width, 
               image.size.height, 
               8, 
               image.size.width * 4, 
               CGImageGetColorSpace(image.CGImage), 
               (CGBitmapInfo)kCGImageAlphaPremultipliedLast); 

    if (context != NULL) 
    { 
     CGContextDrawImage(context, CGRectMake(0.0f, 0.0f, image.size.width, image.size.height), image.CGImage); 
     NSUInteger numberOfPixels = image.size.width * image.size.height; 

     while (numberOfPixels > 0) { 
      if (pixels->r == 255) { 
       numberOfRedPixels++; 

      } 
      pixels++; 
      numberOfPixels--; 
     } 
     CGContextRelease(context); 
    } 
} 
return numberOfRedPixels; 

}

这是一个通过照片库图像进行迭代并且确定每个他们的红色的像素的代码。

[self.library enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop) { 
    if (group) { 
     [group setAssetsFilter:[ALAssetsFilter allPhotos]]; 
     [group enumerateAssetsUsingBlock:^(ALAsset *asset, NSUInteger index, BOOL *stop){ 

      if (asset) { 
       ALAssetRepresentation *rep = [asset defaultRepresentation]; 
       CGImageRef iref = [rep fullResolutionImage]; 

       if (iref){ 

         UIImage *myImage = [UIImage imageWithCGImage:iref scale:[rep scale] orientation:(UIImageOrientation)[rep orientation]]; 

         NSLog(@"%i", [self getRedPixelCount:myImage]); 
       } 
      } 
     }]; 
    } 
} failureBlock:^(NSError *error) { 
    NSLog(@"error enumerating AssetLibrary groups %@\n", error); 
}]; 

问候, C.

+1

我认为在一个循环中调用'fullResolutionImage'并不是一个好主意。这是在代码中创建内存问题的非常好的候选人。无论如何,你可以在你的仪器中分析你的代码,并确切地看到那里发生了什么。 – faviomob

回答

1

你不释放你需要添加由

struct pixel* pixels = (struct pixel*) calloc(1, image.size.width * image.size.height * sizeof(struct pixel)); 

分配的内存:

free(pixels); 

然后通过这个数组的方式迭代if(pixels!= nil)块的底部。

作出的第一个块的样子:

- (NSUInteger)getRedPixelCount:(UIImage*)image 
{ 
    NSUInteger numberOfRedPixels = 0; 

    struct pixel* pixels = (struct pixel*) calloc(1, image.size.width * image.size.height * sizeof(struct pixel)); 
    if (pixels != nil) 
    { 
     CGContextRef context = CGBitmapContextCreate((void *) pixels, 
                image.size.width, 
                image.size.height, 
                8, 
                image.size.width * 4, 
                CGImageGetColorSpace(image.CGImage), 
                (CGBitmapInfo)kCGImageAlphaPremultipliedLast); 

     if (context != NULL) 
     { 
      CGContextDrawImage(context, CGRectMake(0.0f, 0.0f, image.size.width, image.size.height), image.CGImage); 
      NSUInteger numberOfPixels = image.size.width * image.size.height; 
      struct pixels* ptr = pixels; 

      while (numberOfPixels > 0) { 
       if (ptr->r == 255) { 
        numberOfRedPixels++; 

       } 
       ptr++; 
       numberOfPixels--; 
      } 
      CGContextRelease(context); 
     } 
     free(pixels); 
    } 
    return numberOfRedPixels; 
} 

它也将帮助,如果第二块的变化包括:

 @autoreleasepool { 
      ALAssetRepresentation *rep = [asset defaultRepresentation]; 
      CGImageRef iref = [rep fullResolutionImage]; 

      if (iref){ 

       UIImage *myImage = [UIImage imageWithCGImage:iref scale:[rep scale] orientation:(UIImageOrientation)[rep orientation]]; 

       NSLog(@"%i", [self getRedPixelCount:myImage]); 
       <#statements#> 
      } 
     } 

虽然各大泄漏未释放像素缓冲区。

+0

是的,显然这是这里的主要问题=) – faviomob

+0

当我在if(pixels!= nil)块的末尾添加空闲(像素)(基本上在return语句之前)。我得到这个错误。 malloc:***错误的对象0x108f43000:被释放的指针未被分配 ***在malloc_error_break中设置一个断点来调试 – user3131312

+0

由于“像素++”使用“像素[ - numberOfPixels ] .r“,稍后不要调整它们,也不要将原始像素值的副本存储起来并释放它。 –

0

你可以拥抱 'enumerateAssetsUsingBlock' 与@autorelease块:

@autorelease { 

    if (asset) { 

     ... 
    } 
} 

这股力量都自动释放的对象立即释放。

UPD: 使用[资源缩略图]而不是fullScreenImage或fullResolutionImage。这些方法会生成大量的像素数据。

UPD2: 如果即使[资源缩略图]没有帮助,你必须找到一种方法来释放这个图像数据,只要你不能直接释放它,调用CGImageRelease就可能有点棘手。尝试是这样的:

NSMutabelArray* arr = [NSMutabelArray new]; 

在你enumerateAssetsUsingBlock只是把资产对象本阵:

[arr addObject:asset]; 

而别的什么也不做这个块。

while (arr.count > 0) 
{ 
    ALAsset* asset = [arr lastObject]; 
    // do smth with asset 
    [arr removeLastObject]; // this will remove object from memory immediatelly 
} 
+0

仍然无法正常工作,内存使用量继续增加。 – user3131312

+0

我假设fullResolutionImage生成图像数据并将其存储直到ALAsset对象处于活动状态。即使对于一张图像,这些数据也可能非常大(即10mb)。所以,解决方案取决于你想要解决的问题。如果只需在库中查找所有红色图片,那么使用[资源缩略图图像]对于此像素点分析就足够了。 – faviomob

+0

嗨,我刚刚尝试过,但确实需要thumbnailImage, 'ALAssetRepresentation'没有明显的@interface声明选择器'thumbnailImage' – user3131312

相关问题