2011年8月20日土曜日

Quartz Composer / Automator / AutomatorのパッチでQCRender関連のナンカを実装してみた

動機
これをやったのでこれ的なQCRenderネタをやってみようかと安易に思った('Quartz コンポジションフィルタをイメージに適用'ってパッチが既にありますが).


やってみた
0.プロジェクトの作成
プロジェクトの修正等はこちらを参照下さい
xibのFile's Ownerのクラスも上記と同じクラス名で修正する(こちらの3.xibを編集を参照のこと).
OpenGLとQuartzのframeworkを追加した.


1.コード

#import <Automator/AMBundleAction.h>
#import <Quartz/Quartz.h>

@interface QuartzComposer : AMBundleAction

- (id)runWithInput:(id)input fromAction:(AMAction *)anAction error:(NSDictionary **)errorInfo;

- (IBAction)openQTZ:(id)sender;

@end



#import "QuartzComposer.h"

@implementation QuartzComposer
- (IBAction)openQTZ:(id)sender
{
NSString *compositionPath= [[NSBundle bundleForClass:[self class]] pathForResource:@"composition" ofType:@"qtz"];
[[NSWorkspace sharedWorkspace] openFile:compositionPath withApplication:@"Quartz Composer"];
}

- (id)runWithInput:(id)input fromAction:(AMAction *)anAction error:(NSDictionary **)errorInfo
{
NSUInteger width= 16;
NSUInteger height= 16;
NSString *compositionPath= [[NSBundle bundleForClass:[self class]] pathForResource:@"composition" ofType:@"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) {
NSLog(@"no buffer or no context");
return nil;
}

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

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

NSMutableArray *outputPaths= [NSMutableArray array];
if(renderer) {
NSMutableArray *inputPaths= [NSMutableArray array];
if ([input isKindOfClass:[NSArray class]]) {
[inputPaths addObjectsFromArray:input];
}
else if ([input isKindOfClass:[NSString class]]) {
[inputPaths addObject:input];
}
int i;
for(i=0;i<[inputPaths count];i++) {
NSString *inputPath= [inputPaths objectAtIndex:i];
NSImage *inputImage= [[[NSImage alloc] initWithContentsOfFile:inputPath] autorelease];
[renderer setValue:inputImage forInputKey:@"InputImage"];

if(![renderer renderAtTime:0.0 arguments:nil]) {
NSLog(@"no rendering");
return nil;
}
[renderer createSnapshotImageOfType:@"NSBitmapImageRep"];

NSImage *image= (NSImage *)[renderer valueForOutputKey:@"OutputImage"];
NSBitmapImageRep *bitmapImage= [NSBitmapImageRep imageRepWithData:[image TIFFRepresentation]];
if(bitmapImage) {
char *tempNameBytes = tempnam([NSTemporaryDirectory() fileSystemRepresentation], "QCComposition_Result_");
NSString *tempName = [[[NSString alloc] initWithBytesNoCopy:tempNameBytes
length:strlen(tempNameBytes)
encoding:NSUTF8StringEncoding
freeWhenDone:YES] autorelease];
NSString *outputPath= [tempName stringByAppendingPathExtension:@"png"];


NSDictionary *properties= [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithFloat:1.0], NSImageCompressionFactor,
nil];
NSData *pngImageData= [bitmapImage representationUsingType:NSPNGFileType
properties:properties];

[pngImageData writeToFile:outputPath
atomically:YES];
[outputPaths addObject:outputPath];
}
}
}
else {
NSLog(@"no render");
}

return outputPaths;
}

@end


2.composition.qtzを作成する
Quartz Composerで作成する.この際にInputImageというPublished InputとOutputImageというPublished Outputを用意する.


3.Supporting Files(リソース)にコンポジション(composition.qtz)を加える
Build PhasesのCopy Bundle Resourcesに含まれていること.


4.Viewまわり
xlbにボタンを配置して(IBAction)openQTZ:に繋ぐ.


あとはBuildして配置(~/Library/Automator/下).



結果


Motion Blurなのでこんな感じ.

0 件のコメント: