21

How can I convert a NSImage to CGImage in Swift? In Objective-C I did it like this:

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

Now I tried with:

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

I can't compile, I'm getting the error: Could not find an overload for 'init' that accepts the supplied arguments' at the line let maskRef ...

5 Answers 5

38

Here's what I'm using to convert NSImage to 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) } 
Sign up to request clarification or add additional context in comments.

2 Comments

You can pass nil for proposedRect and get the same result.
You should use CGRect(origin: .zero, size: image.size) instead of CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height)
20

Swift 5 code :-

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

Comments

9

Ah, I found the solution. It's because in Swift you only the an unmanaged object (I just did not really understand, what this means). But this code now works:

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(); } } } 

3 Comments

Right. It's from Apple's book: 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. Excerpt From: Apple Inc. “Using Swift with Cocoa and Objective-C.” iBooks. itunes.apple.com/ru/book/using-swift-cocoa-objective/…
what is takeUnretainedValue? there is no such thing on swift.
takeUnretainedValue() isn't available in Swift 5 (the code executes as expected by simply omitting it).
2

For 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) } } } 

2 Comments

This is very similar to the solution provided almost one year before: stackoverflow.com/a/62298762/1974224. Can you add details on why this answer is different from that one?
@Cristik its more error-safe and shorer
1

A Swift 5 implementation:

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 } } } 

2 Comments

Care to be taken when using unsafelyUnwrapped. Even Apple has a big red warning on the documentation page for this feature.
And also you're force unwrapping tiffRepresentation, which can lead to crashes in case of nil values.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.