2011年7月27日水曜日

Quartz Composer / QCRendererを用いてコマンドラインで画像の差分をとってみる(composite)

動機
画像の差分をとりたいなと思い,GoogleReaderに貯め込んだ記事を探してみた.

ImageMagickという文字をみて,インストールするのめんどくさいなぁ…って逃げ出した.
Quartz Composerでならすぐつくれるのにって思い,以前みつけたQuartz Composer Offlineを応用すれば画像も書き出せるな.ってことでこれを参考にやってみた.(既に有名な記事がありそうだけどやってみたw)

やってみた
1.Command Line Toolプロジェクト

2.Cocoa.framework, OpenGL.framework, Quartz.frameworkを追加

3.コード

#import <Foundation/Foundation.h>
#import <Quartz/Quartz.h>

int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

if (argc != 3) {
[pool drain];
return 1;
}
NSString *filepath1= [NSString stringWithCString:argv[1] encoding:NSUTF8StringEncoding];
NSString *filepath2= [NSString stringWithCString:argv[2] encoding:NSUTF8StringEncoding];
NSImage *image1= [[NSImage alloc] initWithContentsOfFile:filepath1];
NSImage *image2= [[NSImage alloc] initWithContentsOfFile:filepath2];

NSUInteger width= 16;
NSUInteger height= 16;
NSString *compositionPath= @"./composition.qtz";
QCRenderer *renderer= nil;
{
NSOpenGLPixelFormatAttribute attributes[]= {
NSOpenGLPFAPixelBuffer,
NSOpenGLPFANoRecovery,
NSOpenGLPFAAccelerated,
NSOpenGLPFADepthSize, (NSOpenGLPixelFormatAttribute)24,
NSOpenGLPFASampleBuffers, (NSOpenGLPixelFormatAttribute)1,
NSOpenGLPFASamples, (NSOpenGLPixelFormatAttribute)16,
(NSOpenGLPixelFormatAttribute)0
};
NSOpenGLPixelFormat *format= [[[NSOpenGLPixelFormat alloc] initWithAttributes:attributes] autorelease];
NSOpenGLPixelBuffer *pixelBuffer= [[NSOpenGLPixelBuffer alloc] initWithTextureTarget:GL_TEXTURE_RECTANGLE_EXT
textureInternalFormat:GL_RGBA
textureMaxMipMapLevel:0
pixelsWide:width
pixelsHigh:height];

NSOpenGLContext *openGLContext= [[NSOpenGLContext alloc] initWithFormat:format shareContext:nil];
if(pixelBuffer == nil || openGLContext == nil) {
[pool drain];
return 1;
}

[openGLContext setPixelBuffer:pixelBuffer
cubeMapFace:0
mipMapLevel:0
currentVirtualScreen:[openGLContext currentVirtualScreen]];

renderer= [[QCRenderer alloc] initWithOpenGLContext:openGLContext pixelFormat:format file:compositionPath];
}

if(renderer) {
[renderer setValue:image1 forInputKey:@"Image1"];
[renderer setValue:image2 forInputKey:@"Image2"];

if(![renderer renderAtTime:0.0 arguments:nil]) {
[pool drain];
return 1;
}
NSBitmapImageRep *bitmapImage = [renderer createSnapshotImageOfType:@"NSBitmapImageRep"];

if (1){
NSImage *image= (NSImage *)[renderer valueForOutputKey:@"Image"];
if (image) {
bitmapImage= [NSBitmapImageRep imageRepWithData:[image TIFFRepresentation]];
}
}

if(bitmapImage) {
NSDictionary *properties= [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithFloat:1.0], NSImageCompressionFactor,
nil];
NSData *pngImageData= [bitmapImage representationUsingType:NSPNGFileType
properties:properties];
[pngImageData writeToFile:@"./output.png"
atomically:YES];
}
}

[pool drain];
return 0;
}


  • ちなみに青いif分を"if(0){…}"で通らなければViewの画像を出力画像にします.(その際はwidht, heightの値で画像サイズがきまる)
  • ちなみにrenderAtTimeの引数で経過時間を指定しています.



4.composition.qtz(実行時はコマンドと同じフォルダに)

publishしてあるキーについて




結果
> ./commandName imageFilePath1 imageFilePath2

1.入力ファイル(第一, 第二引数)
出力画像サイズをQCRendererの初期化時のサイズに依存しないという点からQuarz Composer Offlineと異なりOutputのPublishで画像を取得してみた.


2.出力ファイル(output.png)



composition.qtzの中身を変えれば当然出力も変わる(変えられる).

0 件のコメント: