Я использую NSView
размещать несколько Базовых Анимаций 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
Однако, когда я использую этот код, Базовые Слои анимации не представляются.
Я занялся расследованиями 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
s для рендеринга к битовому массиву? Я не могу найти пример кода нигде для того, чтобы сделать это, на самом деле я не могу найти пример кода для CARenderer
вообще.
В "Какао - моя девушка" есть отличный пост о записи "Cocoa is my girlfriend". Автор запечатлевает всю анимацию в фильме, но можно использовать ту часть, где он хватается за один кадр
.
Перейдите в раздел "Получение текущего кадра" этой статьи:
http://www.cimgf.com/2009/02/03/record-your-core-animation-animation/
Основная идея:
renderInContext:
Обновление:
Я только что прочитал, что метод renderInContext:
не поддерживает все уровни в Mac OS X 10.5.
Он не работает для следующих классов уровней:
Если вам нужен пример кода, как визуализировать иерархию CALayer в NSImage (или UIImage для iPhone), вы можете посмотреть на CPLayer фреймворка Core Plot и его -метод ImageOfLayer. Фактически мы создали путь рендеринга, не зависящий от обычного процесса -renderInContext:, используемого CALayer, так как обычный способ не сохраняет векторные элементы при генерации PDF-представлений слоев. Поэтому в этом коде вы увидите метод -recursivelyRenderInContext:.
Однако, это не поможет, если вы пытаетесь захватить с любого из типов слоев, упомянутых Weichsel (QCCompositionLayer, CAOpenGLLayer или QTMovieLayer).