Swift开发中如何获取UIImageView可见部分并转换为UIImage
UIImageView可见内容转UIImage实现方案
原有代码问题排查
原有代码无法正常运行的核心原因如下:
- 使用
UIGraphicsBeginImageContext初始化上下文时未传入缩放参数,默认缩放因子为1,在Retina屏幕上生成的图片会出现模糊问题 - 执行
context.rotate(by: 2 * .pi)属于无效操作,也没有处理CoreGraphics坐标系与UIKit坐标系上下翻转的差异,会导致生成的图片倒置 - 直接渲染UIImageView的layer会把背景色、边框等不属于图像本身的装饰元素也一同渲染,不符合图片裁剪的需求
UI调试参考截图

修复后实现代码
场景1:需要导出UIImageView完整可见内容(包含背景、边框等装饰元素)
推荐使用系统更稳定的UIGraphicsImageRenderer替代旧的上下文操作API:
func imageFromImageView(imageView: UIImageView) -> UIImage? { let renderFormat = UIGraphicsImageRendererFormat() renderFormat.scale = UIScreen.main.scale let renderer = UIGraphicsImageRenderer(size: imageView.bounds.size, format: renderFormat) return renderer.image { context in imageView.layer.render(in: context.cgContext) } }
场景2:仅需要裁剪UIImageView中显示的图像内容(排除view自身装饰元素,适配contentMode)
这是图片裁剪功能的常用场景,实现如下:
func croppedVisibleImage(from imageView: UIImageView) -> UIImage? { guard let originImage = imageView.image else { return nil } let viewSize = imageView.bounds.size let imageSize = originImage.size var scale: CGFloat = 1.0 var imageDisplayRect: CGRect = .zero // 根据contentMode计算图片实际显示的位置和缩放比例 switch imageView.contentMode { case .scaleAspectFill: scale = max(viewSize.width / imageSize.width, viewSize.height / imageSize.height) imageDisplayRect.size = CGSize(width: imageSize.width * scale, height: imageSize.height * scale) imageDisplayRect.origin.x = (viewSize.width - imageDisplayRect.width) / 2 imageDisplayRect.origin.y = (viewSize.height - imageDisplayRect.height) / 2 case .scaleAspectFit: scale = min(viewSize.width / imageSize.width, viewSize.height / imageSize.height) imageDisplayRect.size = CGSize(width: imageSize.width * scale, height: imageSize.height * scale) imageDisplayRect.origin.x = (viewSize.width - imageDisplayRect.width) / 2 imageDisplayRect.origin.y = (viewSize.height - imageDisplayRect.height) / 2 default: imageDisplayRect = CGRect(origin: .zero, size: viewSize) scale = 1 } // 转换得到原始图片上的裁剪区域 let cropRect = CGRect( x: max(0, -imageDisplayRect.origin.x) / scale, y: max(0, -imageDisplayRect.origin.y) / scale, width: viewSize.width / scale, height: viewSize.height / scale ) guard let croppedCGImage = originImage.cgImage?.cropping(to: cropRect) else { return nil } return UIImage(cgImage: croppedCGImage, scale: originImage.scale, orientation: originImage.imageOrientation) }
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

