4

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

}
techno
  • 6,100
  • 16
  • 86
  • 192

1 Answers1

2

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
    }
}
Leo Dabus
  • 229,809
  • 59
  • 489
  • 571
  • I'm getting the following error `Cannot use optional chaining on non-optional value of type '() -> NSGraphicsContext?`,So I followed the compiler auto correct and changed it to `NSGraphicsContext.current().imageInterpolation = .high` ... Your new code produces the same error.Please advice. – techno Feb 04 '18 at 07:58
  • First advice is to update your Swift / Xcode to the latest version. Second I have already tested the method here and it scales properly. Make sure you have set your image view constraints properly and that you are using the proper imageAlignment – Leo Dabus Feb 04 '18 at 18:55
  • Thanks for your reply. I will update xcode..Have you tested converting 2432X3648 Pixels to 1800X2700 ..I don't understand what you mean by alignment... – techno Feb 04 '18 at 18:57
  • If you don't post your code I would be only guessing. https://developer.apple.com/documentation/appkit/nsimageview/1404963-imagealignment and https://developer.apple.com/documentation/appkit/nsimagealignment – Leo Dabus Feb 04 '18 at 18:58
  • I don't use the image from the image view ... I load the image from disk and create an NSImage..I will post more code tomorrow.Please check with the specific sizing i told you...The code seems to work fine in some cases. – techno Feb 04 '18 at 19:01
  • @techno send me the link of the image, the target size and the resulting size. All images that I have tested here did scale properly – Leo Dabus Feb 04 '18 at 19:13
  • All I got was a black image – Leo Dabus Feb 04 '18 at 19:29
  • Yes,once you resize it,you can find white border around it... I have upload it properly here again http://ge.tt/4cL4pQo2 – techno Feb 04 '18 at 19:30
  • I'm trying to Detect a Face and Resize the detected face using the code you had posted earlier.Please see the update, does this cause the resizing issue? – techno Feb 06 '18 at 07:17