昨日の続き。GIFで保存すると影の部分が GIFのアルファチャネル(1bit, いわゆる透明情報)として書き出されてしまっていた。
結局これは GIFの仕様上避けられないことなので、発想を変えて背景色を与えて、そこに影を落とす様にしむけてみた。アルファチャネルを持たない JPEGでは(潔く?)初めからこのようになっている。
GIFの保存には NSBitmapImagRep#representationUsingType:properties: を使っている。これを使う前に白い背景と合成させる。その為のメソッドを書く。
- (NSBitmapImageRep*)fillBackground:(NSBitmapImageRep*)bitmap_rep
{
NSImage *src_image = [[[NSImage alloc] init] autorelease];
[src_image addRepresentation:bitmap_rep];
NSSize image_size = [src_image size];
NSImage *bg_image = [[[NSImage alloc] initWithSize:image_size] autorelease];
[bg_image lockFocus];
[[NSColor whiteColor] set];
[NSBezierPath fillRect:NSMakeRect(0, 0, image_size.width, image_size.height)];
[src_image compositeToPoint:NSZeroPoint operation:NSCompositeSourceOver];
[bg_image unlockFocus];
NSBitmapImageRep* output = [[[NSBitmapImageRep alloc] initWithData:[bg_image TIFFRepresentation]] autorelease];
return output;
}
このメソッドでは、入力された NSBitmapImageRep と同じ大きさの NSImageを作り、白く塗りつぶす。その上に入力画像を NSImage#compositeToPoint:operation: で上書きする。
これを保存前に呼出して使う。
結果はこんな感じ。影の部分は背景(白色)と合成され多少マシになっている。
NSBitmapImagRep#representationUsingType:properties:のオプションに NSImageDitherTransparency を指定してみる。あまり変わらない。
影を付けない場合。
なお最後にPreview.appと比較してみた。最初に PNGで書き出し、これを Preview.app で GIFへ変換して書き出す。
結果は下の通り。
Preview.appの場合、ディザが奇麗にかかると期待したがプログラムで書き出したものと見た目は変わらない。恐らく同じメソッドを使っていると思われる。また自動的に白い背景が付くところも同じ発想だ。
- - - -
直接は関係ないがこのブログで使っている Bloggerでは、プログラムやPreview.appで作成した GIF画像をアップロードするとエラーになって受け入れてくれない。GIF形式が特殊なんだろうか?Windowsなどで確認する必要があるな。