画像エディターのぼかし処理について

ぼかし処理

    func boxBluredImage(radius: CGFloat) -> UIImage {
        
        let inputImage = CIImage(cgImage: self.cgImage!)
        let affineClampFilter = CIFilter(name: "CIAffineClamp")!
        affineClampFilter.setValue(inputImage, forKey: "inputImage")
        affineClampFilter.setValue(CGAffineTransform(scaleX: 1, y: 1), forKey: "inputTransform")
        let affineClampedImage = affineClampFilter.outputImage!

        
        let filter = CIFilter(name: "CIBoxBlur")!
        filter.setValue(affineClampedImage, forKey: "inputImage")
        filter.setValue(radius, forKey: "inputRadius")
        let bluredImage = filter.outputImage
        

        let cropFilter = CIFilter(name: "CICrop")!
        cropFilter.setValue(bluredImage, forKey: "inputImage")
        cropFilter.setValue(inputImage.extent, forKey: "inputRectangle")
        let croppedImage = cropFilter.outputImage!

        let context = CIContext()
        let cgImage = context.createCGImage(croppedImage, from: croppedImage.extent)!
        return UIImage(cgImage: cgImage)
    }

上のはすごい適当ですがCIFilterを使ってぼかし処理を加えました。

なぞってマスク

とりあえず下記のクラスを作成してみました。

class DrawingMaskView: UIView {
    
    static func mask(to: UIView) {
        let maskView = DrawingMaskView()
        maskView.frame = to.frame
        maskView.imageView.frame = to.bounds
        to.superview?.addSubview(maskView)
        to.mask = maskView.imageView
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        print("init")
        addGestureRecognizer(panGesture)
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    private var imageView = UIImageView()
    private var maskImage = UIImage()
    private var lineWidth: CGFloat = 40
    
    private lazy var panGesture: UIPanGestureRecognizer = {
        return UIPanGestureRecognizer(target: self, action: #selector(actionPan))
    }()
    
    private var previousPosition: CGPoint = .zero
    
    @objc func actionPan(_ sender: UIPanGestureRecognizer) {
        
        let currentPosition = sender.location(in: sender.view)
        
        if sender.state == .began {
            previousPosition = currentPosition
        }
        
        if sender.state != .ended {
            drawLine(from: previousPosition, to: currentPosition)
        }
        previousPosition = currentPosition
    }
    
    func drawLine(from: CGPoint, to: CGPoint){
        
        UIGraphicsBeginImageContextWithOptions(bounds.size, false, 0)

        if let ctx = UIGraphicsGetCurrentContext() {
            maskImage.draw(at: .zero)
            ctx.setLineWidth(lineWidth)
            ctx.setLineCap(.round)
            ctx.setStrokeColor(UIColor.green.cgColor)
            
            ctx.move(to: from)
            ctx.addLine(to: to)
            ctx.strokePath()
            maskImage = UIGraphicsGetImageFromCurrentImageContext()!
        }
        UIGraphicsEndImageContext()
        imageView.image = maskToAlpha(maskImage)
    }
    
    func maskToAlpha(_ image: UIImage) -> UIImage {
        
        guard let cgImage = image.cgImage else {
            return UIImage()
        }
        
        let inputImage = CIImage(cgImage: cgImage)
        let filter = CIFilter(name: "CIMaskToAlpha")!
        filter.setValue(inputImage, forKeyPath: "inputImage")
        return UIImage(ciImage: filter.outputImage!)
    }
}

CoreGraphicsを使ってお絵かきの要領でなぞったところに絵を描いてきます。 ただViewのmaskは透明度が考慮されるのでCoreImageのフィルターを使ってマスク画像を透明に変換しました。

        
        let blue = UIView()
        blue.backgroundColor = .blue
        blue.frame = view.bounds
        view.addSubview(blue)

        let red = UIView()
        red.backgroundColor = .red
        red.frame = view.bounds
        view.addSubview(red)
        
        DrawingMaskView.mask(to: red)

こんな感じでViewを二つ並べてなぞるとなぞったとこだけ赤いViewが出現すます。

f:id:churabou:20180601130448g:plain

この二つのViewをオリジナルの画像とぼかし画像をもつImageViewにするとなぞった部分のぼかし画像が見えるようになりUI上でのぼかし処理が完成しました。画像を変えるだけでモザイク処理にもできました。

f:id:churabou:20180601130452g:plain

f:id:churabou:20180601130454g:plain

あとはCoreImageにもCoreGraphicsにも画像をmaskして合成するメソッドがあるのでそれを用いて画像を出力した。 わからない事だらけだが今の所このやり方でぼかし処理をしている。