我使用NSView
来托管多个Core Animation CALayer
对象。我想要做的是抓取视图当前状态的快照作为位图图像。
使用类似这样的正常NSView
相对简单:
void ClearBitmapImageRep(NSBitmapImageRep* bitmap) {
unsigned char* bitmapData = [bitmap bitmapData];
if (bitmapData != NULL)
bzero(bitmapData, [bitmap bytesPerRow] * [bitmap pixelsHigh]);
}
@implementation NSView (Additions)
- (NSBitmapImageRep*)bitmapImageRepInRect:(NSRect)rect
{
NSBitmapImageRep* imageRep = [self bitmapImageRepForCachingDisplayInRect:rect];
ClearBitmapImageRep(imageRep);
[self cacheDisplayInRect:rect toBitmapImageRep:imageRep];
return imageRep;
}
@end
但是,当我使用此代码时,不会渲染Core Animation图层。
我调查了CARenderer
,因为它似乎做了我需要的事情,但是我无法让它渲染我现有的图层树。我尝试了以下方法:
NSOpenGLPixelFormatAttribute att[] =
{
NSOpenGLPFAWindow,
NSOpenGLPFADoubleBuffer,
NSOpenGLPFAColorSize, 24,
NSOpenGLPFAAlphaSize, 8,
NSOpenGLPFADepthSize, 24,
NSOpenGLPFANoRecovery,
NSOpenGLPFAAccelerated,
0
};
NSOpenGLPixelFormat *pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:att];
NSOpenGLView* openGLView = [[NSOpenGLView alloc] initWithFrame:[self frame] pixelFormat:pixelFormat];
NSOpenGLContext* oglctx = [openGLView openGLContext];
CARenderer* renderer = [CARenderer rendererWithCGLContext:[oglctx CGLContextObj] options:nil];
renderer.layer = myContentLayer;
[renderer render];
NSBitmapImageRep* bitmap = [oglView bitmapImageRepInRect:[oglView bounds]];
然而,当我这样做时,我得到一个例外:
CAContextInvalidLayer -- layer <CALayer: 0x1092ea0> is already attached to a context
我猜这一定是因为图层树托管在我的NSView
中,因此附加到其上下文中。我不明白如何从NSView
分离层树以便将其渲染为位图,在这种情况下创建重复的层树非常重要。
还有其他方法可以让CALayer
呈现给位图吗?我无法在任何地方找到任何示例代码,事实上我根本找不到CARenderer
的任何示例代码。
答案 0 :(得分:15)
关于录制核心动画,有一篇关于“可可是我女朋友”的文章。作者将整个动画捕捉到一部电影中,但你可以使用他抓住一个画面的部分
跳转到本文中的“获取当前帧”部分:
http://www.cimgf.com/2009/02/03/record-your-core-animation-animation/
基本理念是:
renderInContext:
<强>更新强>
我刚才读到,renderInContext:
方法不支持Mac OS X 10.5中的所有类型的图层。
它不适用于以下图层类:
答案 1 :(得分:4)
如果您需要有关如何将CALayer层次结构呈现给NSImage(或iPhone的UIImage)的示例代码,您可以查看Core Plot框架的CPLayer及其-imageOfLayer method。我们实际上创建了一个独立于CALayer使用的正常-renderInContext:进程的渲染路径,因为在生成图层的PDF表示时,常规方法不会保留向量元素。这就是为什么你会在这段代码中看到-recursivelyRenderInContext:方法。
但是,如果您尝试从weichsel(QCCompositionLayer,CAOpenGLLayer或QTMovieLayer)提到的任何图层类型中捕获,这将无法帮助您。