La configuration est simple.
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?
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:
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.
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()
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
}
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)
}
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
}
}
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.