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

:

은 그런 방식으로이 배열을 통해 반복 if (pixels! = nil) 블록의 맨 아래. 제 2 블록의 변경을 포함하는 경우

- (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) 블록의 끝 부분에 free (pixels)를 추가하면 (기본적으로 return 문 앞에). 이 오류가 발생합니다. malloc : *** 개체에 대한 오류 0x108f43000 : 해제 된 포인터가 할당되지 않았습니다. *** 디버그를 위해 malloc_error_break에 중단 점을 설정하십시오. – user3131312

+0

"pixels ++"use "pixels"- numberOfPixels ] .r "나중에 조정하거나 원본 픽셀 값의 복사본을 저장하지 않고 자유롭게 만듭니다. –

0

당신은 받아 들일 수 @autorelease와 'enumerateAssetsUsingBlock'블록 :

@autorelease { 

    if (asset) { 

     ... 
    } 
} 

모든 autoreleasing 개체가 즉시 해제이 힘.

UPD : fullScreenImage 또는 fullResolutionImage 대신 [에셋 축소판]을 사용하십시오. 이러한 방법은 엄청난 양의 픽셀 데이터를 생성합니다.

UPD2 : [자산 축소판]도 도움이되지 않으면이 이미지 데이터를 공개 할 방법을 찾아야 만합니다. CGImageRelease를 직접 호출 할 수없는 한 조금 까다로울 수 있습니다. 단지이 배열에 자산 객체를 넣어 당신의 enumerateAssetsUsingBlock에서

NSMutabelArray* arr = [NSMutabelArray new]; 

을 : : 이런 식으로 뭔가를 시도

[arr addObject:asset]; 

그리고이 블록에서 아무 것도하지 않는다.

free(pixels); 

을에서 : 당신은 당신은 추가 할 필요가

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

에 의해 할당 된 메모리를 해제하지 않는

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). 따라서 솔루션은 해결하려는 대상에 따라 달라집니다. 라이브러리에있는 모든 빨간색 그림을 찾으면 [asset thumbnailImage]를 사용하면이 픽셀 단위 분석에 충분할 것입니다. – faviomob

+0

안녕하세요, 방금 시도했지만 이미지를 가져옵니다. 'ALAssetRepresentation'에 대한 @interface가 선택어 'thumbnailImage'를 선언하지 않습니다. – user3131312

관련 문제