有没有办法在没有内部缓存的情况下从 CGImage 读取数据?
Is there a way to read data from CGImage without internal caching?
我正在与 CGContextDrawImage
/CGDataProviderCopyData
函数中的内部缓存(15 mp 图像大约 90 MB)作斗争。
这是探查器中的堆栈跟踪:
在所有情况下,IOSurface
都创建为 "cache",并且在 @autoreleasepool
耗尽后不会被清理。
这给应用程序留下了很少的生存机会。
缓存不依赖于图像大小:我尝试渲染 512x512
,以及 4500x512
和 4500x2500
(全尺寸)图像块。
我对所有 CG
对象使用 @autoreleasepool
、CFGetRetainCount
returns 1
,然后再清理它们。
操作数据的代码:
+ (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 来手动清理系统内存吗?
欢迎提出任何建议。
如果只是需要对CIImage数据进行操作,可以考虑使用CIImageProcessorKernel将数据放入CPU或者不提取数据进行GPU计算
我注意到
[ci上下文
render:image toBitmap:bitmap rowBytes: w*4 bounds:image.extent format:kCIFormatRGBA8 colorSpace:colorSpace];
没有这个90M的缓存。也许这就是你想要的。
回答你的第二个问题,
Is there a way to disable caching at render?
将环境变量 CI_SURFACE_CACHE_CAPACITY
设置为 0 将或多或少禁用 CIContext
表面缓存。此外,您可以通过将该变量设置为以字节为单位的给定值来指定自定义(近似)缓存限制。例如,将 CI_SURFACE_CACHE_CAPACITY
设置为 2147483648 指定 2 GiB 表面缓存限制。
请注意,一个进程的所有 CIContext
实例似乎共享一个表面缓存。似乎不可能为每个 CIContext
.
使用单独的缓存
我正在与 CGContextDrawImage
/CGDataProviderCopyData
函数中的内部缓存(15 mp 图像大约 90 MB)作斗争。
这是探查器中的堆栈跟踪:
在所有情况下,IOSurface
都创建为 "cache",并且在 @autoreleasepool
耗尽后不会被清理。
这给应用程序留下了很少的生存机会。
缓存不依赖于图像大小:我尝试渲染 512x512
,以及 4500x512
和 4500x2500
(全尺寸)图像块。
我对所有 CG
对象使用 @autoreleasepool
、CFGetRetainCount
returns 1
,然后再清理它们。
操作数据的代码:
+ (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 来手动清理系统内存吗?
欢迎提出任何建议。
如果只是需要对CIImage数据进行操作,可以考虑使用CIImageProcessorKernel将数据放入CPU或者不提取数据进行GPU计算
我注意到
[ci上下文 render:image toBitmap:bitmap rowBytes: w*4 bounds:image.extent format:kCIFormatRGBA8 colorSpace:colorSpace];
没有这个90M的缓存。也许这就是你想要的。
回答你的第二个问题,
Is there a way to disable caching at render?
将环境变量 CI_SURFACE_CACHE_CAPACITY
设置为 0 将或多或少禁用 CIContext
表面缓存。此外,您可以通过将该变量设置为以字节为单位的给定值来指定自定义(近似)缓存限制。例如,将 CI_SURFACE_CACHE_CAPACITY
设置为 2147483648 指定 2 GiB 表面缓存限制。
请注意,一个进程的所有 CIContext
实例似乎共享一个表面缓存。似乎不可能为每个 CIContext
.