Core Image の CIFilter を使うといろいろなフィルタ処理(画像処理/画像加工)ができますが、iOS 8で CIKernel というクラスが追加され、そのフィルタ(CIFilter)を自作できるようになりました。
以下、CIKernel のフィルタ処理を記述し、それを使ってオリジナルの CIFilter を定義し、画像に適用するまでの手順です。
(更新履歴)本記事は2014年のiOS 8がまだベータ版だった頃に書いたもので、Objective-Cコードは古くなっている可能性があります。Swiftコードは2017年12月に追記したもので、Swift 4対応です。
CIKernel をつくる
カーネルを書く
カーネルはGLSLのサブセットで書きます。
kernel vec4 swapRedAndGreenAmount ( __sample s, float amount )
{ return mix(s.rgba, s.grba, amount); }
CIKernelオブジェクトを生成する
上記で書いたシェーダを 文字列として CIKernel の初期化メソッドに渡します
CIKernel *kernel = [CIKernel kernelWithString:kernelStr];
let kernel = CIColorKernel(source: kernelStr)!
CIFilter サブクラスをつくる
上記で生成した CIKernel オブジェクトを使用して、CIFilter サブクラスをつくります。
ヘッダには下記のようにプロパティを定義します。
@interface MyFilter : CIFilter
@property (nonatomic, strong) CIImage *inputImage;
@property (nonatomic, copy) NSNumber *inputAmount;
@end
実装ファイル側は長くなるので省略しますが、CIKernelを適用して出力する部分はこんな感じす。
- (CIImage *)outputImage
{
return [[self myKernel] applyWithExtent:self.inputImage.extent
arguments:@[self.inputImage, self.inputAmount]];
}
Swift 4で書くと、こんな感じになります。
class MyFilter: CIFilter {
private let kernelStr =
"kernel vec4 swapRedAndGreenAmount ( __sample s, float amount ) { return mix(s.rgba, s.grba, amount); }"
private let kernel: CIColorKernel
var inputImage: CIImage?
var inputAmount: Float = 1.0
override init() {
kernel = CIColorKernel(source: kernelStr)!
super.init()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func outputImage() -> CIImage? {
guard let inputImage = inputImage else {return nil}
return kernel.apply(extent: inputImage.extent, arguments: [inputImage, inputAmount])
}
}
##画像に適用する
使い方は 普通の CIFilter (ビルトインフィルタ) と同じ。
NSDictionary *params = @{kCIInputImageKey: ciImage,
@"inputAmount": @(1.0),
};
CIFilter *filter = [CIFilter filterWithName:@"MyFilter"
withInputParameters:params];
Swift 4の場合:
let filter = MyFilter()
filter.inputImage = inputImage
let outputImage = filter.outputImage()
###実行結果
(左:元画像 右:カスタムフィルタ適用後の画像)
##参考資料
- Developing Core Image Filter for iOS (WWDC 2014 Session 515)
- CIKernel Class Reference
- Core Image Kernel Language Reference
##関連記事
ちょっと古いものもありますが、Core Image、画像処理関連の記事は他にもいろいろと書いているので、よろしければご参照ください。