Does anyone know how to "snapshot" a complete SKView
or SKScene
into an NSImage
?
有谁知道如何将完整的SKView或SKScene“快照”成NSImage?
We have been able to use the textureFromNode
API to create an SKTexture
from a node and all its children. But so far we can't figure out a way to extract the image data into say an NSImage
. We are building a mixed Cocoa
/ SpriteKit
app where we need to extract small thumbnails of scenes.
我们已经能够使用textureFromNode API从节点及其所有子节点创建SKTexture。但到目前为止,我们无法找到将图像数据提取为NSImage的方法。我们正在构建一个混合的Cocoa / SpriteKit应用程序,我们需要提取场景的小缩略图。
Again, this seems possible on iOS (to get a UIImage
) using drawViewHierarchyInRect
:
再次,这似乎可以使用drawViewHierarchyInRect在iOS上(获取UIImage):
UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, scale);
[self drawViewHierarchyInRect:self.bounds afterScreenUpdates:YES];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
But how to do this on Cocoa
with NSImage
? Help.
但是如何使用NSImage在Cocoa上执行此操作?帮帮我。
4 个解决方案
#1
3
As of OS X 10.11 (and iOS 9 and tvOS, but we'll ignore those since you're asking about NSImage
), SKTexture
can export its contents to a CGImageRef
. So the textureFromNode
approach you mention is now the first step in a working solution:
从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];
Note the size
parameter to initWithCGImage:
you can pass CGSizeZero
there to make the NSImage
inherit the pixel size of the CGImage
, but since you might be dealing with a Retina Display you probably want the point size, which you can get from the view dimensions.
请注意initWithCGImage的size参数:您可以在那里传递CGSizeZero以使NSImage继承CGImage的像素大小,但由于您可能正在处理Retina显示,您可能需要点大小,您可以从视图维度获得。
#2
1
There's no direct access to the image data from a SKTexture yet. You can present the node in a offscreen scene and capture the view hierarchy. I use this code in iOS for reference:
目前还无法直接访问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
}
#3
0
Here was my attempt (on OSX) to scoop the underlying rendered image...
这是我尝试(在OSX上)挖掘底层渲染图像...
First, I subclassed SKView
and in its drawRect
method lazily grabbed an NSBitmapImageRep
首先,我将SKView子类化,并在其drawRect方法中懒洋洋地抓取了一个NSBitmapImageRep
if (![self cache])
[self setCache:[self bitmapImageRepForCachingDisplayInRect:[self visibleRect]]];
I then set up an NSTimer
which would periodically attempt to copy the contents of that cache to a custom thumbnail view:
然后我设置了一个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];
No dice. All I get in my thumbNail view is black.
没有骰子。我进入thumbNail视图的所有内容都是黑色的。
Likely for the same reason that this is all OpenGL/GPU-based drawing.
可能出于同样的原因,这是所有基于OpenGL / GPU的绘图。
That would lead me in the direction of somehow finding the underlying OpenGL drawing context used by SKView
and doing a glReadPixels
on that context.
这将导致我以某种方式找到SKView使用的基础OpenGL绘图上下文并在该上下文上执行glReadPixels。
#4
0
SKView
is a UIView
subclass, so you should be able to draw the view's layer in a CoreGraphics context, and then get the image from the context.
SKView是一个UIView子类,因此您应该能够在CoreGraphics上下文中绘制视图的图层,然后从上下文中获取图像。
Look at using view.layer.drawInContext
.
看看使用view.layer.drawInContext。
#1
3
As of OS X 10.11 (and iOS 9 and tvOS, but we'll ignore those since you're asking about NSImage
), SKTexture
can export its contents to a CGImageRef
. So the textureFromNode
approach you mention is now the first step in a working solution:
从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];
Note the size
parameter to initWithCGImage:
you can pass CGSizeZero
there to make the NSImage
inherit the pixel size of the CGImage
, but since you might be dealing with a Retina Display you probably want the point size, which you can get from the view dimensions.
请注意initWithCGImage的size参数:您可以在那里传递CGSizeZero以使NSImage继承CGImage的像素大小,但由于您可能正在处理Retina显示,您可能需要点大小,您可以从视图维度获得。
#2
1
There's no direct access to the image data from a SKTexture yet. You can present the node in a offscreen scene and capture the view hierarchy. I use this code in iOS for reference:
目前还无法直接访问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
}
#3
0
Here was my attempt (on OSX) to scoop the underlying rendered image...
这是我尝试(在OSX上)挖掘底层渲染图像...
First, I subclassed SKView
and in its drawRect
method lazily grabbed an NSBitmapImageRep
首先,我将SKView子类化,并在其drawRect方法中懒洋洋地抓取了一个NSBitmapImageRep
if (![self cache])
[self setCache:[self bitmapImageRepForCachingDisplayInRect:[self visibleRect]]];
I then set up an NSTimer
which would periodically attempt to copy the contents of that cache to a custom thumbnail view:
然后我设置了一个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];
No dice. All I get in my thumbNail view is black.
没有骰子。我进入thumbNail视图的所有内容都是黑色的。
Likely for the same reason that this is all OpenGL/GPU-based drawing.
可能出于同样的原因,这是所有基于OpenGL / GPU的绘图。
That would lead me in the direction of somehow finding the underlying OpenGL drawing context used by SKView
and doing a glReadPixels
on that context.
这将导致我以某种方式找到SKView使用的基础OpenGL绘图上下文并在该上下文上执行glReadPixels。
#4
0
SKView
is a UIView
subclass, so you should be able to draw the view's layer in a CoreGraphics context, and then get the image from the context.
SKView是一个UIView子类,因此您应该能够在CoreGraphics上下文中绘制视图的图层,然后从上下文中获取图像。
Look at using view.layer.drawInContext
.
看看使用view.layer.drawInContext。