如何使用 Swift 模糊 UIImageView 中的现有图像?

问题描述 投票:0回答:11

设置很简单。

  • 具有分配了图像的 UIImageView 的 ViewController。
  • 一个 UIButton,单击时会模糊 UIImageView 中的图像。

Storyboard

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var bg: UIImageView!

    @IBAction func blur(_ sender: Any) {
        let inputImage = CIImage(cgImage: (bg.image?.cgImage)!)

        let filter = CIFilter(name: "CIGaussianBlur")
        filter?.setValue(inputImage, forKey: "inputImage")
        filter?.setValue(10, forKey: "inputRadius")
        let blurred = filter?.outputImage
        bg.image = UIImage(ciImage: blurred!)
    }
}

单击按钮时,屏幕会变成白色。无法弄清楚我做错了什么。有人知道我做错了什么吗?

ios swift uiimageview cifilter ciimage
11个回答
38
投票

您可以简单地使用

UIVisualEffect
来实现模糊效果。当您尝试使用 CoreImage 实现模糊效果时。请在
import CoreImage
到您的班级之后尝试以下代码。

var context = CIContext(options: nil)

func blurEffect() {

    let currentFilter = CIFilter(name: "CIGaussianBlur") 
    let beginImage = CIImage(image: bg.image!)
    currentFilter!.setValue(beginImage, forKey: kCIInputImageKey)
    currentFilter!.setValue(10, forKey: kCIInputRadiusKey)

    let cropFilter = CIFilter(name: "CICrop")
    cropFilter!.setValue(currentFilter!.outputImage, forKey: kCIInputImageKey)
    cropFilter!.setValue(CIVector(cgRect: beginImage!.extent), forKey: "inputRectangle")

    let output = cropFilter!.outputImage 
    let cgimg = context.createCGImage(output!, from: output!.extent)
    let processedImage = UIImage(cgImage: cgimg!)
    bg.image = processedImage
}

输出:

enter image description here

注意:我建议您在真实设备中测试代码,因为模拟器在 coreImage 上的性能太慢。


32
投票

对于那些❤️协议的人

protocol Blurable {
    func addBlur(_ alpha: CGFloat)
}

extension Blurable where Self: UIView {
    func addBlur(_ alpha: CGFloat = 0.5) {
        // create effect
        let effect = UIBlurEffect(style: .dark)
        let effectView = UIVisualEffectView(effect: effect)
        
        // set boundry and alpha
        effectView.frame = self.bounds
        effectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        effectView.alpha = alpha
        
        self.addSubview(effectView)
    }
}

// Conformance
extension UIView: Blurable {}

// use
someImageview.addBlur()

8
投票

以下是我在 SWIFT 3.1 中获得预期结果的方式: 希望它会有所帮助。

func blurImage(image:UIImage) -> UIImage? {
        let context = CIContext(options: nil)
        let inputImage = CIImage(image: image)
        let originalOrientation = image.imageOrientation
        let originalScale = image.scale

        let filter = CIFilter(name: "CIGaussianBlur")
        filter?.setValue(inputImage, forKey: kCIInputImageKey)
        filter?.setValue(10.0, forKey: kCIInputRadiusKey) 
        let outputImage = filter?.outputImage

        var cgImage:CGImage?

        if let asd = outputImage
        {
            cgImage = context.createCGImage(asd, from: (inputImage?.extent)!)
        }

        if let cgImageA = cgImage
        {
            return UIImage(cgImage: cgImageA, scale: originalScale, orientation: originalOrientation)
        }

        return nil
    }

7
投票

CoreImage 中实际上有一个方便的实现 https://developer.apple.com/documentation/coreimage/ciimage/1645897-applyinggaussianblur

extension UIImage {

func blur(_ radius: Double) -> UIImage? {
    if let img = CIImage(image: self) {
        return UIImage(ciImage: img.applyingGaussianBlur(sigma: radius).cropped(to: img.extent))
    }
    return nil
}

2
投票

使用这个:

 import UIKit

    class ViewController: UIViewController {

        @IBOutlet weak var bgImageView: UIImageView!
        @IBOutlet weak var blurButton: UIButton!


        override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view, typically from a nib.
        }

        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
            // Dispose of any resources that can be recreated.
        }


        @IBAction func blurButtonTapped(_ sender: Any) {

                let inputImage = CIImage(cgImage: (self.bgImageView.image?.cgImage)!)
                let filter = CIFilter(name: "CIGaussianBlur")
                filter?.setValue(inputImage, forKey: "inputImage")
                filter?.setValue(10, forKey: "inputRadius")
                let blurred = filter?.outputImage

                var newImageSize: CGRect = (blurred?.extent)!
                newImageSize.origin.x += (newImageSize.size.width - (self.bgImageView.image?.size.width)!) / 2
                newImageSize.origin.y += (newImageSize.size.height - (self.bgImageView.image?.size.height)!) / 2
                newImageSize.size = (self.bgImageView.image?.size)!

                let resultImage: CIImage = filter?.value(forKey: "outputImage") as! CIImage
                let context: CIContext = CIContext.init(options: nil)
                let cgimg: CGImage = context.createCGImage(resultImage, from: newImageSize)!
                let blurredImage: UIImage = UIImage.init(cgImage: cgimg)
                self.bgImageView.image = blurredImage
        }

    }

输出:

enter image description here

Gitbub 链接:

https://github.com/k-satireddy/ImageBlurEffect


2
投票

一个性能良好、结果不错的解决方案是

StackBlur
,它使用了一种巧妙的算法,可以有效地近似模糊:

这是高斯模糊和盒子模糊之间的折衷方案,它创建 模糊效果比 Box Blur 好看得多,但速度比我的快 7 倍 高斯模糊的实现。我将其称为“堆栈模糊”是因为 最好地描述了这个过滤器的内部工作原理:它创建了一种 移动颜色的堆栈(或者可能是“河内塔”类型的结构) 同时扫描图像。这个“塔”控制着重量 卷积核内的单个像素并给出像素 中心的权重最高。速度的秘密在于 算法只需将一个新像素添加到堆栈的右侧 同时删除最左边的像素。其余颜色 堆栈最顶层的值要么增加,要么减少 一,取决于它们是在右侧还是左侧 堆栈。

查看 Github 上的 StackBlur

有很多版本,也有 Swift 端口,但这些版本比 Obj-C 版本慢得多。

2019 年新增:

如果要模糊的图像是远程加载的,我强烈推荐Nuke框架,它可以远程加载图像并可以应用开箱即用的模糊滤镜。它的应用程序类似于Android上的Glide库。虽然模糊一张图像可能很容易,但在考虑设备资源限制的情况下模糊许多图像(例如在集合视图中)就不那么简单了。 Nuke 针对远程图像加载、缓存和处理进行了高度优化。它还可以在多个方面进行扩展。通过比较可用的远程图像加载框架,我认为截至 2019 年 11 月,Nuke 是最稳定、最先进的。


1
投票

我的分机

extension UIImage {
    
    func blurImage(radius: CGFloat = 10) -> UIImage? {
        guard let cgImage = cgImage else { return nil }
        let inputCIImage = CIImage(cgImage: cgImage)
        let context = CIContext(options: nil)
        
        let filter = CIFilter(name: "CIGaussianBlur")
        filter?.setValue(inputImage, forKey: kCIInputImageKey)
        filter?.setValue(radius, forKey: kCIInputRadiusKey)
        let outputImage = filter?.outputImage
        
        if let outputImage = outputImage,
            let cgImage = context.createCGImage(outputImage, from: inputImage.extent) {
            
            return UIImage(
                cgImage: cgImage,
                scale: scale,
                orientation: imageOrientation
            )
        }
        return nil
    }
 }

0
投票

我在 NSObject 类中进行了模糊处理,因此我可以轻松地在整个项目中使用此方法。

class Helper: NSObject
{
    class func addBlurView(_ inView : UIView) -> UIVisualEffectView
    {
        let blurEffect = UIBlurEffect(style: UIBlurEffectStyle.dark)
        let blurEffectView = UIVisualEffectView(effect: blurEffect)

        //always fill the view
        blurEffectView.frame = inView.bounds
        blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        blurEffectView.alpha = 0.5

        return blurEffectView
    }
}

在 ViewController 中,我创建了 UIVisualEffectView 的对象。然后调用辅助类方法来添加模糊。

import UIKit

class ViewController: UIViewController
{
   var blurEffectView : UIVisualEffectView!
    override func viewDidLoad() {
        super.viewDidLoad()

      blurEffectView = Helper.addBlurView((imgView)!)
      self.imgView.addSubview(blurEffectView)
}

0
投票

检查是否有东西为零。我遇到了类似的问题,但就我而言,我没有创建 CIImage 的新实例,因为 image.ciimage 为零。


-1
投票

您可以通过

UIBlurEffect
UIVisualEffectView
添加模糊效果:

@IBAction func blur(_ sender: Any) {

    let darkBlur = UIBlurEffect(style: UIBlurEffectStyle.dark) 
    let blurView = UIVisualEffectView(effect: darkBlur)
    blurView.frame = bg_imagview.bounds
    blurView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
    bg_imagview.addSubview(blurView)

}

-2
投票

嘿,所有像我一样的懒人。

只需使用 cocoapods 添加 SwifterSwift 即可。

导入SwifterSwift。

import SwifterSwift

像下面一样模糊图像视图。

someImageView.blur()
© www.soinside.com 2019 - 2024. All rights reserved.