在长过滤器链中何时何地使用 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 有啥区别?何时何地使用它们?

Twig 渲染与包含 - 何时何地使用其中一个?

NHibernate ISession Flush:何时何地使用它,为啥?

分裂何时何地发生?

SQL 中何时何地使用单引号? [复制]

何时/何地在 FastAPI 中使用正文/路径/查询/字段?