在长过滤器链中何时何地使用 prepareForImageCapture
Posted
技术标签:
【中文标题】在长过滤器链中何时何地使用 prepareForImageCapture【英文标题】:Where and when to use prepareForImageCapture in a long filter chain 【发布时间】:2014-01-09 19:59:10 【问题描述】:我有几个过滤器(全部堆叠)来处理图像,我使用滑块来修改这些过滤器的设置。我遇到了一些内存限制,正在考虑使用prepareForImageCapture
来提高内存和性能,但想知道在哪里/何时应用它?这仅适用于 ios 7。
-
从
UIImage
创建一个GPUImagePicture
创建GPUImageFilter
并将目标从GPUImagePicture
添加到GPUImageFilter
再创建X个GPUImageFilters
,通过addTarget:
链接它们
创建一个GPUImageView
并将最后一个GPUImageFilter
定位到它
处理GPUImagePicture
我应该在哪里打电话给prepareForImageCapture
?我应该在每个GPUImageFilter
上调用它吗?如果是,何时以及以什么顺序?
【问题讨论】:
【参考方案1】:在过滤器上使用时,-prepareForImageCapture
设置该过滤器的渲染目标纹理以通过纹理缓存访问。
这意味着当您在过滤器上调用它时,下次您使用 -imageFromCurrentlyProcessedOutput
或其中一种照片捕获方法时,您从该过滤器返回的 UIImage 将在其中包含一个内存映射表示过滤器的内部纹理。这将当时所需的内存减少了一半,因为内存中只存在一个图像字节的副本,而不是 UIImage 和滤镜的背景纹理的单独副本。
但是,由于内存映射现在在 UIImage 和 GPUImageFilter 之间共享,因此过滤器会锁定在它渲染的最后一个图像,直到提取的 UIImage 被解除分配。如果为新图像重新渲染过滤器,结果将覆盖 UIImage 中的字节。这就是为什么并非所有过滤器都默认启用此功能的原因,因为人们可能会对此行为感到困惑。
对于您在屏幕上显示的示例,您不需要为任何这些过滤器设置此项。它只影响您从中提取静止图像的过滤器。更好的方法是在链中的第一个过滤器上使用-forceProcessingAtSize:
,并使用目标视图的尺寸(以像素为单位)作为强制大小。渲染在最终视图中看不到的额外像素是没有意义的,这将节省在内部表示此图像所需的内存。但是,在将最终处理后的图像捕获到磁盘之前,将大小强制为 0,0,以将这些过滤器恢复为完整大小。
我正在对过滤器链接进行长期改进,包括缓存用于过滤器的帧缓冲区,以便它们可以重复使用。这将使您可以创建任意长的过滤器链,而不会产生额外的内存损失。不过,我不能保证我什么时候能完成这项工作。
【讨论】:
很惊讶如果我直接显示到 GUIImageView,它不应该改进任何东西。一时兴起,每当我更新链中的任何过滤器时,我都会在 every 过滤器上调用prepareForImageCapture
(因为在同一个过滤器上多次调用它并没有什么坏处)并且它基本上 改善了我的记忆问题,没有明显的缺点。我会尝试用forceProcessingAtSize
代替prepareForImageCapture
,看看会发生什么。
@Shizam - GPUImageView 仅从上一次传递中获取纹理并将其重新渲染到屏幕上。将该过滤器的纹理附加到 iOS 纹理缓存不会减少内存中纹理的大小,只会使 GPU 纹理和 CPU 端内存之间的直接映射成为可能。完全没有理由通过在链中切换过滤器以使用 iOS 纹理缓存来查看内存性能的任何差异。也许该内存被隐藏在正常的内存压力计算中。在内存监视器中查看其他进程中的奇数内存增益。以上是关于在长过滤器链中何时何地使用 prepareForImageCapture的主要内容,如果未能解决你的问题,请参考以下文章
BaseHTTPServer 和 SimpleHTTPServer 有啥区别?何时何地使用它们?