【swift】图片的编辑与合成

需求:
1.图片可放大缩小,旋转,与位移
2.贴纸贴图可放大缩小旋转位移,可同时添加多张
3.文字可放大缩小旋转位移,可同时添加多个,文字方向横竖切换等
4.所有元素都可镜像,其中图片贴纸跟文字贴纸可复制
5.最终按照给定的切割区域,把区域内的元素合成一张图片,并保证元素质量

最终效果图:Demo在最后


普通封面图

图片贴纸

文字贴纸

核心代码

镜像

/// 编辑图片
/// - Parameters:
///   - radians: 旋转的弧度
///   - isMirrorH: 是否水平镜像
///   - isMirrorV: 是否垂直镜像
/// - Returns: 编辑后的图片
func operate(radians: CGFloat = 0.0, isMirrorH: Bool = false, isMirrorV: Bool = false) -> UIImage {
	if radians == 0.0, !isMirrorH, !isMirrorV {
	    return self
	}
	var targetImage = self
	if isMirrorH {
	    // 水平镜像
	    targetImage = targetImage.flipH()
	}
	if isMirrorV {
	    // 垂直镜像
	    targetImage = targetImage.flipV()
	}
	return targetImage.rotate(radians: radians)
}

/// 旋转图片
/// - Parameter radians: 旋转弧度数
/// - Returns: 编辑后的图片
func rotate(radians: CGFloat = 0.0) -> UIImage {
	if radians == 0.0 {
	    return self
	}
	let imageRect = CGRect(origin: .zero, size: size)
	// 获取旋转后的图片尺寸大小
	var rotatedRect = imageRect.applying(CGAffineTransform(rotationAngle: CGFloat(radians))).integral
	rotatedRect.origin.x = 0
	rotatedRect.origin.y = 0
	// 开启画布 这里第三个参数 scale 出入0 系统会自动缩放
	UIGraphicsBeginImageContextWithOptions(rotatedRect.size, false, 0.0)
	guard let context = UIGraphicsGetCurrentContext() else { return self }
	// 把旋转点放在屏幕中心
	context.translateBy(x: rotatedRect.width / 2, y: rotatedRect.height / 2)
	context.rotate(by: radians)
	context.translateBy(x: -size.width / 2, y: -size.height / 2)
	// 开始绘画
	draw(at: .zero)
	// 获取图片
	let rotatedImage = UIGraphicsGetImageFromCurrentImageContext()
	UIGraphicsEndImageContext()
	return rotatedImage ?? self
}

///  水平镜像
/// - Returns: 处理过后的图片
func flipH() -> UIImage {
	return self.withHorizontallyFlippedOrientation()
}

/// 垂直镜像
/// - Returns: 处理过后的图片
func flipV() -> UIImage {
	// 先绕中心点旋转180度 然后再水平镜像
	return self.rotate(radians: CGFloat(Double.pi)).withHorizontallyFlippedOrientation()
}
图片合成

1.计算视图位置
利用 convert(_ rect: CGRect, to view: UIView?) -> CGRect 函数,计算出目标视图相对于待切割区域的位置

// 获取封面图相对于图纸文件的位置
let rect = self.editContainerView.convert(coverView.frame, to: self.dashCutView)

2.计算旋转角度
利用 atan2f(Float(view.transform.b), Float(view.transform.a))计算出视图当前位置的旋转角度,这里计算的是 -pi~pi 弧度数,顺时针是正数,逆时针是负数

// 这是图片旋转的角度 弧度数 
let degree = atan2f(Float(coverView.transform.b), Float(coverView.transform.a))

3.合成图片

  1. 第一步:开启画布
  2. 第二步:绘制封面图
  3. 第三步:循环出编辑区域内所有的图片贴图和文字贴图,绘制贴图
  4. 第四步:关闭画布
var kScale = 4.0
if DD_ScreenWidth <= 375.0 {
    kScale = 5.0
}
// 获取封面背景图
guard let coverImage = coverView.image else { return DDMBProgressHUD.showTipMessage("未获取到图片信息") }
/// 开启上下文
let fileSize = self.dashCutView.DD_size;
let targetSize = CGSize(width: fileSize.width*kScale, height: fileSize.height*kScale);
// 开启画布
UIGraphicsBeginImageContextWithOptions(targetSize, false, 0);
// 获取封面图相对于图纸文件的位置
let rect = self.editContainerView.convert(coverView.frame, to: self.dashCutView)
// 绘制封面图
// 这是图片旋转的角度 弧度数
let degree = atan2f(Float(coverView.transform.b), Float(coverView.transform.a))
// 获取切割的位置
let targetRect = CGRect(x: rect.origin.x*kScale, y: rect.origin.y*kScale, width: rect.size.width*kScale, height: rect.size.height*kScale)
let coverRotateImage = coverImage.operate(radians: CGFloat(degree), isMirrorH: coverView.isMirrorH, isMirrorV: coverView.isMirrorV)
coverRotateImage.draw(in: targetRect)

	// 绘制贴图和文字
for view in editContainerView.subviews {
    if view !== coverView {
	if view is DDBaseEditView {
	    let editView = view as! DDBaseEditView
	    // 获取贴图
	    if let tagImage = editView.image {
		let degree = atan2f(Float(editView.transform.b), Float(editView.transform.a))
		var targetRect: CGRect = .zero
		if editView.isTextView {
		    let editViewRect = self.editContainerView.layer.convert(editView.layer.frame, to: self.dashCutView.layer)
		    targetRect = CGRect(x: editViewRect.origin.x*kScale, y: editViewRect.origin.y*kScale, width: editViewRect.size.width*kScale, height: editViewRect.size.height*kScale)
		} else {
		    let editViewRect = self.editContainerView.convert(editView.frame, to: self.dashCutView)
		    targetRect = CGRect(x: editViewRect.origin.x*kScale, y: editViewRect.origin.y*kScale, width: editViewRect.size.width*kScale, height: editViewRect.size.height*kScale)
		}
		let tagRotateImage = tagImage.operate(radians: CGFloat(degree), isMirrorH: editView.isMirrorH, isMirrorV: editView.isMirrorV)
		tagRotateImage.draw(in: targetRect)
	    }
	}
    }
}

let resultImage = UIGraphicsGetImageFromCurrentImageContext()
/// 关闭画布
UIGraphicsEndImageContext();

特别提醒
旋转会影响视图的尺寸,但是layer层的尺寸是不会更改的,这点很重要,由于绘制文字视图的时候,我这边首先把文字绘制成了图片,然后再与图片贴纸一起绘制成图片,所以我这里使用的是layer的尺寸。可以在DDBaseViewimage属性查看。

最后附上Demo,如果觉得对您有帮助,大家可以多多Star,大家加油!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值