UIImage cropping
oval shape cropping
circle shape cropping
iOS image processing
SwiftUI image manipulation

How to crop UIImage on oval shape or circle shape?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Cropping a UIImage into a circle or oval is common for avatars, profile previews, and cards. The effect looks simple, but good results depend on choosing the right target size, handling rectangular source images correctly, and deciding whether you need a real cropped bitmap or only a masked display.

Start With a Square for Circle Crops

A true circle needs a square drawing area. If the source image is rectangular, crop a centered square first.

swift
1import UIKit
2
3func centerSquareCrop(_ image: UIImage) -> UIImage {
4    guard let cgImage = image.cgImage else { return image }
5
6    let width = CGFloat(cgImage.width)
7    let height = CGFloat(cgImage.height)
8    let side = min(width, height)
9    let originX = (width - side) / 2
10    let originY = (height - side) / 2
11
12    let rect = CGRect(x: originX, y: originY, width: side, height: side)
13    guard let cropped = cgImage.cropping(to: rect) else { return image }
14
15    return UIImage(cgImage: cropped, scale: image.scale, orientation: image.imageOrientation)
16}

Without this step, a circular mask applied to a rectangular image often leaves the subject stretched or off-center.

Render the Circular Image

Once the image is square, draw it into an oval clipping path with UIGraphicsImageRenderer.

swift
1import UIKit
2
3func circularImage(from image: UIImage, diameter: CGFloat) -> UIImage {
4    let square = centerSquareCrop(image)
5    let renderer = UIGraphicsImageRenderer(size: CGSize(width: diameter, height: diameter))
6
7    return renderer.image { _ in
8        let bounds = CGRect(x: 0, y: 0, width: diameter, height: diameter)
9        UIBezierPath(ovalIn: bounds).addClip()
10        square.draw(in: bounds)
11    }
12}

UIGraphicsImageRenderer is the modern UIKit drawing API and generally behaves better than older context APIs for scale handling.

Create an Oval Crop

An oval crop uses the same clipping approach, but the target width and height differ.

swift
1import UIKit
2
3func ovalImage(from image: UIImage, size: CGSize) -> UIImage {
4    let renderer = UIGraphicsImageRenderer(size: size)
5
6    return renderer.image { _ in
7        let bounds = CGRect(origin: .zero, size: size)
8        UIBezierPath(ovalIn: bounds).addClip()
9        image.draw(in: bounds)
10    }
11}

This is useful for wide avatar chips, story cards, or other designs where a full circle is not the intended shape.

Use the Result in UIKit

A common UIKit flow is to preprocess the image once and assign the result to an image view.

swift
1import UIKit
2
3final class ProfileViewController: UIViewController {
4    @IBOutlet private weak var avatarView: UIImageView!
5
6    override func viewDidLoad() {
7        super.viewDidLoad()
8
9        guard let source = UIImage(named: "avatar") else { return }
10        avatarView.image = circularImage(from: source, diameter: 120)
11        avatarView.contentMode = .scaleAspectFill
12    }
13}

Preprocessing can be better than view-only masking when the same shaped asset is reused often.

SwiftUI Display Masking Versus Real Cropping

In SwiftUI, you can either preprocess a UIImage or clip only at display time.

swift
1import SwiftUI
2
3struct AvatarView: View {
4    let image: UIImage
5
6    var body: some View {
7        Image(uiImage: circularImage(from: image, diameter: 96))
8            .resizable()
9            .frame(width: 96, height: 96)
10    }
11}

If you only need the on-screen visual effect, clipShape(Circle()) is simpler. If you need a real image for upload, caching, or export, create a new bitmap instead.

Performance Considerations

Image rendering can become expensive if repeated during scrolling or cell reuse. A few practical rules help:

  • preprocess once when possible
  • cache by image identifier and output size
  • avoid re-rendering the same crop during every redraw

The code is straightforward, but repeated rendering can still show up as dropped frames on older devices.

Common Pitfalls

The biggest mistake is applying a circular mask to a non-square source image and expecting a correct avatar crop automatically.

Another common issue is confusing display clipping with real bitmap cropping. A clipped view does not automatically produce a new image file. Developers also often re-render the same crop repeatedly inside performance-sensitive views instead of caching it.

Summary

  • Circle crops work best by center-cropping to a square first.
  • Use UIGraphicsImageRenderer for modern image rendering.
  • Oval crops use the same approach with a non-square target size.
  • Preprocess the bitmap when you need reuse, caching, or export.
  • Use view-level clipping only when the effect is purely visual.

Course illustration
Course illustration

All Rights Reserved.