将包含一些 CALayers 的 NSView 渲染到 NSImage

问题描述 投票:0回答:5

我有一个 NSView,其中包含一个 NSScrollView,其中包含一个 CALayer 支持的 NSView。我已经尝试了将 NSView 捕获到 NSImage 中的所有常用方法(使用

-dataWithPDFInsideRect
、NSBitmapImageRep 的
-initWithFocusedViewRect
等)。但是,所有这些方法都将 CALayer 支持的 NSView 视为不存在。我已经看过 this StackOverflow 帖子,但这是一个关于仅将 CALayer 树渲染到图像的问题,而不是包含常规 NSView 和图层支持视图的 NSView。

任何帮助表示赞赏,谢谢:)

objective-c cocoa calayer nsview nsimage
5个回答
6
投票

我发现做到这一点的唯一方法是使用 CGWindow API,例如:

CGImageRef cgimg = CGWindowListCreateImage(CGRectZero, kCGWindowListOptionIncludingWindow, [theWindow windowNumber], kCGWindowImageDefault);

然后用

剪掉与您的视图相对应的 CGImage 部分

-imageByCroppingToRect

然后从裁剪后的 CGImage 中制作一个 NSImage。 请注意,如果该窗口的部分内容位于屏幕外,则此操作将无法正常工作。


3
投票

这可以直接将视图绘制到

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

0
投票

您看过《Cocoa 绘图指南》中的建议吗? (“创建位图”)

要直接绘制位图,请使用所需的参数创建一个新的 NSBitmapImageRep 对象,并使用 NSGraphicsContext 的 GraphicsContextWithBitmapImageRep: 方法创建绘图上下文。使新上下文成为当前上下文并绘制。此技术仅在 Mac OS X v10.4 及更高版本中可用。 或者,您可以创建一个 NSImage 对象(或屏幕外窗口),在其中绘制,然后捕获图像内容。所有版本的 Mac OS X 都支持此技术。

这听起来类似于我熟悉的 iOS 解决方案(使用 UIGraphicsBeginImageContext 和 UIGraphicsGetImageFromCurrentImageContext),所以我希望它适用于您的视图。


0
投票

请查看这篇文章的答案:如何将包含核心动画层的视图渲染到位图?

在与你类似的情况下,这种方法对我来说很有效。


0
投票

现代解决方案:

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 绘图,因此可能需要您进行矩形调整。

© www.soinside.com 2019 - 2024. All rights reserved.