UIImage
Resize
Crop
iOS Development
Image Processing

UIImage Resize, then Crop

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

Introduction

When you need an image to fit an exact box, the usual sequence is resize first, then crop. Resizing brings the image close to the target scale while preserving quality, and cropping removes the extra edges. If you skip the order or ignore aspect ratio, the result often looks stretched or blurry.

Why Resize Before Crop

Suppose you want a square avatar from a rectangular photo. If you crop first without thinking about scale, you may throw away useful image detail or work with a much larger bitmap than necessary. A better pattern is:

  1. scale the image so it fully covers the target size
  2. crop the centered or chosen region

This is the same idea as “aspect fill” for a bitmap you want to save as a new UIImage.

A Swift Helper Using UIGraphicsImageRenderer

Modern iOS code should prefer UIGraphicsImageRenderer for this kind of work. It handles scale cleanly and is safer than the older image context APIs.

swift
1import UIKit
2
3extension UIImage {
4    func resizedAndCropped(to targetSize: CGSize) -> UIImage {
5        let widthRatio = targetSize.width / size.width
6        let heightRatio = targetSize.height / size.height
7        let scale = max(widthRatio, heightRatio)
8
9        let scaledSize = CGSize(
10            width: size.width * scale,
11            height: size.height * scale
12        )
13
14        let x = (targetSize.width - scaledSize.width) / 2
15        let y = (targetSize.height - scaledSize.height) / 2
16        let drawRect = CGRect(origin: CGPoint(x: x, y: y), size: scaledSize)
17
18        let format = UIGraphicsImageRendererFormat.default()
19        format.scale = self.scale
20
21        let renderer = UIGraphicsImageRenderer(size: targetSize, format: format)
22        return renderer.image { _ in
23            self.draw(in: drawRect)
24        }
25    }
26}

Usage:

swift
let output = inputImage.resizedAndCropped(to: CGSize(width: 200, height: 200))

This works by scaling the image enough to cover the output box, then drawing it into a renderer whose canvas is already the final size. The extra area falls outside the canvas, which effectively crops it.

Center Crop vs Custom Crop

The previous example performs a center crop. That is usually correct for avatars, thumbnails, and gallery cards. If you need to preserve the top of a portrait photo rather than the center, adjust the drawing origin.

For example, top-aligned crop:

swift
let x = (targetSize.width - scaledSize.width) / 2
let y: CGFloat = 0

Now the image is still scaled to fill, but the crop keeps the upper content instead of centering vertically.

This is important because “crop” is not only a geometry problem. It is also a content decision.

If You Need Separate Resize and Crop Steps

Sometimes it helps to keep the operations separate for clarity. Here is a two-step version:

swift
1import UIKit
2
3func resize(_ image: UIImage, to size: CGSize) -> UIImage {
4    let renderer = UIGraphicsImageRenderer(size: size)
5    return renderer.image { _ in
6        image.draw(in: CGRect(origin: .zero, size: size))
7    }
8}
9
10func crop(_ image: UIImage, to rect: CGRect) -> UIImage? {
11    guard let cgImage = image.cgImage?.cropping(to: rect) else {
12        return nil
13    }
14    return UIImage(cgImage: cgImage, scale: image.scale, orientation: image.imageOrientation)
15}

This version is useful when your crop rectangle comes from user interaction, such as a drag selection or camera overlay.

Be careful, though: cgImage?.cropping(to:) uses pixel coordinates, not point-based UIKit layout coordinates. If the image has a scale factor, you need to convert correctly.

Image Orientation Matters

A frequent source of bugs is image orientation. Photos coming from the camera can have orientation metadata that makes them display correctly on screen even though the underlying pixel data is rotated.

If cropping seems offset or rotated, normalize the image first:

swift
1func normalizedImage(_ image: UIImage) -> UIImage {
2    let renderer = UIGraphicsImageRenderer(size: image.size)
3    return renderer.image { _ in
4        image.draw(in: CGRect(origin: .zero, size: image.size))
5    }
6}

Then resize or crop the normalized result.

Common Pitfalls

The biggest pitfall is resizing to the exact target dimensions without preserving aspect ratio. That squashes the image instead of cropping it.

Another common issue is mixing points and pixels. UIKit layout works in points, while Core Graphics cropping works on pixel-backed CGImage coordinates.

Orientation problems also show up often with camera images. If the crop region looks wrong, normalize first and test again.

Finally, avoid doing heavy image processing repeatedly on the main thread for large images. Resize and crop work can be expensive, especially in scrolling views or batch imports.

Summary

  • For fixed-size output, resize to fill first and crop second.
  • 'UIGraphicsImageRenderer is a strong modern choice for creating the output image.'
  • Center crop is common, but the crop origin can be customized.
  • Separate resize and crop steps are useful when the crop area comes from user input.
  • Watch for aspect ratio, orientation, and point-versus-pixel coordinate issues.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

All Rights Reserved.