Reputation: 320
I've seen a couple of solutions on how to generate UIImage with string How to generate an UIImage from custom text in Swift, but replicating the same thing on macOS seems difficult since their Graphic library is different. Please I just need to convert a string to NSImage so I can use it on a mac application.
Upvotes: 1
Views: 785
Reputation: 236360
You just need to create a new NSImage object, lockFocus, draw the attributed string on it and unlockFocus again:
extension NSAttributedString {
func image(foregroundColor: NSColor? = nil, backgroundColor: NSColor? = nil) -> NSImage {
let size = self.size()
let image = NSImage(size: size)
image.lockFocus()
let mutableStr = NSMutableAttributedString(attributedString: self)
if let foregroundColor = foregroundColor,
let backgroundColor = backgroundColor {
mutableStr.setAttributes([.foregroundColor: foregroundColor,
.backgroundColor: backgroundColor],
range: .init(location: 0, length: length))
}
else
if let foregroundColor = foregroundColor {
mutableStr.setAttributes([.foregroundColor: foregroundColor],
range: .init(location: 0, length: length))
}
else
if let backgroundColor = backgroundColor {
mutableStr.setAttributes([.backgroundColor: backgroundColor],
range: .init(location: 0, length: length))
}
mutableStr.draw(in: .init(origin: .zero, size: size))
image.unlockFocus()
return image
}
}
let stackOverflow = NSAttributedString(string: "StackOverflow")
stackOverflow.image()
stackOverflow.image(foregroundColor: .red)
stackOverflow.image(backgroundColor: .white)
stackOverflow.image(foregroundColor: .red, backgroundColor: .green)
extension StringProtocol {
func image(foregroundColor: NSColor? = nil, backgroundColor: NSColor? = nil) -> NSImage {
NSAttributedString(string: .init(self)).image(foregroundColor: foregroundColor, backgroundColor: backgroundColor)
}
}
"StackOverflow".image()
edit/update:
If you would like to create an image from a label (NSTextField)
extension NSView {
var image: NSImage? {
guard let bitmapImageRep = bitmapImageRepForCachingDisplay(in: bounds) else { return nil }
cacheDisplay(in: bounds, to: bitmapImageRep)
guard let cgImage = bitmapImageRep.cgImage else { return nil }
return NSImage(cgImage: cgImage, size: bounds.size)
}
}
let label = NSTextField(labelWithString: "StackOverflow")
label.textColor = .blue
label.backgroundColor = .clear
label.sizeToFit()
label.image
Upvotes: 4