【问题标题】:Render/Snapshot SpriteKit Scene to NSImage将 SpriteKit 场景渲染/快照到 NSImage
【发布时间】:2014-01-07 00:35:08
【问题描述】:

有谁知道如何将完整的SKViewSKScene“快照”到NSImage 中?

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

同样,这在 iOS 上似乎是可能的(获得UIImage)使用drawViewHierarchyInRect

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

但是如何在 CocoaNSImage 上执行此操作?帮助。

【问题讨论】:

标签: objective-c macos cocoa sprite-kit skview


【解决方案1】:

从 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];

注意size 参数到initWithCGImage:,您可以将CGSizeZero 传递到那里以使NSImage 继承CGImage像素 大小,但是因为您可能正在处理一个 Retina 显示器,您可能需要 point 尺寸,您可以从视图尺寸中获得。

【讨论】:

    【解决方案2】:

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

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

    if (![self cache])
        [self setCache:[self bitmapImageRepForCachingDisplayInRect:[self visibleRect]]];
    

    然后我设置了一个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];
    

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

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

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

    【讨论】:

    • 标题说你不能继承 SKView……我在想也许在更新:方法?
    【解决方案3】:

    目前还不能从 SKTexture 直接访问图像数据。您可以在屏幕外场景中显示节点并捕获视图层次结构。我在 iOS 中使用此代码作为参考:

    class func imageFromNode(node : SKNode, inScene scene: SKScene) -> UIImage? {
        if let texture = scene.view?.textureFromNode(node) {
            let view = SKView(frame: CGRect(origin: CGPointZero, size: texture.size()))
            view.allowsTransparency = true
            view.backgroundColor = SKColor.clearColor()
    
            let scene = SKScene(size: view.bounds.size)
            scene.view?.allowsTransparency = true
            scene.backgroundColor = SKColor.clearColor()
    
            let sprite  = SKSpriteNode(texture: texture)
            sprite.position = CGPoint(x: CGRectGetMidX(view.frame), y: CGRectGetMidY(view.frame))
            scene.addChild(sprite)
            view.presentScene(scene)
            UIGraphicsBeginImageContextWithOptions(view.bounds.size, false, 0.0)
            view.drawViewHierarchyInRect(view.bounds, afterScreenUpdates: true)
            let image = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            return image
        }
        return nil
    }
    

    【讨论】:

      【解决方案4】:

      SKViewUIView 的子类,因此您应该能够在 CoreGraphics 上下文中绘制视图层,然后从上下文中获取图像。

      看看使用view.layer.drawInContext

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-10-25
        • 2015-05-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多