techno
techno

Reputation: 6500

Resizing NSImage Shifts its Origin and Producing Wrong Results

I'm using the following code to Resize an Image(Keeping Aspect Ratio).When I try to resize an Image whose size is 2432X3648 Pixels to 1800X2700 Pixels The output image origin gets shifted.

extension NSImage {   


  func resizeTo(width: CGFloat, height: CGFloat) -> NSImage {
    let ratioX = width / size.width
    let ratioY = height / size.height
    var ratio = ratioX < ratioY ? ratioX : ratioY
    let newHeight = size.height * ratio
    let newWidth = size.width * ratio
    let canvasSize = CGSize(width: newWidth, height: newHeight)
    let img = NSImage(size: canvasSize)
    img.lockFocus()
    let context = NSGraphicsContext.current()
    context?.imageInterpolation = .high
    draw(in: NSRect(origin: .zero, size: NSSize(width: newWidth,height: newHeight)), from: NSRect(origin: .zero, size: size) , operation: .copy, fraction: 1)
    img.unlockFocus()
    return img
    }


}

Please see the resized sample image.I have marked the Image.The resizing code seems to work fine in other cases.Please advice..

enter image description here

UPDATE: @LeoDabus I have used your code and it produces similar result for output size 1084X2086 Pixels.I had to slightly modify your code - only on a single line as it won't compile.The compiler auto suggested it. NSGraphicsContext.current()?.imageInterpolation = .high

 func resizeTo(width: CGFloat, height: CGFloat) -> NSImage {
        let ratioX = width / size.width
        let ratioY = height / size.height
        let ratio = ratioX < ratioY ? ratioX : ratioY
        let newHeight = size.height * ratio
        let newWidth = size.width * ratio
        let canvasSize = CGSize(width: width, height: CGFloat(ceil(width/size.width * size.height)))
        let img = NSImage(size: canvasSize)
        img.lockFocus()
        NSGraphicsContext.current()?.imageInterpolation = .high
        draw(in: NSRect(origin: CGPoint(x: (canvasSize.width - (size.width * ratio)) / 2, y: (canvasSize.height - (size.height * ratio)) / 2), size: NSSize(width: newWidth,height: newHeight)), from: NSRect(origin: .zero, size: size), operation: .copy, fraction: 1)
        img.unlockFocus()
        return img

}

Upvotes: 4

Views: 691

Answers (1)

Leo Dabus
Leo Dabus

Reputation: 236360

What was actually wrong was only the canvas size which should be using the new width and height:

extension NSImage {
    func resizedTo(width: CGFloat, height: CGFloat) -> NSImage {
        let ratio = min(canvas.width/size.width, canvas.height/size.height)
        let canvasSize = NSSize(width: size.width * ratio, height: size.height * ratio)
        let img = NSImage(size: canvasSize)
        img.lockFocus()
        NSGraphicsContext.current?.imageInterpolation = .high
        draw(in: NSRect(origin: CGPoint(x: (canvasSize.width - (size.width * ratio)) / 2, y: (canvasSize.height - (size.height * ratio)) / 2), size: canvasSize), from: NSRect(origin: .zero, size: size), operation: .copy, fraction: 1)
        img.unlockFocus()
        return img
    }
}

Upvotes: 2

Related Questions