【问题标题】:UIImage + Effects for iOS 7 Blur Effect Slowing App Down - 450MB?iOS 7 模糊效果减慢应用程序的 UIImage + 效果 - 450MB?
【发布时间】:2014-07-11 11:10:27
【问题描述】:

这就是我使用UIImage+Effects 模糊名为artworkImage 的UIImage 以获得iOS 7 模糊效果的方法:

-(void)viewDidAppear:(BOOL)animated{

    MPMediaItem *currentItem = [self.musicPlayer nowPlayingItem];

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0ul), ^(void) {
        @autoreleasepool {

            MPMediaItemArtwork *artwork = [currentItem valueForProperty: MPMediaItemPropertyArtwork];
            UIImage *artworkImage = [artwork imageWithSize: CGSizeMake (618, 618)];

            artworkImage = [artworkImage applyDarkEffect];

            dispatch_async(dispatch_get_main_queue(), ^{

                [backgroundImageView setImage:artworkImage];

                UIGraphicsEndImageContext();
            });
        }
    });
}

我的应用程序真的很慢,所以我研究了如何找出原因,然后我遇到了 Instruments,它向我展示了这个:

所以我研究了一些如何解决这个问题,并遇到了dispatch_async,所以我把实际的模糊放在了背景中,并在前面更新了 UI。它仍然非常慢。

这个名为artworkImageUIImage 会在音乐播放器每次跳过歌曲时更新。我将来自 Apple 示例项目(称为 UIImage+Effects.h)的 iOS 7 模糊效果应用于此 UIImage。

请告诉我该怎么做 - 我搜索了无数线程,都说使用 autorelease,我当然不能与 ARC 一起使用。

任何帮助将不胜感激,谢谢。

【问题讨论】:

  • 使用 dispatch_async 在单独的线程中运行某些东西不会减少它使用的 RAM 量。
  • 改图后内存占用是否保持在450MB?知道这可能有助于指出是什么原因造成的。 CPU使用率如何?我还假设您已经尝试过没有任何 dispatch_async 的东西,但如果您没有尝试过,我会尝试。
  • 这句话毫无意义:“它仍然非常慢(450MB)”。 “慢”是一种速度。 “450MB”是一个大小。
  • 使用“DISPATCH_QUEUE_PRIORITY_DEFAULT”肯定会减慢速度,因为您说的是“随时在后台执行此操作。”
  • @matt 我可能是错的,但我认为在这种情况下应该不会有什么不同,除非有一些其他线程占用了大量的 CPU 周期。它也无法解释大量 RAM 的使用。

标签: ios iphone memory uiimage grand-central-dispatch


【解决方案1】:

这里最有可能发生的是,您正在通过上述处理构建一系列 UIImage,导致您的应用程序最终耗尽内存并崩溃。

Apple 的 UIImage+Effects 类别使用一系列框模糊来模糊 CPU 端。这不是世界上最快的过程。除此之外,创建 UIImage 可能会很慢,就像将 UIImage 设置为 UIImageView 以进行显示一样。几乎所有这些都是在 CPU 上完成的,而不是在 GPU 上。

因此,如果每次更新 UI 元素时触发上述方法,您将首先将一系列块调度到默认后台队列,然后异步调度到主队列。后者很可能是您的内存积累发生的地方,因为那里的每个块都会保留其中的对象。如果您的处理和 UIImageView 更新花费的时间比触发上述方法的时间间隔长,您将在调度队列中构建块,并且每个块中都会有 UIImages。这将很快导致内存堆积和崩溃。

有两种方法可以解决这个问题。首先,您可以使用调度信号量来确保只有一个块在您的后台队列上运行。我描述了一个用于此here 的过程。这可以防止内存积累,但可能对您的模糊速度没有帮助。

为此,您可以查看 Apple 提供的模糊类别的替代方案。我的开源 GPUImage 框架具有 replicates Apple's default effect 的 GPU 加速模糊。如果您需要更暗的变体,我会谈谈如何为这个here 修改它。往返 UIImages 仍然很慢,但是通过将模糊传送到 GPUImageView 而不是 UIImageView,您至少可以替换此处的慢速处理的后半部分。直接过滤到 GPUImageView 进行显示将所有内容保留在 GPU 上。

【讨论】:

  • 感谢您的帮助。我试图实现你的 GPUImage - i.imgur.com/Oh77xQo.png - 但图像没有模糊。另外,我将如何在上面的方法中使用调度信号量?我尝试了很多方法,但我认为我不太明白。
  • @user3127576 - 您在上面的代码中使用了棕褐色调滤镜,所以它当然不会模糊图像。您需要使用类似于上述 GPUImageiOSBlurFilter 或标准高斯的东西。我在我的信号量答案中提供了一些示例代码,您可以在此处应用。应该是普遍适用的。如果你不明白那里发生了什么,请看一下 Mike Ash 的 GCD 帖子:mikeash.com/pyblog/friday-qa-2009-09-25-gcd-practicum.html
  • 天啊!谢谢,现在模糊效果很好,谢谢:)我只是在努力让它变暗?我在 GPUImageiOSBlurFilter.m 中找到了 GPUImageLuminanceRangeFilter,但我不确定要更改什么
  • @user3127576 - 查看 kGPUImageLuminanceRangeFragmentShaderString 字符串常量,这是定义该操作的片段着色器的位置。数学是一种类似 C 的语言,您需要对其进行调整,直到获得您想要的效果。迭代应该不会太难,直到您让它与您需要的确切颜色对齐,然后将该代码复制到此过滤器的自定义深色版本,您可以使用它而无需破解框架代码本身。有几个人这样做了,但还没有人将其作为拉取请求发回。
  • 我不明白为什么 UIImage 在 被更改后会使用 450MB 的 RAM。可能存在某种内存泄漏。
【解决方案2】:

我正在使用 Stackblur

https://github.com/tomsoft1/StackBluriOS

非常易于使用,并且优化良好。

【讨论】:

  • 它仍然非常滞后,有时甚至无法加载。此外,Apple 的 UIImage+Effects 同时使图像变暗,这正是我想要的 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-07-21
  • 2013-06-06
  • 1970-01-01
  • 2015-09-09
  • 1970-01-01
  • 2014-01-30
  • 1970-01-01
相关资源
最近更新 更多