来自Swift的CGImageRef的NSData(NSData from CGImageRef in Swift)

我很难弄清楚如何从CGImageRef获取图像的NSData表示。 我发现的所有答案都使用UIImage或NSImage ,但我的应用程序是跨平台的,所以我只想使用Core Graphics。 Objective-C简单地回答说, CFData是免费桥接到NSData并简单地转换它,但Swift不允许这样做。 我最接近的是:

var image: CGImageRef? = nil //... if let dataProvider: CGDataProviderRef = CGDataProviderCreateWithURL(url) { image = CGImageCreateWithPNGDataProvider(dataProvider, nil, false, CGColorRenderingIntent.RenderingIntentDefault) // works fine //... if let data = CGDataProviderCopyData(CGImageGetDataProvider(image)) as? NSData { // Do something with data, if only it ever got here! } }

但演员阵容永远不会成功......

I am having difficulty figuring out how to get an NSData representation of an image from a CGImageRef. All of the answers I've found make use of UIImage or NSImage, but my application is cross-platform, so I want to use only Core Graphics. Objective-C answers state simply that CFData is toll-free bridged to NSData and simply cast it, but Swift will not allow this. The closest I've got is:

var image: CGImageRef? = nil //... if let dataProvider: CGDataProviderRef = CGDataProviderCreateWithURL(url) { image = CGImageCreateWithPNGDataProvider(dataProvider, nil, false, CGColorRenderingIntent.RenderingIntentDefault) // works fine //... if let data = CGDataProviderCopyData(CGImageGetDataProvider(image)) as? NSData { // Do something with data, if only it ever got here! } }

but the cast doesn't ever succeed...

最满意答案

CGDataProviderCopyData()返回可选的CFData? ,并且不能转换为非可选NSData 。 但你可以转换/桥接到NSData? 并在可选绑定中使用它:

if let data = CGDataProviderCopyData(CGImageGetDataProvider(image)) as NSData? { // Do something with data ... }

这是一个更简单的示例,演示了与CFString和NSString相同的问题:

let cfstr : CFString? = "Hello world" if let nsstr = cfstr as? NSString { print("foo") // not printed } if let nsstr = cfstr as NSString? { print("bar") // printed }

但我承认我的解释并不完全令人满意,因为类似的可选演员在其他情况下也适用:

class MyClass { } class MySubclass : MyClass { } let mc : MyClass? = MySubclass() if let msc = mc as? MySubclass { print("yes") // printed }

所以这必须与CoreFoundation和Foundation类型之间的免费桥接有关。

CGDataProviderCopyData() returns the optional CFData?, and that cannot be cast to the non-optional NSData. But you can convert/bridge it to NSData? and use that in the optional binding:

if let data = CGDataProviderCopyData(CGImageGetDataProvider(image)) as NSData? { // Do something with data ... }

Here is a simpler example demonstrating the same issue with CFString and NSString:

let cfstr : CFString? = "Hello world" if let nsstr = cfstr as? NSString { print("foo") // not printed } if let nsstr = cfstr as NSString? { print("bar") // printed }

But I admit that my explanation is not fully satisfying, because a similar optional cast works in other cases:

class MyClass { } class MySubclass : MyClass { } let mc : MyClass? = MySubclass() if let msc = mc as? MySubclass { print("yes") // printed }

So this must be related to the toll-free bridging between CoreFoundation and Foundation types.

更多推荐