0

我正在从磁盘加载图像,将它们转换为CVPixelBufferRef,做一些事情,然后转换回UIImage以保存回磁盘。我试图确保我绝对释放所有必要的东西,但我的应用程序的内存使用量总是会增加,直到它崩溃。

for (//iterate through images) {
    CVPixelBufferRef pixelBuffer = [self pixelBufferFromCGImage:image.CGImage];
    // do some stuff
    UIImage *newImage = [self imageFromPixelBuffer:pixelBuffer];
    CVPixelBufferRelease(pixelBuffer);
}

以下是我使用的两种方法:

- (CVPixelBufferRef)pixelBufferFromCGImage:(CGImageRef)image {

    CGSize frameSize = CGSizeMake(CGImageGetWidth(image), CGImageGetHeight(image));
    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey, [NSNumber numberWithBool:YES],kCVPixelBufferCGBitmapContextCompatibilityKey, nil];
    CVPixelBufferRef pxbuffer = NULL;

    CVReturn status = CVPixelBufferCreate(
                        kCFAllocatorDefault, frameSize.width, frameSize.height,
                        kCVPixelFormatType_32BGRA, (__bridge CFDictionaryRef)options,
                        &pxbuffer);
    NSParameterAssert(status == kCVReturnSuccess && pxbuffer != NULL);

    CVPixelBufferLockBaseAddress(pxbuffer, 0);
    void *pxdata = CVPixelBufferGetBaseAddress(pxbuffer);

    CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef context = CGBitmapContextCreate(
                                                 pxdata, frameSize.width, frameSize.height,
                                                 8, CVPixelBufferGetBytesPerRow(pxbuffer),
                                                 rgbColorSpace,
                                                 (CGBitmapInfo)kCGBitmapByteOrder32Little |
                                                 kCGImageAlphaPremultipliedFirst);

    CGContextDrawImage(context, CGRectMake(0, 0, CGImageGetWidth(image),
                                           CGImageGetHeight(image)), image);
    CGColorSpaceRelease(rgbColorSpace);
    CGContextRelease(context);

    CVPixelBufferUnlockBaseAddress(pxbuffer, 0);

    CGImageRelease(image);

    return pxbuffer;
}

- (UIImage *)imageFromPixelBuffer:(CVPixelBufferRef)pixelBuffer {
    CIImage *ciImage = [CIImage imageWithCVPixelBuffer:pixelBuffer];
    CIContext *context = [CIContext contextWithOptions:nil];
    CGImageRef myImage = [context createCGImage:ciImage fromRect:CGRectMake(0, 0, CVPixelBufferGetWidth(pixelBuffer), CVPixelBufferGetHeight(pixelBuffer))];
    UIImage *image = [UIImage imageWithCGImage:myImage];

    CGImageRelease(myImage);

    return image;
}

在实际应用中,我当然不只是保存完全相同的图像,而是从第一个图像创建新的像素缓冲区,然后保存所有这些图像。但是,即使对于这个简单的示例,也存在内存增加问题。

我一定错过了一些基本的东西,这让我发疯。

4

2 回答 2

0

在 Instruments 中构建并打开您的应用程序,选择 Leaks 仪器,然后运行您的应用程序。

它将向您显示任何内存泄漏,然后您可以追踪这些泄漏。

如果实际上没有泄漏,那么您遇到了一个更微妙的问题。运行 Allocations 工具,运行您的应用程序,并且(根据您所描述的)您将看到一个渐进的斜坡。选择斜坡的一个区域并检查所有新的分配——您将开始看到模式——出现类似分配的组。这些将为您提供有关未发布分配发生在代码中的确切位置的线索。

于 2017-01-12T23:58:26.563 回答
-1

删除CGImageRelease(image)线。您只是引用 usingimage.CGImage作为 pixelBufferFromCGImage:. 所以你不是在创造、保留它,所以释放它不是你的责任。

于 2017-01-12T19:21:31.493 回答