Swift中如何按30度角度裁剪指定尺寸的图像区域?
实现带旋转角度的图片裁剪(Swift)
你当前使用cgImage.cropping(to:)的方式只能处理轴对齐的矩形裁剪,无法直接实现带角度的区域裁剪。要完成这个需求,需要借助Core Graphics的图形变换能力,通过上下文绘制+旋转变换的方式实现,以下是具体的代码方案:
import UIKit extension UIImage { /// 裁剪并返回带指定旋转角度的矩形区域图片 /// - Parameters: /// - rectSize: 目标裁剪区域的尺寸(未旋转前的大小) /// - rotationAngle: 旋转角度(单位:度) /// - centerOffset: 目标区域中心相对于原图左上角的偏移量 /// - Returns: 裁剪后的旋转图片,失败则返回nil func croppedRotatedRect(rectSize: CGSize, rotationAngle: CGFloat, centerOffset: CGPoint) -> UIImage? { // 将角度转换为弧度 let radians = rotationAngle * .pi / 180 // 计算旋转后矩形的外接尺寸,避免内容被截断 let rotatedWidth = rectSize.width * abs(cos(radians)) + rectSize.height * abs(sin(radians)) let rotatedHeight = rectSize.width * abs(sin(radians)) + rectSize.height * abs(cos(radians)) let rotatedRect = CGRect(x: 0, y: 0, width: rotatedWidth, height: rotatedHeight) // 创建适配的图形上下文 UIGraphicsBeginImageContextWithOptions(rotatedRect.size, false, self.scale) guard let context = UIGraphicsGetCurrentContext() else { UIGraphicsEndImageContext() return nil } // 平移上下文到旋转中心 → 执行旋转 → 平移回对应位置,让目标区域对齐上下文可视范围 context.translateBy(x: rotatedWidth/2, y: rotatedHeight/2) context.rotate(by: radians) context.translateBy(x: -rectSize.width/2 - centerOffset.x, y: -rectSize.height/2 - centerOffset.y) // 绘制原图到上下文 self.draw(at: .zero) // 提取裁剪后的图片 guard let croppedImage = UIGraphicsGetImageFromCurrentImageContext() else { UIGraphicsEndImageContext() return nil } UIGraphicsEndImageContext() // 将裁剪后的图片旋转回原角度,得到最终结果 return croppedImage.rotated(by: -rotationAngle) } /// 辅助方法:将图片旋转指定角度 func rotated(by angle: CGFloat) -> UIImage? { let radians = angle * .pi / 180 // 计算旋转后的图片尺寸 let rotatedSize = CGRect(origin: .zero, size: self.size) .applying(CGAffineTransform(rotationAngle: radians)) .integral.size UIGraphicsBeginImageContextWithOptions(rotatedSize, false, self.scale) guard let context = UIGraphicsGetCurrentContext() else { UIGraphicsEndImageContext() return nil } // 平移到旋转中心并执行旋转,再绘制原图 context.translateBy(x: rotatedSize.width/2, y: rotatedSize.height/2) context.rotate(by: radians) self.draw(at: CGPoint(x: -self.size.width/2, y: -self.size.height/2)) let rotatedImage = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return rotatedImage } } // 使用示例 private var mInputImage: UIImage = UIImage(named: "Z01")! // 400x300像素 // 参数说明: // rectSize: 目标裁剪尺寸200x100 // rotationAngle: 旋转角度30度 // centerOffset: 从原代码的左上角(x:50,y:100)转换为中心偏移:(50+100, 100+50) = (150,150) if let croppedRotatedImage = mInputImage.croppedRotatedRect(rectSize: CGSize(width: 200, height: 100), rotationAngle: 30, centerOffset: CGPoint(x: 150, y: 150)) { // 这里可以使用裁剪后的旋转图片 print("裁剪成功") }
核心逻辑说明
- 先计算旋转后矩形的外接尺寸,确保绘制时目标区域不会被上下文边界截断;
- 通过三次上下文变换(平移→旋转→平移),将原图定位到正确位置,让目标旋转区域正好落在上下文的可视范围内;
- 裁剪出目标尺寸的区域后,再反向旋转回原角度,得到最终的带角度裁剪结果。
内容的提问来源于stack exchange,提问作者Joya Roy
相关产品推荐
相关产品推荐

