You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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("裁剪成功")
}

核心逻辑说明

  1. 先计算旋转后矩形的外接尺寸,确保绘制时目标区域不会被上下文边界截断;
  2. 通过三次上下文变换(平移→旋转→平移),将原图定位到正确位置,让目标旋转区域正好落在上下文的可视范围内;
  3. 裁剪出目标尺寸的区域后,再反向旋转回原角度,得到最终的带角度裁剪结果。

内容的提问来源于stack exchange,提问作者Joya Roy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 12:10:11