Functional Swift 3章 "Wrapping Core Image" まとめ
この章ではCore ImageをfunctionalにラッピングするAPIを構築することで、より実戦的に高階関数と関数合成を利用する方法を学びます。
Filter型
typealias Filter = CIImage -> CIImage
オリジナルの
let filter = CIFilter(name: "CIVignette")
などのkey値で初期化するCIFilterをカプセル化するためにFilter型を関数として定義。
フィルタの構築
Filter型を定義したので、個別のFilterを定義していく
全て
func myFilter("パラメータ") -> Filter
の形
func blur(radius: Double) -> Filter { return { image in let parameters = [ kCIInputRadiusKey: radius, kCIInputImageKey: image ] guard let filter = CIFilter(name: "CIGaussianBlur", withInputParameters: parameters) else { fatalError() } guard let outputImage = filter.outputImage else { fatalError() } return outputImage } }
引数はぼかしの半径のみです。 CIImage型のimageをとり、新しいCIImageを返す関数(先ほど定義したFilter(CIImage -> CIImage))を返します。 同じパターンで様々なフィルタ関数を定義できます。
func chrome() -> Filter { return { image in let parameters = [ kCIInputImageKey: image ] guard let filter = CIFilter(name: "CIPhotoEffectChrome", withInputParameters: parameters) else { fatalError() } guard let outputImage = filter.outputImage else { fatalError() } return outputImage } }
フィルタを合成
ここまで作成したぼかしとクロームのフィルタ関数を合成していきます。
let url = NSURL(string: "http://www.objc.io/images/covers/16.jpg") let image = CIImage(contentsOfURL: url!)! let blurredImage = blur(5.0)(image) let chromedImage = chrome()(blurredImage)
一度ブラーをかけたimageに新たにクロームフィルタをかけて画像を生成しています。 もちろん一つにまとめることもできますが、括弧が増え途端に読めなくなってしまいます。
let result = chrome()(blur(5.0)(image))
そこで、カスタムオペレーションを定義することで読みやすさを保つことができます。
infix operator >>> { associativity left } func >>>(filter1: Filter, filter2: Filter) -> Filter { return { image in filter2(filter1(image)) } } let filter = chrome() >>> blur(5.0) let result = filter(image)