2014-02-26 111 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

相關問題