LoginSignup
12
3

More than 3 years have passed since last update.

Swift:CIAffineClampを使って縁まで綺麗なぼかし画像を取得する

Posted at

CIAffineClampってなぁに

CIAffineClamp.png

CIAffineClampによるフィルターを画像に適用すると,画像の縁(上下左右1px)をそれぞれの方向に無限大に引き伸ばした仮想上の画像データを生成することができます.これにより,ガウシアン・フィルタや一部のカラーフィルタのように,あるピクセルの周囲のピクセルをサンプリングしてそのピクセルの色を決定するようなフィルタ(下図)を扱う場合に画像縁の欠けている部分を補うことができます.
↓こういうやつ
ガウシアン.png
参照できない.png
↑デフォルトでは,はみ出した参照できない部分は透明色で補完されます.

直接CIGaussianBlurを使った場合

before.png
左)オリジナル,右)ぼかし加工結果
画像の縁の色が薄くなってぼかしが弱いことがわかります.

ソース

// オリジナル画像
let nsImage = NSImage(imageLiteralResourceName: "Test")        
guard let imageData = nsImage.tiffRepresentation, let ciImage = CIImage(data: imageData) else { return }

// ガウシアン・フィルタ
guard let blurFilter = CIFilter(name: "CIGaussianBlur") else { return }
blurFilter.setValue(ciImage, forKey: kCIInputImageKey)
blurFilter.setValue(5, forKey: kCIInputRadiusKey)
guard let blurImage = blurFilter.outputImage else { return }
let context = CIContext(options: nil)
guard let resultImage = context.createCGImage(blurImage, from: CGRect(origin: .zero, size: nsImage.size)) else { return }

resultView.image = NSImage(cgImage: resultImage, size: nsImage.size)

CIAffineClampを介して間接的にCIGaussianBlurを使った場合

after.png
左)オリジナル,中央)CIAffineClamp時点での結果,右)ぼかし加工結果
画像の縁までしっかりぼかしがかかっていることがわかります.

ソース

// オリジナル画像
let nsImage = NSImage(imageLiteralResourceName: "Test")        
guard let imageData = nsImage.tiffRepresentation, let ciImage = CIImage(data: imageData) else { return }

// CIAffineClamp
guard let clampFilter = CIFilter(name: "CIAffineClamp") else { return }
clampFilter.setValue(ciImage, forKey: kCIInputImageKey)
clampFilter.setValue(CGAffineTransform(scaleX: 1.0, y: 1.0), forKey: kCIInputTransformKey)
guard let clampImage = clampFilter.outputImage else { return }
let context = CIContext(options: nil)
let rect = CGRect(origin: CGPoint(x: -25, y: -25), size: CGSize(width:  nsImage.size.width + 50, height: nsImage.size.height + 50))
guard let cgImage = context.createCGImage(clampImage, from: rect) else { return }

imageView.image = NSImage(cgImage: cgImage, size: rect.size)

// ガウシアン・フィルタ
guard let blurFilter = CIFilter(name: "CIGaussianBlur") else { return }
blurFilter.setValue(clampImage, forKey: kCIInputImageKey)
blurFilter.setValue(5, forKey: kCIInputRadiusKey)
guard let blurImage = blurFilter.outputImage else { return }
guard let resultImage = context.createCGImage(blurImage, from: CGRect(origin: .zero, size: nsImage.size)) else { return }

resultView.image = NSImage(cgImage: resultImage, size: nsImage.size)

所感

CIFilterはうまく組み合わせることで,効率的に高速な画像処理が行えるため,ガンガン使っていきましょう.

12
3
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
3