簡體   English   中英

如何使用 Swift 模糊 UIImageView 中的現有圖像?

[英]How to blur an existing image in a UIImageView with Swift?

設置很簡單。

  • 一個帶有 UIImageView 的 ViewController,它分配了一個圖像。
  • 單擊時會模糊 UIImageView 中的圖像的 UIButton。

故事板

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!)
    }
}

單擊按鈕時,屏幕將變為白色。 無法弄清楚我做錯了什么。 有人知道我在做什么錯嗎?

您可以簡單地使用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
}

輸出:

在此處輸入圖像描述

注意:我建議您在真實設備中測試代碼,因為模擬器在 coreImage 上的性能太慢。

對於那些❤️協議的人

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()

以下是我在 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
    }

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))
    }
    return nil
}

StackBlur是一個效果不錯且性能良好的解決方案,它使用一種巧妙的算法來有效地逼近模糊:

這是 Gaussian Blur 和 Box blur 之間的折衷方案。它創建的模糊效果比 Box Blur 好得多,但比我的 Gaussian Blur 實現快 7 倍。 我將其命名為堆棧模糊,因為它最好地描述了此濾鏡在內部的工作方式:它在掃描圖像時創建一種移動的顏色堆棧(或者可能是“河內之塔”類型的結構)。 這個“塔”控制卷積核內單個像素的權重,並賦予中心像素最高的權重。 速度的秘訣在於該算法只需在堆棧的右側添加一個新像素,同時移除最左側的像素。 堆棧最頂層的剩余顏色要么加一,要么減一,具體取決於它們是在堆棧的右側還是左側。

查看Github 上的 StackBlur

那里有很多版本,還有 Swift 端口,但這些版本比 Obj-C 版本慢很多。

2019年補充:

如果要模糊的圖像是遠程加載的,我強烈推薦Nuke框架,它可以遠程加載圖像並可以開箱即用地應用模糊過濾器。 它的應用程序可與 Android 上的 Glide 庫相媲美。 雖然模糊一張圖像可能很容易,但在考慮設備資源限制的同時模糊許多圖像(例如在集合視圖中)就不那么簡單了。 Nuke 針對遠程圖像加載、緩存和處理進行了高度優化。 它還可以在多個方面進行擴展。 通過比較可用的遠程圖像加載框架,我認為 Nuke 是截至 2019 年 11 月為止最穩定和最先進的。

用這個:

 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
        }

    }

輸出:

在此處輸入圖像描述

GitHub 鏈接:

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

我的分機

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
    }
 }

我在一個 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)
}

檢查是否有什么東西是零。 我遇到了類似的問題,但在我的情況下,我沒有創建 CIImage 的新實例,因為 image.ciimage 將為零。

您可以通過UIBlurEffectUIVisualEffectView添加模糊效果:

@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)

}

嘿,所有像我一樣的懶人。

只需將 SwifterSwift 與 cocoapods 一起添加即可。

導入 SwifterSwift。

import SwifterSwift

像下面一樣模糊您的圖像視圖。

someImageView.blur()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM