I'm trying to make a custom animation for replacing an NSView
with another.
For that reason I need to get an image of the NSView
before it appears on the screen.
The view may contain layers and NSOpenGLView
subviews, and therefore standard options like initWithFocusedViewRect
and bitmapImageRepForCachingDisplayInRect
do not work well in this case (they layers or OpenGL content well in my experiments).
I am looking for something like CGWindowListCreateImage
, that is able to "capture" an offline NSWindow
including layers and OpenGL content.
Any suggestions?
I created a category for this:
@implementation NSView (PecuniaAdditions)
/**
* Returns an offscreen view containing all visual elements of this view for printing,
* including CALayer content. Useful only for views that are layer-backed.
*/
- (NSView*)printViewForLayerBackedView;
{
NSRect bounds = self.bounds;
int bitmapBytesPerRow = 4 * bounds.size.width;
CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
CGContextRef context = CGBitmapContextCreate (NULL,
bounds.size.width,
bounds.size.height,
8,
bitmapBytesPerRow,
colorSpace,
kCGImageAlphaPremultipliedLast);
CGColorSpaceRelease(colorSpace);
if (context == NULL)
{
NSLog(@"getPrintViewForLayerBackedView: Failed to create context.");
return nil;
}
[[self layer] renderInContext: context];
CGImageRef img = CGBitmapContextCreateImage(context);
NSImage* image = [[NSImage alloc] initWithCGImage: img size: bounds.size];
NSImageView* canvas = [[NSImageView alloc] initWithFrame: bounds];
[canvas setImage: image];
CFRelease(img);
CFRelease(context);
return canvas;
}
@end
This code is primarily for printing NSViews which contain layered child views. Might help you too.