web-dev-qa-db-fra.com

Comment brouiller une image existante dans un UIImageView avec Swift?

La configuration est simple. 

  • Un ViewController avec UIImageView auquel une image est attribuée. 
  • Un bouton UIB qui, une fois cliqué, rend floue l'image dans le 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!)
    }
}

Lorsque le bouton est cliqué, l'écran devient blanc. Je ne peux pas comprendre ce que je fais mal. Quelqu'un sait ce que je fais mal?

15
Mark Moeykens

Vous pouvez simplement utiliser UIVisualEffect pour obtenir un effet de flou. Lorsque vous essayez d’obtenir un effet de flou à l’aide de CoreImage.Essayez ci-dessous le code après import CoreImage dans votre classe.

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
}

Sortie:

 enter image description here

Remarque: Je vous recommande de tester le code dans un périphérique réel car les performances du simulateur sont trop lentes sur coreImage.

17
Joe

pour ceux qui ❤️ protocoles

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

extension Bluring 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: Bluring {}

// use
someImageview.addBlur()
12
kaushal.exe

Voici comment j'ai obtenu mon résultat attendu dans Swift 3.1: J'espère que cela vous aidera.

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
    }
4
Md Milan Mia

J'ai créé le flou dans une classe NSObject afin de pouvoir utiliser facilement cette méthode dans tout le projet.

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

Dans ViewController, j'ai créé un objet de UIVisualEffectView . Appelez ensuite la méthode de la classe d'assistance pour ajouter du flou.

import UIKit

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

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

Utilisez ceci: 

 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
        }

    }

Sortie:

 enter image description here

Lien Gitbub:

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

0
KSR

Les solutions utilisant UIVisualEffectView ou CIFilter ont des performances médiocres ou des résultats mauvais (produisant une bordure claire floue autour de l'image, comme le montre la réponse Joes), ou les deux.

L’une des solutions les plus performantes avec des résultats décents est StackBlur qui utilise un algorithme intelligent qui permet d’approcher efficacement un flou:

C’est un compromis entre le flou gaussien et le flou de boîte que cela crée beaucoup plus beau flou que Box Blur, mais est 7 fois plus rapide que mon Mise en œuvre du flou gaussien. Je l'ai appelé Stack Blur parce que ceci décrit le mieux comment ce filtre fonctionne en interne: il crée une sorte de pile mobile (ou peut-être une structure de type "Tour de Hanoi") de couleurs lors de la numérisation de l'image. Cette "tour" contrôle les poids des pixels simples dans le noyau de convolution et donne le pixel au centre le poids le plus élevé. Le secret de la vitesse est que le L'algorithme n'a qu'à ajouter un nouveau pixel sur le côté droit de la pile et en même temps, supprimez le pixel le plus à gauche. Les couleurs restantes sur la couche la plus haute de la pile sont soit ajoutés, soit réduits de un, selon qu’ils se trouvent à droite ou à gauche du empiler.

Découvrez StackBlur sur Github .

Il existe de nombreuses versions, y compris les ports Swift, mais elles sont beaucoup plus lentes que les versions Obj-C.

0
Manuel