Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

cocoa: how to render view to image?

Tags:

macos

cocoa

I want to know is there any method to render a view to image? just like a screenshot, but I can specify any view to that method. I know how to do it in ios. Saving view content, but how can I do it in mac os ?

like image 202
NOrder Avatar asked Aug 14 '12 08:08

NOrder


2 Answers

There are several ways, but non of them works perfect. Many problems are connected with Layer Backed views.

if you don't have layer backing or hosting views you can use this code:

    NSData* data = [mainView dataWithPDFInsideRect:[mainView bounds]];
    NSImage *img = [[NSImage alloc] initWithData:data];

if you work with layer based views:

till 10.8 the best way for me was

        NSSize mySize = mapImage.bounds.size;
        NSSize imgSize = NSMakeSize( mySize.width, mySize.height );
        NSBitmapImageRep *bir = [mapImage bitmapImageRepForCachingDisplayInRect:[mapImage bounds]];
        [bir setSize:imgSize];
        [mapImage cacheDisplayInRect:[mapImage bounds] toBitmapImageRep:bir];
        caheImg = [[NSImage alloc]initWithSize:imgSize];
        [caheImg addRepresentation:bir];

but in 10.8 bitmapImageRepForCachingDisplayInRect stopped working with Layer Backed views.

there is an option to make a screenshot of your screen and cut out your view:

+ (NSImage*) screenCacheImageForView:(NSView*)aView
{
    NSRect originRect = [aView convertRect:[aView bounds] toView:[[aView window] contentView]];

    NSRect rect = originRect;
    rect.origin.y = 0;
    rect.origin.x += [aView window].frame.origin.x;
    rect.origin.y += [[aView window] screen].frame.size.height - [aView window].frame.origin.y - [aView window].frame.size.height;
    rect.origin.y += [aView window].frame.size.height - originRect.origin.y - originRect.size.height;

    CGImageRef cgimg = CGWindowListCreateImage(rect,
                                           kCGWindowListOptionIncludingWindow,
                                           (CGWindowID)[[aView window] windowNumber],
                                           kCGWindowImageDefault);
    return [[NSImage alloc] initWithCGImage:cgimg size:[aView bounds].size];
}
like image 82
Remizorrr Avatar answered Oct 21 '22 15:10

Remizorrr


I'm using this code in my app, which works great.

However, if I drag the app to a secondary monitor the screen capture is thrown out and I get the wrong rect captured.

The following code fixes that issue (I've also removed some redundant maths from the calculation where a field was being subtracted and then added) in case anyone comes across this in the future:

NSRect originRect = [aView convertRect:[aView bounds] toView:[[aView window] contentView]];

NSArray *screens = [NSScreen screens];
NSScreen *primaryScreen = [screens objectAtIndex:0];

NSRect rect = originRect;
rect.origin.y = 0;
rect.origin.x += [aView window].frame.origin.x;
rect.origin.y = primaryScreen.frame.size.height - [aView window].frame.origin.y - originRect.origin.y - originRect.size.height;
like image 38
Darren Wheatley Avatar answered Oct 21 '22 16:10

Darren Wheatley