以前紹介した画像をグレースケール変換して表示する方法が、Alphaチャネル(半透明マスク)に対応していないことがわかった。
透明部分が黒くなる
以前は背景が白い画像を使っていたので気がつかなかったのだが、背景が透明な画像をグレースケール変換するとその部分が黒くなってしまうことがわかった。
元画像の例。図ではわからないが周りの部分が透明になっている。
これを前回の方法でグレースケール変換するとこうなる。
周りの透明部分が黒くなってしまっている。これはグレースケール変換用に作成した CGBitmapContextCreate() の引数で kCGImageAlphaNone を渡していたため。この引数は Alphaチャネルを持たないことを示している。
CGContextRef context = CGBitmapContextCreate( nil, image.size.width, image.size.height, 8, 0, colorSpace, kCGImageAlphaNone);
Alphaチャネルの合成
これを解決するには透明部分、すなわちAlphaチャネルのみを取り出した画像を作り、これをマスク情報として前回の画像に合成してやれば良い。
Alphaチャネルの画像は CGBitmapContextCreate() の引数に kCGImageAlphaOnly を渡すと作ることができる。
先の例の画像の場合、Alphaチャネルはこんな感じになる。
白い部分が透明で、黒い部分が不透明をな領域を表している。
合成には CGImageCreateWithMask() が使える。
最終的なソースコードはこんな感じ
-(UIImage*)convertGrayScaleImage:(UIImage*)image { CGRect rect = CGRectMake(0.0, 0.0, image.size.width, image.size.height); CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray(); // (1) create alpha chanel CGContextRef alphaContext = CGBitmapContextCreate( nil, image.size.width, image.size.height, 8, 0, colorSpace, kCGImageAlphaOnly); CGContextDrawImage(alphaContext, rect, [image CGImage]); CGImageRef alphaImage = CGBitmapContextCreateImage(alphaContext); CGContextRelease(alphaContext); // (2) create gray scale image CGContextRef context = CGBitmapContextCreate( nil, image.size.width, image.size.height, 8, 0, colorSpace, kCGImageAlphaNone); CGContextDrawImage(context, rect, [image CGImage]); CGImageRef grayScaleImage = CGBitmapContextCreateImage(context); CGContextRelease(context); // (3) composite images UIImage* grayScaleUIImage = [UIImage imageWithCGImage: CGImageCreateWithMask(grayScaleImage, alphaImage)]; CGImageRelease(grayScaleImage); CGImageRelease(alphaImage); CGColorSpaceRelease(colorSpace); return grayScaleUIImage; }
さて実行してみよう。
背景が透明になった。
参考情報
iPhoneアプリ開発、その(185) 出るもんが出たか…|テン*シー*シー
kCGImageAlphaOnly と CGImageCreateWithMask() について参考になった。
Responses
Leave a Response