CIFilter で画像をモノトーンに変換する : Objective-C プログラミング
PROGRAM
CIFilter で画像をモノトーンに変換する
iPhone アプリで使うボタン画像を 1 色だけ用意して、シーンに合わせて色を変えて使う方法はないかと調べていたところ、CIFilter の "CIColorMonochrome" というものが iOS 5.0 から使えることを知りました。
このフィルタを使うことで、指定した色で画像を単調化できるとのことなので、さっそく試してみました。
コードは簡単で、たとえば変換したい画像を UIImage で、単調化する色を UIColor で指定して、単調化された画像を戻り値で返すメソッドを実装すると、次のような感じになります。
// image を monochromeColor で単調化した画像を返します。
- (UIImage*)monochromeImageByImage:(UIImage*)image monochromeColor:(UIColor*)monochromeColor
{
UIImage* monochromeImage;
// UIImage と UIColor を Core Image のデータ形式に変換します。
CIImage* ciImage = [[CIImage alloc] initWithImage:image];
CIColor* ciColor = [[CIColor alloc] initWithColor:monochromeColor];
NSNumber* nsIntensity = @1.0f;
// コンテキストとモノトーンフィルタを作成して、そこに画像を通すことで、単調化された画像を取得できます。
CIContext* ciContext = [CIContext contextWithOptions:nil];
CIFilter* ciMonochromeFilter = [CIFilter filterWithName:@"CIColorMonochrome" keysAndValues:kCIInputImageKey, ciImage, @"inputColor", ciColor, @"inputIntensity", nsIntensity, nil];
// 単調化された画像をいったん CGImageRef に変換して、それを UIImage に変換します。
CGImageRef cgMonochromeImage = [ciContext createCGImage:ciMonochromeFilter.outputImage fromRect:[ciMonochromeFilter.outputImage extent]];
monochromeImage = [UIImage imageWithCGImage:cgMonochromeImage scale:image.scale orientation:UIImageOrientationUp];
CGImageRelease(cgImage);
// これで、単調化された画像を UIImage で取得することができました。
return monochromeImage;
}
CIFilter を使うためには CIImage や CIColor のデータを使う必要があるため、データの変換で少し複雑になっていますが、やっていることは CIContext を取得して、CIFilter を使って画像にフィルタをかけているだけです。
ここでは CIFilter で指定するフィルター名を "CIColorMonochrome" にすることで、単調化するフィルタを用意しています。
次の keysAndValues では、この "CIColorMonochrome" フィルタで使うパラメーターを指定していて、kCIInputImageKey では変換する画像を CIImage で、"inputColor" では単調化で使う色を CIColor で指定しています。
もうひとつの "inputIntensity" では、単調化の際の線形ブレンドの強さを指定しています。
この線形ブレンドの値が 1.0 のとき、指定した色で完全に単調化されるようでした。それより大きい場合は指定した色が強く、小さい場合は弱く適用されるようですが、この時には指定した色とは印象がだいぶ違って来たりする様子です。
この "CIColorMonochrome" フィルタを通した場合、たとえば次のような画像が得られました。
上段が元の画像で、単調化された後の画像が下の段です。真ん中の色が、単調化に使った色になっています。
印象としては、指定した色をベースにして、黒に近づくほど濃く、白に近づくほど薄く、単調化される様子ですね。
重要なところは、真っ白や真っ黒のような色は、このフィルタを通してもそのままの色で出力されるところです。
こんな感じで、色を変えたい画像は黒よりも薄い色で描く必要があったり、適用する色も出来上がりの色を意識して指定しないといけないところはありますけど、それさえ気を付ければ、プログラム中で状況に合わせてボタンの画像色を変えることも簡単ですね。
たとえば、背景色をユーザーに自由に設定してもらって、それに合わせてボタンの色を変化させるといったことも、画像を 1 枚ずつ用意するだけでできるようになると思います。
黒色で作成した画像も調整したければ、ビットマップを操作して画像をモノトーンに変換する で記した方法や、Objective-C フラグメントシェーダー事始め で記した方法を使って、ビットマップデータを自分の好みに変換することでも実現できました。
[ もどる ]