CoreImageで画像の加工をする その2「フィルタの重ねがけ」

CoreImageで画像の加工をする その1「準備から実行」の続きです。

前回モノクロ加工を行いましたが複数のエフェクトを適用したい場合があると思います。

例えばコントラストを調整する下記の様なメソッドを作ります

-(UIImage*)effectColorControls:(UIImage *)targetImage{
    
    CIImage *ciImage = [[CIImage alloc] initWithImage:targetImage];
    
    CIFilter *ciFilter = [CIFilter filterWithName:@"CIColorControls"
                                    keysAndValues:kCIInputImageKey, ciImage,
                          @"inputContrast", [NSNumber numberWithFloat:1.75],
                          nil
                          ];
    
    NSDictionary *contextOptions = [NSDictionary dictionaryWithObjectsAndKeys:
                                     [NSNumber numberWithBool:NO],kCIContextUseSoftwareRenderer,nil];
    
    CIContext *ciContext = [CIContext contextWithOptions:contextOptions];
    CGImageRef cgImageRef = [ciContext createCGImage:[ciFilter outputImage] fromRect:[[ciFilter outputImage] extent]];
    UIImage* resultImage = [UIImage imageWithCGImage:cgImageRef];
    CGImageRelease(cgImageRef);
    
    return resultImage;
}

これを呼び出すと下記の様な結果になります

before:

f:id:ojukog:20130413150546p:plain

after:

f:id:ojukog:20130413155821j:plain

 

ここまでは前回の使い方と同じです。

今回は前回作ったモノクロ+コントラストの2つを適用してみます。

凄く単純だと作った2つのメソッドを呼び出す様な

-(void)effectSample{
    UIImage *targetImage = [UIImage imageNamed:@"sample.png"];
    
    //モノクロ
    targetImage = [self effectMono:targetImage];
    //コントラスト
    targetImage = [self effectColorControls:targetImage];
    
    UIImageView *imageView = [[UIImageView alloc] initWithImage:targetImage];
    [self.view addSubview:imageView];
}

こんな感じで良い気がします。

実際これでも両方のエフェクトがかかった形になるのですが、毎回CIImageやCIContextを作ったりと非常に無駄が多いです。

特にCIContextは毎回作るのではなく使いまわすのが推奨されているので出来れば1度で済ませたいです。

またメモリ的にも重ねがけの方が使用量が少ないです。大きな画像を扱うとCGImageRefを作った時点でかなりのメモリが使用されてしまうので何度も行うのは得策ではないと思います。

 

じゃあ重ねがけってどうやんのよというとこんな感じでやります

-(UIImage*)effectMonoAndColorControls:(UIImage *)targetImage{
    CIImage *ciImage = [[CIImage alloc] initWithImage:targetImage];
    
    //モノクロ
   *ciFilter = [CIFilter filterWithName:@"CIColorMonochrome"
                                    keysAndValues:kCIInputImageKey, ciImage,
                          @"inputColor", [CIColor colorWithRed:0.75 green:0.75 blue:0.75],
                          @"inputIntensity", [NSNumber numberWithFloat:1.0],
                          nil
                          ];
    //コントラスト
    ciFilter = [CIFilter filterWithName:@"CIColorControls"
                          keysAndValues:kCIInputImageKey, [ciFilter outputImage],
                @"inputContrast", [NSNumber numberWithFloat:1.75],
                nil
                ];
    
    NSDictionary *contextOptions = [NSDictionary dictionaryWithObjectsAndKeys:
                                     [NSNumber numberWithBool:NO],kCIContextUseSoftwareRenderer,nil];
    
    CIContext *ciContext = [CIContext contextWithOptions:contextOptions];
    CGImageRef cgImageRef = [ciContext createCGImage:[ciFilter outputImage] fromRect:[[ciFilter outputImage] extent]];
    UIImage* resultImage = [UIImage imageWithCGImage:cgImageRef];
    CGImageRelease(cgImageRef);
    
    return resultImage;
}

要はCIFilterを作る際に使っているInputImageに、エフェクトを適用したCIImageのOutputImageを入れれば良いだけです。

これを実行するとこんな結果になります

f:id:ojukog:20130413163237j:plain

 

※ちょっとわかりにくいですがモノクロ単体だとこうなってました

f:id:ojukog:20130413152831j:plain

 

これでフィルタの重ねがけが出来るようになり、色々なフィルタの組み合わせで遊べます。

例えばPhotompyで使っている昔風にする加工や、一時期賑わった漫画風の様な加工も簡単に行えます