Estoy usando un NSView
para alojar varios objetos de Core Animation CALayer
. Lo que quiero poder hacer es tomar una instantánea del estado actual de la vista como una imagen de mapa de bits.¿Cómo renderizo una vista que contiene capas de animación principal en un mapa de bits?
Esto es relativamente simple, con una normal de NSView
usar algo como esto:
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
Sin embargo, cuando se utiliza este código, las capas de núcleo de animación no se representan.
He investigado CARenderer
, ya que parece hacer lo que necesito, sin embargo, no puedo hacer que represente mi árbol de capas existente. He intentado lo siguiente:
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]];
Sin embargo, cuando hago esto me da una excepción:
CAContextInvalidLayer -- layer <CALayer: 0x1092ea0> is already attached to a context
supongo que esto debe ser porque el árbol de capas se encuentra alojado en mi NSView
y por lo tanto, adjunto a su contexto. No entiendo cómo puedo separar el árbol de capas del NSView
para convertirlo en un mapa de bits, y no es trivial en este caso crear un árbol de capas duplicadas.
¿Hay alguna otra forma de obtener el CALayer
para renderizar en un mapa de bits? No puedo encontrar ningún código de muestra en ninguna parte para hacer esto, de hecho, no puedo encontrar ningún código de muestra para CARenderer
.
Muchas gracias, esto es exactamente lo que necesitaba y funciona perfectamente. Ojalá hubiera notado el método '-renderInContext:' anterior, 'CARenderer' me llevó por el camino del jardín. –
¿Funciona esto para los elementos fuera de pantalla? P.ej. mi CALayer contiene algunos elementos que aún no están en el marco de la vista, pero necesito desplazarme para verlos. – Tudorizer
¿Alguien ha conseguido que esto funcione con una animación iniciada con [UIView animateWithDuration: ...]? A mi no me sirvió. – Isak