1

我正在 viewController 的 viewDidLoad 中使用以下函数创建模糊效果

func applyBlurEffect(image: UIImage){

        let imageToBlur = CIImage(image: image)!
        let blurfilter = CIFilter(name: "CIGaussianBlur")!
        blurfilter.setValue(10, forKey: kCIInputRadiusKey)
        blurfilter.setValue(imageToBlur, forKey: "inputImage")
        let resultImage = blurfilter.value(forKey: "outputImage") as! CIImage
        let croppedImage: CIImage = resultImage.cropping(to: CGRect(x:0,y: 0,width: imageToBlur.extent.size.width,height: imageToBlur.extent.size.height))
        let context = CIContext(options: nil)
        let blurredImage = UIImage (cgImage: context.createCGImage(croppedImage, from: croppedImage.extent)!)
        self.backImage.image = blurredImage


}

但是这段代码阻塞了 UI 并且 viewController 在延迟 3-4 秒后打开。我不想在没有 blurEffect 的情况下呈现 UI,也不希望用户在打开 viewController 时等待 3-4 秒。请提供此问题的最佳解决方案。

4

4 回答 4

1

GPUImage ( https://github.com/BradLarson/GPUImage ) blur 的工作速度比 CoreImage 快得多:

extension UIImage {
  func imageWithGaussianBlur() -> UIImage? {
    let source = GPUImagePicture(image: self)
    let gaussianFilter = GPUImageGaussianBlurFilter()
    gaussianFilter.blurRadiusInPixels = 2.2
    source?.addTarget(gaussianFilter)
    gaussianFilter.useNextFrameForImageCapture()
    source?.processImage()
    return gaussianFilter.imageFromCurrentFramebuffer()
  }
}

然而小延迟仍然是可能的(取决于图像大小),所以如果你不能在视图加载之前预处理图像,我建议先调整图像大小,模糊并显示结果缩略图,然后在原始图像之后在后台队列中处理,用模糊的原件替换缩略图。

于 2017-01-08T12:24:33.470 回答
0

核心映像编程指南

性能最佳实践

遵循以下做法以获得最佳性能:

  • 不要在每次渲染时都创建 CIContext 对象。上下文存储了大量的状态信息;重用它们更有效。
  • 评估您的应用是否需要色彩管理。除非你需要,否则不要使用它。请参阅您的应用程序需要颜色管理吗?在使用 GPU 上下文渲染 CIImage 对象时避免使用 Core Animation 动画。如果您需要同时使用两者,您可以将两者都设置为使用 CPU。
  • 确保图像不超过 CPU 和 GPU 限制。CIContext 对象的图像大小限制取决于 Core Image 使用 CPU 还是 GPU。使用
    inputImageMaximumSize 和 outputImageMaximumSize 方法检查限制。
  • 尽可能使用较小的图像。性能随输出像素的数量而变化。您可以将 Core Image 渲染到更小的视图、纹理或帧缓冲区中。允许 Core Animation 放大以显示大小。
  • 使用 Core Graphics 或 Image I/O 函数来裁剪或下采样,例如函数 CGImageCreateWithImageInRect 或
    CGImageSourceCreateThumbnailAtIndex。
  • UIImageView 类最适合静态图像。如果您的应用需要获得最佳性能,请使用较低级别的 API。
  • 避免 CPU 和 GPU 之间不必要的纹理传输。
    在应用内容比例因子之前渲染到与源图像大小相同的矩形。
  • 考虑使用可以产生类似于算法过滤器的结果的更简单的过滤器。例如,CIColorCube 可以产生
    与 CISepiTone 类似的输出,而且效率更高。

  • 在 iOS 6.0 及更高版本中利用对 YUV 图像的支持。相机像素缓冲区本身就是 YUV,但大多数图像处理
    算法都需要 RBGA 数据。在两者之间转换是有成本
    的。Core Image 支持从 CVPixelBuffer 对象读取 YUB
    并应用适当的颜色变换。

也可以看看 Brad Larson 的 GPUImage。您可能想使用它。看到这个答案。https://stackoverflow.com/a/12336118/1378447

于 2017-01-02T08:34:05.623 回答
0

利用调度队列。这个对我有用:

func applyBlurEffect(image: UIImage){

        DispatchQueue.global(qos: DispatchQoS.QoSClass.userInitiated).async {

            let imageToBlur = CIImage(image: image)!
            let blurfilter = CIFilter(name: "CIGaussianBlur")!
            blurfilter.setValue(10, forKey: kCIInputRadiusKey)
            blurfilter.setValue(imageToBlur, forKey: "inputImage")
            let resultImage = blurfilter.value(forKey: "outputImage") as! CIImage
            let croppedImage: CIImage = resultImage.cropping(to: CGRect(x:0,y: 0,width: imageToBlur.extent.size.width,height: imageToBlur.extent.size.height))
            let context = CIContext(options: nil)
            let blurredImage = UIImage (cgImage: context.createCGImage(croppedImage, from: croppedImage.extent)!)

            DispatchQueue.main.async {
                self.backImage.image = blurredImage
            }
        }
    }

但是这种方法会造成图像模糊 3-4 秒的延迟(但不会阻止其他 UI 内容的加载)。如果你也不想要那个时间延迟,那么将 UIBlurEffect 应用于 imageView 将产生类似的效果:

func applyBlurEffect(image: UIImage){

        self.profileImageView.backgroundColor = UIColor.clear
        let blurEffect = UIBlurEffect(style: .extraLight)
        let blurEffectView = UIVisualEffectView(effect: blurEffect)
        blurEffectView.frame = self.backImage.bounds
        blurEffectView.alpha = 0.5

        blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight] // for supporting device rotation
        self.backImage.addSubview(blurEffectView)
    }

通过将模糊效果样式更改为.light.dark以及 alpha 值从 0 到 1,您可以获得所需的效果

于 2017-01-05T09:39:17.797 回答
0

您能否将原始图像呈现给视图控制器并在后台线程上执行模糊处理,并在模糊处理准备好后做一个很好的效果来替换图像?

另外,也许您可​​以使用 UIVisualEffectView 并查看性能是否更好?

Apple 不久前还发布了一个使用 UIImageEffects 执行模糊的示例。它是用 Obj-C 编写的,但您可以在 Swift 中轻松使用它https://developer.apple.com/library/content/samplecode/UIImageEffects/Listings/UIImageEffects_UIImageEffects_h.html

于 2017-01-02T13:43:43.573 回答