Transform two NSImages on top of each other into a single NSImage without using `lockFocus`

50 views Asked by At

I have a large image and a smaller image, both in Data type which I transformed into NSImage. I want to put the smaller image on top of the large image, top-left aligned, in a new single NSImage.

Currently this code works, however both lockFocus and unlockFocus are deprecated. I don't think the documentation is clear enough for me to understand how I should rewrite it.

This is the working code:

func combineImages(image1: NSImage, image2: NSImage) -> NSImage {
    let size = NSMakeSize(max(image1.size.width, image2.size.width), max(image1.size.height, image2.size.height))
    let newImage = NSImage(size: size)
    
    newImage.lockFocus()
    
    image2.draw(at: NSPoint(x: 0, y: size.height - image2.size.height), from: NSZeroRect, operation: .sourceOver, fraction: 1.0)
    image1.draw(at: NSZeroPoint, from: NSZeroRect, operation: .sourceOver, fraction: 1.0)
    
    newImage.unlockFocus()

    return newImage
}

The deprecation method is:

This method is incompatible with resolution-independent drawing and should not be used.

1

There are 1 answers

3
l'L'l On BEST ANSWER

You can use init(size:flipped:drawingHandler:) instead:

func combineImages(image1: NSImage, image2: NSImage) -> NSImage {
    let size = NSSize(width: max(image1.size.width, image2.size.width), height: max(image1.size.height, image2.size.height))
    let newImage = NSImage(size: size, flipped: false) { _ in
        let drawPointImage2 = NSPoint(x: 0, y: size.height - image2.size.height)
        image2.draw(at: drawPointImage2, from: NSRect(origin: .zero, size: image2.size), operation: .sourceOver, fraction: 1.0)
        image1.draw(at: NSPoint.zero, from: NSRect(origin: .zero, size: image1.size), operation: .sourceOver, fraction: 1.0)
        return true
    }
    
    return newImage
}

Using rect closure:

func combineImages(image1: NSImage, image2: NSImage) -> NSImage {
    let size = NSSize(width: max(image1.size.width, image2.size.width), height: max(image1.size.height, image2.size.height))
    let newImage = NSImage(size: size, flipped: false) { rect -> Bool in
        let drawPointImage2 = NSPoint(x: 0, y: size.height - image2.size.height)
        image2.draw(at: drawPointImage2, from: NSRect(origin: .zero, size: image2.size), operation: .sourceOver, fraction: 1.0)
        image1.draw(at: NSPoint.zero, from: NSRect(origin: .zero, size: image1.size), operation: .sourceOver, fraction: 1.0)
        return true
    }
    
    return newImage
}

init(size:flipped:drawingHandler:)