CoreImageの機能と概要
- フィルタ(リファレンスにリンク)
- フィルタグラフ
- フィルタの組み合わせで複雑なエフェクトを実現(?)
- プラグインアーキテクチャ
- システム提供のフィルタと、ユーザー自作フィルタを組み合わせて機能を拡張できる
- ほとんどのハードウェア上で動作するように書かれてる
- 必要とされる時までできるだけ実行を遅らせるので、メモリ確保が直前とかがある
- コンテキスト( context)というオブジェクトが必要
- 必要なメモリ割当、フィルタのカーネルをコンパイルして実行など、いろいろ使えるらしい
- 座標は左下が0,0で、右上に行くに従って増える。SpriteKitなんかと一緒で、UIImageとは上下が逆になる。
フィルタのかけ方
- フィルタの作成と設定
- ソースイメージをフィルタに渡す
- フィルタ処理した画像を得る
コードは以下。
思ったよりも難しくないね。フィルタ名とパラメータの扱いがわかればどんどんいけそう?
let uiInputImage = UIImage(named: "イメージ名") //UIImage作成
let ciInputImage = CIImage(image: uiInputImage!) //CIImageに変換
//*******フィルタの作成と設定(例:モノクロフィルタ)*******
let filter = CIFilter(name: "CIColorMonochrome") //フィルタ作成
filter!.setValue(image, forKey: kCIInputImageKey) //フィルタに画像渡す
filter?.setValue(CIColor(red: 1.0, green: 1.0, blue: 0), forKey: kCIInputColorKey) //フィルタパラメータ設定
filter?.setValue(1.0, forKey: kCIInputIntensityKey) //フィルタパラメータ設定
//フィルタ処理した画像を得る
//******CIContext作成*******
//これ使って一度CGImageに直した方がいろいろいいらしい
let ciContext = CIContext(options: nil) //nilで作成
let cgImage = ciContext.createCGImage((vignetteFilter?.outputImage)!, fromRect: ciInputImage!.extent)
//最後のextentってのはUIImageでいうboundsみたいな値らしい?
//*******CGImageからUIImageに変換******
let uiImage = UIImage(CGImage: cgImage) //UIImageに変換
myImageView.image = uiImage
フィルタ処理後のイメージを得る
monochromeFilter!.outputImage
でCIImageが得られるので、それをUIImageに再変換して表示したり、そのまま次のフィルタ処理に回したりする。
Context使ったほうがいいらしい
直接CIImageをUIImageに変換した場合、UIImageに設定してたものが無視されたりするんだそうな。
それを回避するため、一度CIContextを使ってCGImageに変換してからのほうがいいんだそうな。
パラメータはkeyを使って設定
フィルタの設定はkeyによってどのパラメータをいじるかを指定するわけだが、多くのkeyに対してはkCIで始まるStringが定義されているので、それを使えばいいし、定義されていないKeyがあれば" "で囲んだStringで指定してやればいい。
- 以下はどちらでも可
- monochromeFilter?.setValue(1.0, forKey: kCIInputIntensityKey)
- monochromeFilter?.setValue(1.0, forKey: "InputIntensityKey")
数値は厳密にはNSNumberの値なのだが、そのまま直接数値を指定する分には問題なさそう。
乱数とか、事前に計算の要素を入れた場合は、以下のように型に気をつけないといけない。
let scale = NSNumber(double: Double(arc4random() % 40) / 10) //0〜4までの整数値
filter?.setValue(scale, forKey: kCIInputScaleKey)
フィルタ作成時にパラメータを一度に並べて指定することもできる
let monochromeFilter = CIFilter(name: "CIColorMonochrome",
withInputParameters:
["inputColor" : sepiaColor,
"inputIntensity" : 1.0])
座標は元画像の大きさを、CIVectorで指定
パラメータで座標を指定する場合があるが、その場合は最終的に表示されるUIImageの大きさを基準にするのでなく、元画像の大きさで指定する。
出力先が640x480のサイズでも、オリジナル画像が1000x500だったら、中心部分を指定するには500,250の位置を指定する。
sourceImage.size.widthと.heightを使って求められるわな。
指定時はCIVector(x, y)でやらないといけない。
filter?.setValue(CIVector(x: centerX, y: centerY), forKey: kCIInputCenterKey)