Cannot create a Screenshot of a SCNView

后端 未结 3 601
南笙
南笙 2020-12-17 03:46

Is it possible to get a screenshot of an SCNView? I\'m trying with the below code, but it always comes out white...

NSRect bounds = [window.contentView bound         


        
3条回答
  •  隐瞒了意图╮
    2020-12-17 04:24

    SceneKit uses an OpenGL context to draw. You can't turn that into PDF data as easily as a Quartz based context (as used by "normal" AppKit views).
    But you can grab the rasterized bitmap data from OpenGL:

    - (IBAction)takeShot:(id)sender
    {
        NSString* path = @"/Users/weichsel/Desktop/test.tiff";
        NSImage* image = [self imageFromSceneKitView:self.scene];
        BOOL didWrite = [[image TIFFRepresentation] writeToFile:path atomically:YES];
        NSLog(@"Did write:%d", didWrite);
    }
    
    - (NSImage*)imageFromSceneKitView:(SCNView*)sceneKitView
    {
        NSInteger width = sceneKitView.bounds.size.width * self.scene.window.backingScaleFactor;
        NSInteger height = sceneKitView.bounds.size.height * self.scene.window.backingScaleFactor;
        NSBitmapImageRep* imageRep=[[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
                                                                           pixelsWide:width
                                                                           pixelsHigh:height
                                                                        bitsPerSample:8
                                                                      samplesPerPixel:4
                                                                             hasAlpha:YES
                                                                             isPlanar:NO
                                                                       colorSpaceName:NSCalibratedRGBColorSpace
                                                                          bytesPerRow:width*4
                                                                         bitsPerPixel:4*8];
        [[sceneKitView openGLContext] makeCurrentContext];
        glReadPixels(0, 0, (int)width, (int)height, GL_RGBA, GL_UNSIGNED_BYTE, [imageRep bitmapData]);
        [NSOpenGLContext clearCurrentContext];
        NSImage* outputImage = [[NSImage alloc] initWithSize:NSMakeSize(width, height)];
        [outputImage addRepresentation:imageRep];
        NSImage* flippedImage = [NSImage imageWithSize:NSMakeSize(width, height) flipped:YES drawingHandler:^BOOL(NSRect dstRect) {
            [imageRep drawInRect:dstRect];
            return YES;
        }];
        return flippedImage;
    }
    

    Don't forget to link OpenGL.framework and #import "OpenGL/gl.h"

    Update
    SceneKit seems to use a flipped context. I added some code to fix the upside-down image.

    Update 2
    Updated code to take the backing scale factor into account (for retina displays)

提交回复
热议问题