スクリーンキャプチャした画像にマウスカーソル画像を合成してみる。
サンプル:MousePointer-3.zip
まずは全画面キャプチャに、NSCursorから取得した矢印カーソルを合成してみる。タイマーを開始すると5秒後に screen.tiff をデスクトップへ作成する。
キャプチャには CGWindowListCreateImage を使い、矢印カーソルは NSCursor#arrowCursor を使う。
- (NSImage*)cursorImage
{
return [[NSCursor arrowCursor] image];
}
- (NSImage*)screenImage
{
CGImageRef cgimage = CGWindowListCreateImage(CGRectInfinite,
kCGWindowListOptionAll,
kCGNullWindowID,
kCGWindowImageDefault);
NSBitmapImageRep *bitmap_rep = [[NSBitmapImageRep alloc] initWithCGImage:cgimage];
NSImage *image = [[[NSImage alloc] init] autorelease];
[image addRepresentation:bitmap_rep];
[bitmap_rep release];
CGImageRelease(cgimage);
return image;
}
スクリーンキャプチャ画像は後の合成処理がしやすい様に CGImageRef から NSImage へ変換しておく。
先の2つのメソッドから NSImage を取得した後、#compositeToPoint:operation: を使い合成処理を行う。カーソル位置は、キャプチャ直後の座標を NSEvent#mouseLocation から取得して利用している。
- (void)capture
{
NSImage* screen_image = [self screenImage];
NSImage* cursor_image = [self cursorImage];
NSPoint p = [NSEvent mouseLocation];
NSSize s = [cursor_image size];
[screen_image lockFocus];
[cursor_image compositeToPoint:p operation:NSCompositeSourceOver];
[screen_image unlockFocus];
:
:
するとこうなる。以下、みやすいようにカーソルの周辺だけに手作業で切り取ってある。

実はマウスカーソルは Safariアイコンの磁石の中心を指していた。合成の結果、マウスカーソルの位置がずれている。これは左下が原点の座標系を使っていることによる。
そこで補正してやる。マウスカーソルの高さの分だけ修正すると次の様になる。
NSPoint p = [NSEvent mouseLocation];
NSSize s = [cursor_image size];
p.y -= s.height;

いい感じだがまだ少しづれている。今度の原因はマウスカーソルのポイント位置が画像の左上からずれていること。これはマウスカーソル毎に hot spot と呼ばれるオフセット(NSPoint)として定義されている。例えば NSCursor#arrowCursor の場合、画像の左上からカーソルが指す点は (4, 4)だけずれている。

hot spot は NSCursor#hotSpot で取得することができる。
そこでこの (4, 4)を補正してやると:

うまくいった。