从 CALayer 或 NSView 获取图像 (swift 3)
Get Image from CALayer or NSView (swift 3)
我正在寻找一种方法来渲染 CALayer 或 NSView 并取回 NSImage。
我有一个自定义 class,它是 NSView 的子class。
一开始我只是简单的做了一个渐变图层覆盖NSView。
class ContentView: NSView {
override func draw(_ dirtyRect: NSRect) {
fillGradientLayer()
}
func fillGradientLayer() {
gradientLayer = CAGradientLayer()
gradientLayer.colors = [#colorLiteral(red: 0, green: 0.9909763549, blue: 0.7570167824, alpha: 1),#colorLiteral(red: 0, green: 0.4772562545, blue: 1, alpha: 1)].map({return [=11=].cgColor})
gradientLayer.startPoint = CGPoint(x: 0, y: 0.5)
gradientLayer.endPoint = CGPoint(x: 1, y: 0.5)
gradientLayer.frame = self.frame.insetBy(dx: margin, dy: margin)
gradientLayer.zPosition = 2
gradientLayer.name = "gradientLayer"
gradientLayer.contentsScale = (NSScreen.main()?.backingScaleFactor)!
self.layer?.addSublayer(gradientLayer)
}
}
有时我想从 CALayers 获取 NSImage(或 CGImage)。
我在网上找了一些样本,把它们变成了这样:
extension CALayer {
func getBitmapImage() -> NSImage {
let btmpImgRep = NSBitmapImageRep(bitmapDataPlanes: nil, pixelsWide: Int(self.frame.width), pixelsHigh: Int(self.frame.height), bitsPerSample: 8, samplesPerPixel: 4, hasAlpha: true, isPlanar: false, colorSpaceName: NSDeviceRGBColorSpace, bytesPerRow: 0, bitsPerPixel: 0)
let image: NSImage = NSImage(size: self.frame.size)
image.lockFocus()
let ctx = NSGraphicsContext(bitmapImageRep: btmpImgRep!)
let cgCtxt = ctx!.cgContext
self.render(in: cgCtxt)
cgCtxt.draw(layer: CGLayer, in: CGRect)
image.unlockFocus()
return image
}
}
第一个问题是 draw(layer: CGLayer, in: CGRect) 方法需要 CGLayer 而不是 CALayer。
其次,我不知道我最终得到的代码是否最终会渲染我的图层,或者我做错了什么。
感谢您的帮助。
已编辑:
从 CALayer 获取 CGImage 的解决方案。
extension CALayer {
func getBitmapImage() -> NSImage {
let btmpImgRep =
NSBitmapImageRep(bitmapDataPlanes: nil, pixelsWide: Int(self.frame.width), pixelsHigh: Int(self.frame.height), bitsPerSample: 8, samplesPerPixel: 4, hasAlpha: true, isPlanar: false, colorSpaceName: NSDeviceRGBColorSpace, bytesPerRow: 0, bitsPerPixel: 32)
let ctx = NSGraphicsContext(bitmapImageRep: btmpImgRep!)
let cgContext = ctx!.cgContext
self.render(in: cgContext)
let cgImage = cgContext.makeImage()
let nsimage = NSImage(cgImage: cgImage!, size: CGSize(width: self.frame.width, height: self.frame.height))
return nsimage
}
}
如何从 NSView 获取 NSImage 在下面的回答中。
P.S。我不太了解 NSBitmapImageRep 属性,所以这部分可能是错误的。
这里有一些 NSView
选项:
extension NSView {
/// Get `NSImage` representation of the view.
///
/// - Returns: `NSImage` of view
func image() -> NSImage {
let imageRepresentation = bitmapImageRepForCachingDisplay(in: bounds)!
cacheDisplay(in: bounds, to: imageRepresentation)
return NSImage(cgImage: imageRepresentation.cgImage!, size: bounds.size)
}
}
或
extension NSView {
/// Get `Data` representation of the view.
///
/// - Parameters:
/// - fileType: The format of file. Defaults to PNG.
/// - properties: A dictionary that contains key-value pairs specifying image properties.
/// - Returns: `Data` for image.
func data(using fileType: NSBitmapImageRep.FileType = .png, properties: [NSBitmapImageRep.PropertyKey: Any] = [:]) -> Data {
let imageRepresentation = bitmapImageRepForCachingDisplay(in: bounds)!
cacheDisplay(in: bounds, to: imageRepresentation)
return imageRepresentation.representation(using: fileType, properties: properties)!
}
}
一些CALayer
选项:
extension CALayer {
/// Get `NSImage` representation of the layer.
///
/// - Returns: `NSImage` of the layer.
func image() -> NSImage {
let width = Int(bounds.width * contentsScale)
let height = Int(bounds.height * contentsScale)
let imageRepresentation = NSBitmapImageRep(bitmapDataPlanes: nil, pixelsWide: width, pixelsHigh: height, bitsPerSample: 8, samplesPerPixel: 4, hasAlpha: true, isPlanar: false, colorSpaceName: .deviceRGB, bytesPerRow: 0, bitsPerPixel: 0)!
imageRepresentation.size = bounds.size
let context = NSGraphicsContext(bitmapImageRep: imageRepresentation)!
render(in: context.cgContext)
return NSImage(cgImage: imageRepresentation.cgImage!, size: bounds.size)
}
}
或
extension CALayer {
/// Get `Data` representation of the layer.
///
/// - Parameters:
/// - fileType: The format of file. Defaults to PNG.
/// - properties: A dictionary that contains key-value pairs specifying image properties.
///
/// - Returns: `Data` for image.
func data(using fileType: NSBitmapImageRep.FileType = .png, properties: [NSBitmapImageRep.PropertyKey: Any] = [:]) -> Data {
let width = Int(bounds.width * contentsScale)
let height = Int(bounds.height * contentsScale)
let imageRepresentation = NSBitmapImageRep(bitmapDataPlanes: nil, pixelsWide: width, pixelsHigh: height, bitsPerSample: 8, samplesPerPixel: 4, hasAlpha: true, isPlanar: false, colorSpaceName: .deviceRGB, bytesPerRow: 0, bitsPerPixel: 0)!
imageRepresentation.size = bounds.size
let context = NSGraphicsContext(bitmapImageRep: imageRepresentation)!
render(in: context.cgContext)
return imageRepresentation.representation(using: fileType, properties: properties)!
}
}
我正在寻找一种方法来渲染 CALayer 或 NSView 并取回 NSImage。
我有一个自定义 class,它是 NSView 的子class。 一开始我只是简单的做了一个渐变图层覆盖NSView。
class ContentView: NSView {
override func draw(_ dirtyRect: NSRect) {
fillGradientLayer()
}
func fillGradientLayer() {
gradientLayer = CAGradientLayer()
gradientLayer.colors = [#colorLiteral(red: 0, green: 0.9909763549, blue: 0.7570167824, alpha: 1),#colorLiteral(red: 0, green: 0.4772562545, blue: 1, alpha: 1)].map({return [=11=].cgColor})
gradientLayer.startPoint = CGPoint(x: 0, y: 0.5)
gradientLayer.endPoint = CGPoint(x: 1, y: 0.5)
gradientLayer.frame = self.frame.insetBy(dx: margin, dy: margin)
gradientLayer.zPosition = 2
gradientLayer.name = "gradientLayer"
gradientLayer.contentsScale = (NSScreen.main()?.backingScaleFactor)!
self.layer?.addSublayer(gradientLayer)
}
}
有时我想从 CALayers 获取 NSImage(或 CGImage)。 我在网上找了一些样本,把它们变成了这样:
extension CALayer {
func getBitmapImage() -> NSImage {
let btmpImgRep = NSBitmapImageRep(bitmapDataPlanes: nil, pixelsWide: Int(self.frame.width), pixelsHigh: Int(self.frame.height), bitsPerSample: 8, samplesPerPixel: 4, hasAlpha: true, isPlanar: false, colorSpaceName: NSDeviceRGBColorSpace, bytesPerRow: 0, bitsPerPixel: 0)
let image: NSImage = NSImage(size: self.frame.size)
image.lockFocus()
let ctx = NSGraphicsContext(bitmapImageRep: btmpImgRep!)
let cgCtxt = ctx!.cgContext
self.render(in: cgCtxt)
cgCtxt.draw(layer: CGLayer, in: CGRect)
image.unlockFocus()
return image
}
}
第一个问题是 draw(layer: CGLayer, in: CGRect) 方法需要 CGLayer 而不是 CALayer。
其次,我不知道我最终得到的代码是否最终会渲染我的图层,或者我做错了什么。
感谢您的帮助。
已编辑: 从 CALayer 获取 CGImage 的解决方案。
extension CALayer {
func getBitmapImage() -> NSImage {
let btmpImgRep =
NSBitmapImageRep(bitmapDataPlanes: nil, pixelsWide: Int(self.frame.width), pixelsHigh: Int(self.frame.height), bitsPerSample: 8, samplesPerPixel: 4, hasAlpha: true, isPlanar: false, colorSpaceName: NSDeviceRGBColorSpace, bytesPerRow: 0, bitsPerPixel: 32)
let ctx = NSGraphicsContext(bitmapImageRep: btmpImgRep!)
let cgContext = ctx!.cgContext
self.render(in: cgContext)
let cgImage = cgContext.makeImage()
let nsimage = NSImage(cgImage: cgImage!, size: CGSize(width: self.frame.width, height: self.frame.height))
return nsimage
}
}
如何从 NSView 获取 NSImage 在下面的回答中。
P.S。我不太了解 NSBitmapImageRep 属性,所以这部分可能是错误的。
这里有一些 NSView
选项:
extension NSView {
/// Get `NSImage` representation of the view.
///
/// - Returns: `NSImage` of view
func image() -> NSImage {
let imageRepresentation = bitmapImageRepForCachingDisplay(in: bounds)!
cacheDisplay(in: bounds, to: imageRepresentation)
return NSImage(cgImage: imageRepresentation.cgImage!, size: bounds.size)
}
}
或
extension NSView {
/// Get `Data` representation of the view.
///
/// - Parameters:
/// - fileType: The format of file. Defaults to PNG.
/// - properties: A dictionary that contains key-value pairs specifying image properties.
/// - Returns: `Data` for image.
func data(using fileType: NSBitmapImageRep.FileType = .png, properties: [NSBitmapImageRep.PropertyKey: Any] = [:]) -> Data {
let imageRepresentation = bitmapImageRepForCachingDisplay(in: bounds)!
cacheDisplay(in: bounds, to: imageRepresentation)
return imageRepresentation.representation(using: fileType, properties: properties)!
}
}
一些CALayer
选项:
extension CALayer {
/// Get `NSImage` representation of the layer.
///
/// - Returns: `NSImage` of the layer.
func image() -> NSImage {
let width = Int(bounds.width * contentsScale)
let height = Int(bounds.height * contentsScale)
let imageRepresentation = NSBitmapImageRep(bitmapDataPlanes: nil, pixelsWide: width, pixelsHigh: height, bitsPerSample: 8, samplesPerPixel: 4, hasAlpha: true, isPlanar: false, colorSpaceName: .deviceRGB, bytesPerRow: 0, bitsPerPixel: 0)!
imageRepresentation.size = bounds.size
let context = NSGraphicsContext(bitmapImageRep: imageRepresentation)!
render(in: context.cgContext)
return NSImage(cgImage: imageRepresentation.cgImage!, size: bounds.size)
}
}
或
extension CALayer {
/// Get `Data` representation of the layer.
///
/// - Parameters:
/// - fileType: The format of file. Defaults to PNG.
/// - properties: A dictionary that contains key-value pairs specifying image properties.
///
/// - Returns: `Data` for image.
func data(using fileType: NSBitmapImageRep.FileType = .png, properties: [NSBitmapImageRep.PropertyKey: Any] = [:]) -> Data {
let width = Int(bounds.width * contentsScale)
let height = Int(bounds.height * contentsScale)
let imageRepresentation = NSBitmapImageRep(bitmapDataPlanes: nil, pixelsWide: width, pixelsHigh: height, bitsPerSample: 8, samplesPerPixel: 4, hasAlpha: true, isPlanar: false, colorSpaceName: .deviceRGB, bytesPerRow: 0, bitsPerPixel: 0)!
imageRepresentation.size = bounds.size
let context = NSGraphicsContext(bitmapImageRep: imageRepresentation)!
render(in: context.cgContext)
return imageRepresentation.representation(using: fileType, properties: properties)!
}
}