我在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秒。 请为此问题提供最佳解决方案。
答案 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)
绩效最佳实践
请遵循以下做法以获得最佳效果:
- 每次渲染时都不要创建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,您可以获得所需的效果