【问题标题】:Swift NSImage to CGImageSwift NSImage 到 CGImage
【发布时间】:2014-08-27 01:38:59
【问题描述】:

如何在 Swift 中将 NSImage 转换为 CGImage?在 Objective-C 中,我是这样做的:

- (CGImageRef)CGImage {
    NSData *imageData = self.TIFFRepresentation;
    CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)imageData, NULL);
    CGImageRef maskRef =  CGImageSourceCreateImageAtIndex(source, 0, NULL);
    return maskRef;
}

现在我尝试了:

extension NSImage {
    var CGImage: CGImageRef {
    get {
        let imageData = self.TIFFRepresentation
        let source = CGImageSourceCreateWithData(imageData as CFDataRef, nil)
        let maskRef = CGImageSourceCreateImageAtIndex(source, UInt(0), nil)
        return maskRef;
    }
    }
}

我无法编译,出现错误:Could not find an overload for 'init' that accepts the supplied arguments'let maskRef ...

【问题讨论】:

    标签: cocoa swift nsimage


    【解决方案1】:

    这是我用来将 NSImage 转换为 CGImage 的方法:

    let image = NSImage(named:"image")
    if let image = image {
        var imageRect = CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height)
        let imageRef = image.cgImage(forProposedRect: &imageRect, context: nil, hints: nil)
    }
    

    【讨论】:

    • 您可以将nil 传递给proposedRect 并得到相同的结果。
    • 你应该使用CGRect(origin: .zero, size: image.size)而不是CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height)
    【解决方案2】:

    Swift 5 代码:-

    if let image = NSImage(named: "Icon"){
        let cgImage = image.cgImage(forProposedRect: nil, context: nil, hints: nil)
    }
    

    【讨论】:

      【解决方案3】:

      啊,我找到了解决方案。这是因为在 Swift 中你只有一个非托管对象(我只是不太明白,这是什么意思)。但是这段代码现在可以工作了:

      extension NSImage {
          var CGImage: CGImageRef {
          get {
              let imageData = self.TIFFRepresentation
              let source = CGImageSourceCreateWithData(imageData as CFDataRef, nil).takeUnretainedValue()
              let maskRef = CGImageSourceCreateImageAtIndex(source, UInt(0), nil)
              return maskRef.takeUnretainedValue();
          }
          }
      }
      

      【讨论】:

      • 对。它来自 Apple 的书:When Swift imports APIs that have not been annotated, the compiler cannot automatically memory manage the returned Core Foundation objects. Swift wraps these returned Core Foundation objects in an Unmanaged<T> structure. All indirectly returned Core Foundation objects are unmanaged as well. 摘自:Apple Inc. “Using Swift with Cocoa and Objective-C”。电子书。 itunes.apple.com/ru/book/using-swift-cocoa-objective/…
      • 什么是 takeUnretainedValue? swift上没有这样的东西。
      • takeUnretainedValue() 在 Swift 5 中不可用(代码按预期执行,只需省略它)。
      【解决方案4】:

      对于 Swift 4.0、XCode 9.2:

      extension NSImage {
          @objc var CGImage: CGImage? {
             get {
                  guard let imageData = self.tiffRepresentation else { return nil }
                  guard let sourceData = CGImageSourceCreateWithData(imageData as CFData, nil) else { return nil }
                  return CGImageSourceCreateImageAtIndex(sourceData, 0, nil)
             }
          }
      }
      

      【讨论】:

      • 这与几乎一年前提供的解决方案非常相似:stackoverflow.com/a/62298762/1974224。您能否详细说明为什么这个答案与那个答案不同?
      • @Cristik 更安全且更安全
      【解决方案5】:

      Swift 5 实现:

      extension NSImage {
          var CGImage: CGImage {
              get {
                  let imageData = self.tiffRepresentation!
                  let source = CGImageSourceCreateWithData(imageData as CFData, nil).unsafelyUnwrapped
                  let maskRef = CGImageSourceCreateImageAtIndex(source, Int(0), nil)
                  return maskRef.unsafelyUnwrapped
              }
          }
      }
      

      【讨论】:

      • 使用unsafelyUnwrapped时要小心。甚至 Apple 在documentation 页面上也针对此功能发出了大红色警告。
      • 而且你还强制解开tiffRepresentation,如果值为 nil 可能会导致崩溃。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-11-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多