Working with Images in Swift: resize and crop for iOS and macOS
Image processing is one of the most common tasks when developing mobile and desktop applications. On Apple platforms (iOS and macOS), you can use both built-in frameworks (UIKit for iOS, AppKit for macOS) and the powerful low-level Core Graphics to resize and crop images. In this article, we will cover universal methods that work on both platforms and provide ready-made code examples in Swift.
Main Approaches to Image Processing
There are three main ways to resize or crop an image in Swift:
- UIKit (iOS/tvOS) — uses the
UIImageclass and itsdraw(in:)method orUIGraphicsImageRenderer. - AppKit (macOS) — uses the
NSImageclass and work withNSGraphicsContext. - Core Graphics (Quartz 2D) — a cross-platform low-level C framework that works on both iOS and macOS. It is based on
CGImageand graphics contexts.
For versatility, we will use Core Graphics, as it allows you to write code that can be easily adapted for both platforms. However, for iOS projects, it is often more convenient to use UIGraphicsImageRenderer — it is simpler and faster.
Resizing an Image (Resize)
The resize function takes the original image (UIImage or NSImage) and a new size (CGSize). The algorithm is simple: a graphics context of the desired size is created, the original image is drawn into it, and then a new image is extracted from the context.
Example for iOS (UIKit)
import UIKit
extension UIImage { func resized(to newSize: CGSize) -> UIImage? { let renderer = UIGraphicsImageRenderer(size: newSize) return renderer.image { _ in self.draw(in: CGRect(origin: .zero, size: newSize)) } }}
// Usage:if let image = UIImage(named: "example"), let resized = image.resized(to: CGSize(width: 300, height: 200)) { // use resized}Example for macOS (AppKit + Core Graphics)
import AppKit
extension NSImage { func resized(to newSize: NSSize) -> NSImage? { guard let cgImage = self.cgImage(forProposedRect: nil, context: nil, hints: nil) else { return nil } let bitmap = NSBitmapImageRep( bitmapDataPlanes: nil, pixelsWide: Int(newSize.width), pixelsHigh: Int(newSize.height), bitsPerSample: 8, samplesPerPixel: 4, hasAlpha: true, isPlanar: false, colorSpaceName: .deviceRGB, bitmapFormat: .alphaFirst, bytesPerRow: 0, bitsPerPixel: 0 ) guard let context = NSGraphicsContext(bitmapImageRep: bitmap!) else { return nil } NSGraphicsContext.saveGraphicsState() NSGraphicsContext.current = context let rect = NSRect(origin: .zero, size: newSize) self.draw(in: rect, from: .zero, operation: .copy, fraction: 1.0) NSGraphicsContext.restoreGraphicsState() let newImage = NSImage(size: newSize) newImage.addRepresentation(bitmap!) return newImage }}Cropping an Image (Crop)
Cropping (crop) is selecting a rectangular area from the original image. In Core Graphics, the cropping(to:) function of CGImage is used for this. It is important to remember that coordinates in Core Graphics start from the bottom-left corner, so for iOS (where the Y-axis points downward), coordinate transformation may be required.