This post presents a method to change the image size of a UIImage without stretching in Swift. Following the method in this post will allow you to set the size of a UIImage to a desired size while keeping the aspect ratio the same.

Set Image Size

The first step is to determine the new scaled size of the original UIImage. This new scaled size must preserve the aspect ratio of the original image.

let image = // your image
let targetSize = CGSize(width: 100, height: 100)

// Compute the scaling ratio for the width and height separately
let widthScaleRatio = targetSize.width / image.size.width
let heightScaleRatio = targetSize.height / image.size.height

// To keep the aspect ratio, scale by the smaller scaling ratio
let scaleFactor = min(widthScaleRatio, heightScaleRatio)

// Multiply the original image’s dimensions by the scale factor 
// to determine the scaled image size that preserves aspect ratio
let scaledImageSize = CGSize(
    width: image.size.width * scaleFactor,
    height: image.size.height * scaleFactor
)

Draw Resized UIImage

The next step is to create a new scaled UIImage from the original UIImage. One way to draw a resized UIImage is to use the UIGraphicsImageRenderer.

let image = // your image
let scaledImageSize = // scaled image size

let renderer = UIGraphicsImageRenderer(size: scaledImageSize)
let scaledImage = renderer.image { _ in
    image.draw(in: CGRect(origin: .zero, size: scaledImageSize))
}

UIImage Extension For Resizing

The last step is to combine the code snippets for resizing and drawing into a UIImage extension. An extension will allow you to resize any UIImage directly.

import UIKit

extension UIImage {
    func scalePreservingAspectRatio(targetSize: CGSize) -> UIImage {
        // Determine the scale factor that preserves aspect ratio
        let widthRatio = targetSize.width / size.width
        let heightRatio = targetSize.height / size.height
        
        let scaleFactor = min(widthRatio, heightRatio)
        
        // Compute the new image size that preserves aspect ratio
        let scaledImageSize = CGSize(
            width: size.width * scaleFactor,
            height: size.height * scaleFactor
        )

        // Draw and return the resized UIImage
        let renderer = UIGraphicsImageRenderer(
            size: scaledImageSize
        )

        let scaledImage = renderer.image { _ in
            self.draw(in: CGRect(
                origin: .zero, 
                size: scaledImageSize
            ))
        }
        
        return scaledImage
    }
}

Resizing UIImage Without Stretching

That’s it! You now have an extension that will resize any UIImage to a target size without stretching or distorting the original image.

let image = // your image
let targetSize = CGSize(width: 100, height: 100)

let scaledImage = image.scalePreservingAspectRatio(
    targetSize: targetSize
)