将UIImages转换为CVPixelBufferRef和Back会导致内存不断增加&最终崩溃

时间:2017-01-12 19:03:03

标签: ios objective-c memory uiimage cvpixelbuffer

我正在从磁盘加载图像,将它们转换为 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;
}

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

我必须错过一些基本的东西,这让我疯狂。

2 个答案:

答案 0 :(得分:0)

在乐器中构建并打开您的应用程序,选择Leaks乐器,然后锻炼您的应用程序。

它会显示您可以追踪的任何内存泄漏。

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

答案 1 :(得分:-1)

删除CGImageRelease(image)行。 您仅使用image.CGImage作为pixelBufferFromCGImage:的参数进行引用。 因此,您不会创建,保留它,因此发布它不是您的责任。