Tochukwu
Tochukwu

Reputation: 320

Is it possible to generate NSImage from string?

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

Answers (1)

Leo Dabus
Leo Dabus

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

Related Questions