访问ALAssetsLibrary时出现内存错误

时间:2014-02-26 18:04:16

标签: ios objective-c 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);
}];

此致 下进行。

2 个答案:

答案 0 :(得分: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#>
            }
        }

虽然主要泄漏没有释放像素缓冲区。

答案 1 :(得分:0)

您可以使用@autorelease:

包含'enumerateAssetsUsingBlock'块
@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
}