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

iOS相册图片添加圆形标记并保存问题求助(附代码)

解决图片添加圆形标记并保存的问题

看起来你遇到的核心问题有两个:一是圆形标记的坐标没有适配图片实际尺寸,导致看起来像是超出图片范围;二是缺少将带标记的图片保存到相册的实现。咱们一步步来解决:

1. 修复圆形标记的绘制问题

你的DrawOnImage函数有两个关键问题:

  • 使用了UIGraphicsBeginImageContext,它不支持Retina屏幕的缩放比例,会导致绘制的标记模糊或坐标偏移
  • 硬编码了椭圆的位置和大小,没有适配不同尺寸的图片,容易出现错位

修改后的绘制函数支持自定义圆形位置,同时适配Retina屏幕:

func drawCircleOnImage(_ image: UIImage, circleFrame: CGRect) -> UIImage {
    // 使用带缩放比例的上下文,保证绘制清晰度与原图一致
    UIGraphicsBeginImageContextWithOptions(image.size, false, image.scale)
    defer { UIGraphicsEndImageContext() } // 确保上下文一定会被关闭,避免内存泄漏
    
    // 先绘制原始图片作为底图
    image.draw(at: .zero)
    
    // 获取绘图上下文并设置样式
    guard let context = UIGraphicsGetCurrentContext() else { return image }
    context.setStrokeColor(UIColor.green.cgColor)
    context.setAlpha(1.0)
    context.setLineWidth(10.0)
    
    // 添加圆形路径并绘制
    context.addEllipse(in: circleFrame)
    context.drawPath(using: .stroke)
    
    // 获取最终带标记的图片
    guard let markedImage = UIGraphicsGetImageFromCurrentImageContext() else { return image }
    return markedImage
}

关键说明:

  • UIGraphicsBeginImageContextWithOptions的第三个参数传入image.scale,完美适配Retina屏幕的清晰度要求
  • 允许传入circleFrame参数,你可以根据需求灵活指定圆形在图片上的位置和大小

2. 处理图片视图的坐标转换(点击添加标记场景)

如果是通过点击UIImageView来添加圆形,需要把触摸点的坐标转换为图片的实际坐标——因为UIImageView的contentMode(比如aspectFit)会缩放图片,直接用触摸点会导致坐标错位:

// 给imagePicked添加触摸手势的响应方法
@objc func handleImageTap(_ gesture: UITapGestureRecognizer) {
    guard let originalImage = imagePicked.image else { return }
    let tapPoint = gesture.location(in: imagePicked)
    
    // 计算图片与视图的缩放比例,适配不同的contentMode
    let imageSize = originalImage.size
    let viewSize = imagePicked.bounds.size
    let scaleWidth = imageSize.width / viewSize.width
    let scaleHeight = imageSize.height / viewSize.height
    let actualScale: CGFloat
    
    switch imagePicked.contentMode {
    case .scaleAspectFit:
        actualScale = min(scaleWidth, scaleHeight)
    case .scaleAspectFill:
        actualScale = max(scaleWidth, scaleHeight)
    default:
        actualScale = 1.0
    }
    
    // 以点击点为中心,绘制一个直径100的圆形
    let circleRadius: CGFloat = 50
    let circleX = tapPoint.x * actualScale - circleRadius
    let circleY = tapPoint.y * actualScale - circleRadius
    let circleFrame = CGRect(x: circleX, y: circleY, width: circleRadius*2, height: circleRadius*2)
    
    // 生成带标记的图片并更新显示
    let markedImage = drawCircleOnImage(originalImage, circleFrame: circleFrame)
    imagePicked.image = markedImage
}

记得在viewDidLoad里开启图片视图的交互并添加手势:

override func viewDidLoad() {
    super.viewDidLoad()
    let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleImageTap(_:)))
    imagePicked.addGestureRecognizer(tapGesture)
    imagePicked.isUserInteractionEnabled = true
}

3. 保存带标记的图片到相册

添加一个保存按钮的响应方法,调用系统API完成相册保存:

@IBAction func saveMarkedImageButton(_ sender: Any) {
    guard let markedImage = imagePicked.image else {
        // 提示用户无可用图片
        let alert = UIAlertController(title: "提示", message: "请先为图片添加标记", preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "确定", style: .default))
        present(alert, animated: true)
        return
    }
    
    // 保存到系统相册
    UIImageWriteToSavedPhotosAlbum(markedImage, self, #selector(imageSavedCallback(_:didFinishSavingWithError:contextInfo:)), nil)
}

// 保存结果的回调方法
@objc func imageSavedCallback(_ image: UIImage, didFinishSavingWithError error: Error?, contextInfo: UnsafeRawPointer) {
    let alertTitle = error == nil ? "保存成功" : "保存失败"
    let alertMessage = error?.localizedDescription ?? "图片已保存到相册"
    let alert = UIAlertController(title: alertTitle, message: alertMessage, preferredStyle: .alert)
    alert.addAction(UIAlertAction(title: "确定", style: .default))
    present(alert, animated: true)
}

额外小提示

你的图片选择器代码里设置了allowsEditing = true,如果需要使用编辑后的图片,可以把UIImagePickerControllerOriginalImage换成UIImagePickerControllerEditedImage,这个根据你的需求调整即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:57:33