从 CALayer 或 NSView 获取图像(swift 3) [英] Get Image from CALayer or NSView (swift 3)

查看:19
本文介绍了从 CALayer 或 NSView 获取图像(swift 3)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在寻找一种方法来渲染 CALayer 或 NSView 并返回 NSImage.

I was looking for a way to render a CALayer or NSView and get NSImage back.

我有一个自定义类,它是 NSView 的子类.一开始我只是做了一个渐变层来覆盖NSView.

I have a custom class, which is a subclass of NSView. At the beginning I simply make a gradient layer to cover 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 $0.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)
   }
}

在某些时候,我想从 CALayer 中获得一个 NSImage(或 CGImage).我在网上找了一些样本,把它们变成了这样:

At some point I want to get a NSImage (or CGImage) from CALayers. I found some samples around the Internet and turned them into this:

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.

The first problem is that draw(layer: CGLayer, in: CGRect) method expects a CGLayer but not CALayer.

其次,我不知道我最终得到的代码是否会渲染我的图层,或者我做错了什么.

Secondly, I don't know if the code I ended up with will eventually render my layer or I'm doing something wrong.

感谢您的帮助.

从 CALayer 获取 CGImage 的解决方案.

Edited: Solution to get a CGImage from CALayer.

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 在下面的答案中.

How to get NSImage from NSView is in the answer below.

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: NSBitmapImageFileType = .PNG, properties: [String : 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 * self.contentsScale)
        let height = Int(bounds.height * self.contentsScale)
        let imageRepresentation = NSBitmapImageRep(bitmapDataPlanes: nil, pixelsWide: width, pixelsHigh: height, bitsPerSample: 8, samplesPerPixel: 4, hasAlpha: true, isPlanar: false, colorSpaceName: NSDeviceRGBColorSpace, 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: NSBitmapImageFileType = .PNG, properties: [String : Any] = [:]) -> Data {
        let width = Int(bounds.width * self.contentsScale)
        let height = Int(bounds.height * self.contentsScale)
        let imageRepresentation = NSBitmapImageRep(bitmapDataPlanes: nil, pixelsWide: width, pixelsHigh: height, bitsPerSample: 8, samplesPerPixel: 4, hasAlpha: true, isPlanar: false, colorSpaceName: NSDeviceRGBColorSpace, 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 获取图像(swift 3)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆