2011年7月29日金曜日

Quartz Composer / WebViewの画像を取得するパッチ

追記(2011/07/31): 修正版を書きました



やってみた
WebKit.frameworkを追加

WebViewPlugIn.h

#import <Quartz/Quartz.h>
#import <Webkit/WebKit.h>

@interface WebViewPlugIn : QCPlugIn {
@private
WebView *aWebView;
NSString *oldURL;
NSBitmapImageRep *aBitmapImageRep;
}

@property(assign) NSString *inputURL;
@property(assign) id outputImage;
@end

WebViewPlugIn.m

#import <OpenGL/CGLMacro.h>
#import "WebViewPlugIn.h"

#define kQCPlugIn_Name @"WebView"
#define kQCPlugIn_Description @"WebView description"

@implementation WebViewPlugIn
@dynamic inputURL;
@dynamic outputImage;
+ (NSDictionary *)attributes
{
return [NSDictionary dictionaryWithObjectsAndKeys:
kQCPlugIn_Name, QCPlugInAttributeNameKey,
kQCPlugIn_Description, QCPlugInAttributeDescriptionKey,
nil];
}

+ (NSDictionary *)attributesForPropertyPortWithKey:(NSString *)key
{
return nil;
}

+ (QCPlugInExecutionMode)executionMode
{
return kQCPlugInExecutionModeProvider;
}

+ (QCPlugInTimeMode)timeMode
{
return kQCPlugInTimeModeIdle;
}

- (id)init
{
self = [super init];
if (self) {
NSRect r= NSMakeRect(0,0, 16, 16);
aWebView= [[WebView alloc] initWithFrame:r
frameName:nil
groupName:nil];
NSWindow *w= [[NSWindow alloc] init];
[w setContentView:aWebView];
[w setFrame:r display:YES];
[aWebView setFrameLoadDelegate:self];
}
return self;
}
- (void)finalize
{
[super finalize];
}
- (void)dealloc
{
[aWebView release];
[oldURL release];
[super dealloc];
}
@end
@implementation WebViewPlugIn (Execution)
- (BOOL)startExecution:(id <QCPlugInContext>)context
{
return YES;
}
- (void)enableExecution:(id <QCPlugInContext>)context
{
}
static void _BufferReleaseCallback(const void* address, void* info)
{
free(CGBitmapContextGetData((CGContextRef)info));
CGContextRelease(info);
}
- (BOOL)execute:(id <QCPlugInContext>)context atTime:(NSTimeInterval)time withArguments:(NSDictionary *)arguments
{
if (![oldURL isEqualToString:self.inputURL]) {
[aWebView setMainFrameURL:self.inputURL];
[oldURL release];
oldURL= [self.inputURL retain];
}
if (aBitmapImageRep!=nil) {
NSSize size= [aBitmapImageRep size];
id provider= [[context outputImageProviderFromBufferWithPixelFormat:QCPlugInPixelFormatBGRA8
pixelsWide:size.width
pixelsHigh:size.height
baseAddress:[aBitmapImageRep bitmapData]
bytesPerRow:[aBitmapImageRep bytesPerRow]
releaseCallback:_BufferReleaseCallback
releaseContext:NULL
colorSpace:[context colorSpace]
shouldColorMatch:YES]
retain];
if(provider == nil)
return NO;
self.outputImage = provider;
}
else {
self.outputImage= nil;
}
return YES;
}
- (void)disableExecution:(id <QCPlugInContext>)context
{
}
- (void)stopExecution:(id <QCPlugInContext>)context
{
}
@end
@implementation WebViewPlugIn (WebView)
- (void)webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame
{
NSView *view = [[[aWebView mainFrame] frameView] documentView];
NSSize size= [view bounds].size;
size.width+= (4-((NSUInteger)size.width)%4);
[[view window] setContentSize:size];
[aBitmapImageRep release];
[view lockFocus];
aBitmapImageRep = [[NSBitmapImageRep alloc] initWithFocusedViewRect:[view bounds]];
[view unlockFocus];
}
@end

bytesPerRowの値は16で割り切れないと駄目なんだって.
1pixelで4byte(QCPlugInPixelFormatBGRA8)だから'4-(width%4)'を加えてみた.
これだと4で割り切れたとしても無駄に4pixel増えちゃうけど.


結果
Editor



View( ここを表示したもの )


0 件のコメント: