有没有一种方法可以从CGImage中读取数据而无需内部缓存?

时间:2018-11-09 11:35:18

标签: ios caching core-graphics core-image iosurface

我在CGContextDrawImage / CGDataProviderCopyData函数中使用内部缓存(对于15 mp映像大约90 MB)进行了斗争。
这是探查器中的堆栈跟踪:

enter image description here

在所有情况下,IOSurface被创建为“缓存”,并且在@autoreleasepool耗尽后不会被清除。
这为应用程序的生存留下了很少的机会。
缓存不取决于图像大小:我尝试渲染512x512以及4500x5124500x2500(全尺寸)图像块。

我使用@autoreleasepoolCFGetRetainCount对所有1对象返回CG,然后再清理它们。

操作数据的代码:

+ (void)render11:(CIImage*)ciImage fromRect:(CGRect)roi toBitmap:(unsigned char*)bitmap {
    @autoreleasepool
    {
        int w = CGRectGetWidth(roi), h = CGRectGetHeight(roi);

        CIContext* ciContext = [CIContext contextWithOptions:nil];
        CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

        CGContextRef cgContext = CGBitmapContextCreate(bitmap, w, h,
                                                   8, w*4, colorSpace,
                                                   kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);


        CGImageRef cgImage = [ciContext createCGImage:ciImage
                                         fromRect:roi
                                           format:kCIFormatRGBA8
                                       colorSpace:colorSpace
                                         deferred:YES];


        CGContextDrawImage(cgContext, CGRectMake(0, 0, w, h), cgImage);

        assert( CFGetRetainCount(cgImage) == 1 );

        CGColorSpaceRelease(colorSpace);
        CGContextRelease(cgContext);
        CGImageRelease(cgImage);
    }
}


我对IOSurface的了解:来自先前的私有框架IOSurface
CIContext具有功能render: ... toIOSurface:
我已经创建了IOSurfaceRef并将其传递给此函数,并且内部实现仍会创建其自己的表面,并且不会对其进行清理。

所以,您知道(或假设):
1.除了CGImage的数据缓冲区还有其他方法可以读取  CGContextDrawImage / CGDataProviderCopyData
2.有没有一种方法可以在渲染时禁用缓存?
3.为什么会发生缓存?
4.我可以使用一些较低级别的(非私有的)API来手动清理系统内存吗?

欢迎提出任何建议。

2 个答案:

答案 0 :(得分:3)

要回答第二个问题,

Is there a way to disable caching at render?

将环境变量CI_SURFACE_CACHE_CAPACITY设置为0或多或少会禁用CIContext表面缓存。此外,您可以通过将变量设置为给定的字节数来指定自定义(近似)缓存限制。例如,将CI_SURFACE_CACHE_CAPACITY设置为2147483648会指定2 GiB表面缓存限制。

请注意,似乎所有进程的CIContext实例共享一个表面缓存。每个CIContext似乎无法使用单独的缓存。

答案 1 :(得分:1)

如果只需要处理CIImage数据,则可以考虑使用CIImageProcessorKernel将数据放入CPU或GPU计算中,而无需提取它们。

我注意到

[ciContext      render:image toBitmap:bitmap rowBytes:w * 4 bounds:image.extent format:kCIFormatRGBA8 colorSpace:colorSpace];

没有这样的90M缓存。也许这就是您想要的。

enter image description here