1

I'm using the following code to resize an image.But i keep getting a white border at the bottom

 func resize(withSize targetSize: NSSize) -> NSImage? {

        let size=NSSize(width: floor((targetSize.width/(NSScreen.main?.backingScaleFactor)!)), height:floor( (targetSize.height/(NSScreen.main?.backingScaleFactor)!)))

        let frame = NSRect(x: 0, y: 0, width: floor(size.width), height: floor(size.height))

        guard let representation = self.bestRepresentation(for: frame, context: nil,hints: nil) else {
            return nil
        }

        let image = NSImage(size: size, flipped: false, drawingHandler: { (_) -> Bool in
            return representation.draw(in: frame)
        })

        return image
    }

I have tried using floor function to round off the values.But still the same issue.

enter image description here

techno
  • 6,100
  • 16
  • 86
  • 192
  • your code will scaleToFit (this will distort your origanal image). Is it intentional? – Leo Dabus Apr 04 '20 at 18:13
  • @LeoDabus No.... I just want to resize the image... – techno Apr 04 '20 at 18:18
  • This will also take in account the screen scale. If you pass a size of 300x300, the screen scale is @2x the resulting image will be 600x600. Is it what you want? – Leo Dabus Apr 04 '20 at 18:28
  • @LeoDabus I passed the screen scale to make sure the image is not 2X scaled as I have a retina screen.Basically I need two functions to resize image keeping aspect ratio and one without preserving the aspect ratio.The output file must be the exact size the user enters in pixels in case of non aspect ratio preservation.. it should be independent of the screen size. – techno Apr 04 '20 at 18:32
  • If you don't take into account the screen scale the result will look pixelated – Leo Dabus Apr 04 '20 at 18:40
  • @LeoDabus ah... okay.. The core functionality is image resizing .. the image should be the same size irrespective of the machine. – techno Apr 04 '20 at 18:41

1 Answers1

1
extension NSImage {
    func resize(withSize targetSize: NSSize) -> NSImage? {
        let ratioX = targetSize.width / size.width / (NSScreen.main?.backingScaleFactor ?? 1)
        let ratioY = targetSize.height / size.height / (NSScreen.main?.backingScaleFactor ?? 1)
        let ratio = ratioX < ratioY ? ratioX : ratioY
        let canvasSize = NSSize(width: size.width * ratio, height: size.height * ratio)
        let frame = NSRect(origin: .zero, size: canvasSize)
        guard let representation = bestRepresentation(for: frame, context: nil, hints: nil)
        else { return nil }
        return NSImage(size: canvasSize, flipped: false) { _ in representation.draw(in: frame) }
    }
}

let image = NSImage(contentsOf: URL(string: "https://i.stack.imgur.com/Xs4RX.jpg")!)!
let resized = image.resize(withSize: .init(width: 400, height: 300))  // w 267 h 300

If you would like to take into account the screen scale just remove the division by (NSScreen.main?.backingScaleFactor ?? 1) from the method when calculating ratioX and ratioY

Leo Dabus
  • 229,809
  • 59
  • 489
  • 571