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

Lupurus
  • 3,618
  • 2
  • 29
  • 59

5 Answers5

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)
}
Eric
  • 16,003
  • 15
  • 87
  • 139
az_
  • 1,493
  • 1
  • 16
  • 24
18

Swift 5 code :-

if let image = NSImage(named: "Icon"){
    let cgImage = image.cgImage(forProposedRect: nil, context: nil, hints: nil)
}
Jay Mehta
  • 1,511
  • 15
  • 20
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();
    }
    }
}
Lupurus
  • 3,618
  • 2
  • 29
  • 59
  • 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 structure. All indirectly returned Core Foundation objects are unmanaged as well.` Excerpt From: Apple Inc. “Using Swift with Cocoa and Objective-C.” iBooks. https://itunes.apple.com/ru/book/using-swift-cocoa-objective/id888894773?l=en&mt=11 – ovejka Jul 06 '14 at 12:52
  • 5
    what is takeUnretainedValue? there is no such thing on swift. – Duck Mar 01 '15 at 17:33
  • 1
    `takeUnretainedValue()` isn't available in Swift 5 (the code executes as expected by simply omitting it). – Todd Nov 06 '19 at 14:13
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)
       }
    }
}
Darkwonder
  • 1,149
  • 1
  • 13
  • 26
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
        }
    }
}
madx
  • 6,723
  • 4
  • 55
  • 59
  • Care to be taken when using `unsafelyUnwrapped`. Even Apple has a big red warning on the [documentation](https://developer.apple.com/documentation/swift/optional/1641793-unsafelyunwrapped) page for this feature. – Cristik Aug 31 '21 at 08:40
  • And also you're force unwrapping `tiffRepresentation`, which can lead to crashes in case of nil values. – Cristik Aug 31 '21 at 08:51