2006年 12月 02日

OSX スクリーンショット

画面イメージを取得して書き出してみる。

// gcc -framework Cocoa
// depth 32bit, intel little endian
#import <Cocoa/Cocoa.h>

int main() {
	int w = CGDisplayPixelsWide(kCGDirectMainDisplay);
	int h = CGDisplayPixelsHigh(kCGDirectMainDisplay);
	NSLog(@"%d, %d", w, h);

	unsigned char* _screenBytesActual = (unsigned char*)CGDisplayBaseAddress(kCGDirectMainDisplay);
	NSLog(@"Address: %08x", _screenBytesActual);

	int bitPerPixel    = CGDisplayBitsPerPixel(kCGDirectMainDisplay);
	int bitPerSample   = CGDisplayBitsPerSample(kCGDirectMainDisplay);
	int samplePerPixel = CGDisplaySamplesPerPixel(kCGDirectMainDisplay);
	int bytePerRow     = CGDisplayBytesPerRow(kCGDirectMainDisplay);
	int bytePerPixel   = bitPerPixel / 8;
	NSLog(@"%d %d %d %d %d", bitPerPixel, bitPerSample, samplePerPixel, bytePerRow, bytePerPixel);

	FILE* fp;
	if ((fp = fopen("test.bin", "w")) == NULL) {
		NSLog(@"fopen failed");
		exit(1);
	}

	int x, y;
	for (y = 0; y < h; y ++) {
		fwrite(_screenBytesActual + y * bytePerRow, w * bytePerPixel, 1, fp);
	}
	fclose(fp);

	return 0;
}

書き出されたファイルは BGRA がディスプレイの左上から並んでる (intel)。
1ピクセルあたり 4 bytes なので、全体では 1280*800*4 = 4096000 = 4000KB

でできた test.bin を png なりに変換してみる。ここでは rmagick

require 'rubygems'
require 'RMagick'
require 'ostruct'
require 'profiler'

frame = OpenStruct.new
frame.width = 1280
frame.height = 800

Profiler__.start_profile
img = Magick::Image.new(frame.width, frame.height)
img.import_pixels(0, 0, frame.width, frame.height, "BGRA", File.read("test.bin"), Magick::CharPixel)

img.write("test.png")

Profiler__.print_profile(STDOUT)

img.write は遅い。