我有一个 NSView,其中包含一个 NSScrollView,其中包含一个 CALayer 支持的 NSView。我已经尝试了将 NSView 捕获到 NSImage 中的所有常用方法(使用
-dataWithPDFInsideRect
、NSBitmapImageRep 的 -initWithFocusedViewRect
等)。但是,所有这些方法都将 CALayer 支持的 NSView 视为不存在。我已经看过 this StackOverflow 帖子,但这是一个关于仅将 CALayer 树渲染到图像的问题,而不是包含常规 NSView 和图层支持视图的 NSView。
任何帮助表示赞赏,谢谢:)
我发现做到这一点的唯一方法是使用 CGWindow API,例如:
CGImageRef cgimg = CGWindowListCreateImage(CGRectZero, kCGWindowListOptionIncludingWindow, [theWindow windowNumber], kCGWindowImageDefault);
然后用
剪掉与您的视图相对应的 CGImage 部分-imageByCroppingToRect
。
然后从裁剪后的 CGImage 中制作一个 NSImage。 请注意,如果该窗口的部分内容位于屏幕外,则此操作将无法正常工作。
这可以直接将视图绘制到
NSImage
,尽管我还没有尝试过使用图层支持的视图:
NSImage * i = [[NSImage alloc] initWithSize:[view frame].size];
[i lockFocus];
if ([view lockFocusIfCanDrawInContext:[NSGraphicsContext currentContext]]) {
[view displayRectIgnoringOpacity:[view frame] inContext:[NSGraphicsContext currentContext]];
[view unlockFocus];
}
[i unlockFocus];
NSData * d = [i TIFFRepresentation];
[d writeToFile:@"/path/to/my/test.tiff" atomically:YES];
[i release];
您看过《Cocoa 绘图指南》中的建议吗? (“创建位图”)
要直接绘制位图,请使用所需的参数创建一个新的 NSBitmapImageRep 对象,并使用 NSGraphicsContext 的 GraphicsContextWithBitmapImageRep: 方法创建绘图上下文。使新上下文成为当前上下文并绘制。此技术仅在 Mac OS X v10.4 及更高版本中可用。 或者,您可以创建一个 NSImage 对象(或屏幕外窗口),在其中绘制,然后捕获图像内容。所有版本的 Mac OS X 都支持此技术。
这听起来类似于我熟悉的 iOS 解决方案(使用 UIGraphicsBeginImageContext 和 UIGraphicsGetImageFromCurrentImageContext),所以我希望它适用于您的视图。
请查看这篇文章的答案:如何将包含核心动画层的视图渲染到位图?
在与你类似的情况下,这种方法对我来说很有效。
现代解决方案:
let bitmap = hostingView.bitmapImageRepForCachingDisplay(in: pixelRect)!
hostingView.cacheDisplay(in: centeredRect, to: bitmap)
let image = NSImage(cgImage: bitmap.cgImage!, size: pointSize)
确保正确的内容与您的案例相关。对于视网膜来说,
pixelRect
的大小是pointSize
的两倍,并且出于某种原因,在cacheDisplay(in:to:)
中,我们必须传递一个x和y位于视图中心的矩形。我不太擅长 macOS 绘图,因此可能需要您进行矩形调整。