2016年7月7日木曜日

CoreImageの使い方基礎

CoreImageの機能と概要

  • フィルタ(リファレンスにリンク)
    • ぼかしとか、画像にかけるエフェクト
  • フィルタグラフ
    • フィルタの組み合わせで複雑なエフェクトを実現(?)
  • プラグインアーキテクチャ
    • システム提供のフィルタと、ユーザー自作フィルタを組み合わせて機能を拡張できる
  • ほとんどのハードウェア上で動作するように書かれてる
  • 必要とされる時までできるだけ実行を遅らせるので、メモリ確保が直前とかがある
  • コンテキスト( context)というオブジェクトが必要
    • 必要なメモリ割当、フィルタのカーネルをコンパイルして実行など、いろいろ使えるらしい
  • 座標は左下が0,0で、右上に行くに従って増える。SpriteKitなんかと一緒で、UIImageとは上下が逆になる。

フィルタのかけ方

  1. フィルタの作成と設定
  2. ソースイメージをフィルタに渡す
  3. フィルタ処理した画像を得る
コードは以下。
思ったよりも難しくないね。フィルタ名とパラメータの扱いがわかればどんどんいけそう?

//元画像作成
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)

    0 件のコメント:

    コメントを投稿