在viewDidLoad中的图像上使用GaussianBlur阻止UI

时间:2016-12-29 12:14:35

标签: ios image swift3 gaussianblur

我在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,并且在3-4秒的延迟后打开了viewController。我不想在没有blurEffect的情况下呈现UI,也不希望用户在打开viewController时等待3-4秒。 请为此问题提供最佳解决方案。

4 个答案:

答案 0 :(得分:1)

GPUImage(https://github.com/BradLarson/GPUImage)模糊效果比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()
  }
}

然而,仍然可能出现小延迟(取决于图像大小),因此如果您无法在视图加载之前预处理图像,我建议先调整图像大小,模糊并显示生成的缩略图,然后原始图像在后台队列中处理,用模糊原稿替换缩略图。

答案 1 :(得分:0)

Core Image Programming Guide

  

绩效最佳实践

     

请遵循以下做法以获得最佳效果:

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

  •   
  • 利用iOS 6.0及更高版本中对YUV图像的支持。相机像素缓冲区本身就是YUV但是大多数图像处理
      算法期望RBGA数据。转换成本之间需要付出代价   他们俩。 Core Image支持从CVPixelBuffer对象中读取YUB   并应用适当的颜色转换。

  •   

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

答案 2 :(得分:0)

您可以使用原始图像呈现视图控制器并在背景线程上执行模糊,并且一旦模糊图像准备就可以更换图像吗?

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

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

中轻松使用它

答案 3 :(得分: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,您可以获得所需的效果