渲染/快照SpriteKit场景到NSImage

pou*_*v23 15 macos cocoa objective-c sprite-kit skview

有谁知道如何"快照"一个完整的SKViewSKScene一个NSImage

我们已经能够使用textureFromNodeAPI SKTexture从节点及其所有子节点创建.但到目前为止,我们无法找到一种方法将图像数据提取为一个NSImage.我们正在构建一个混合Cocoa/ SpriteKit应用程序,我们需要提取场景的小缩略图.

再次,这似乎可以在iOS(获得a UIImage)使用drawViewHierarchyInRect:

UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, scale);
[self drawViewHierarchyInRect:self.bounds afterScreenUpdates:YES];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Run Code Online (Sandbox Code Playgroud)

但如何做到这一点上CocoaNSImage?救命.

ric*_*ter 5

从 OS X 10.11(以及 iOS 9 和 tvOS,但我们会忽略那些,因为你问的是NSImage),SKTexture可以将其内容导出到CGImageRef. 所以textureFromNode你提到的方法现在是工作解决方案的第一步:

SKTexture *texture = [view textureFromNode: view.scene];
NSImage *image = [[NSImage alloc] initWithCGImage: texture.CGImage
                                             size: view.bounds];
Run Code Online (Sandbox Code Playgroud)

请注意sizeinitWithCGImage:您可以CGSizeZero在此处传递参数以使NSImage继承 的像素大小CGImage,但由于您可能正在处理 Retina 显示器,因此您可能需要大小,您可以从视图尺寸中获取该大小。


zzy*_*yzy 0

这是我(在 OSX 上)获取底层渲染图像的尝试...

首先,我进行了子类化SKView,并在其drawRect方法中懒惰地抓取了一个NSBitmapImageRep

if (![self cache])
    [self setCache:[self bitmapImageRepForCachingDisplayInRect:[self visibleRect]]];
Run Code Online (Sandbox Code Playgroud)

然后,我设置一个NSTimer定期尝试将该缓存的内容复制到自定义缩略图视图的方法:

MySKView *sv = .....
NSBitmapImageRep *cache = [sv cache];
if (!cache)
    return;

NSRect srcFrame = NSMakeRect(0,0,[sv frame].size.width,[sv frame].size.height);
NSRect thumbFrame = [[self thumbView] frame];
NSRect thumbRect = NSMakeRect(0,0,thumbFrame.size.width,thumbFrame.size.height);
[sv cacheDisplayInRect:srcFrame toBitmapImageRep:cache];
[[self thumbView] lockFocus];
[cache drawInRect:thumbRect
         fromRect:srcFrame
         operation:NSCompositeCopy
         fraction:1.0
   respectFlipped:YES
            hints:nil];
[[self thumbView] unlockFocus];
Run Code Online (Sandbox Code Playgroud)

没有骰子。我在缩略图视图中看到的都是黑色。

可能出于同样的原因,这都是基于 OpenGL/GPU 的绘图。

这将引导我以某种方式找到所使用的底层 OpenGL 绘图上下文SKView,并在该上下文上执行操作glReadPixels