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
相关产品推荐
相关产品推荐

