在GIF图片上添加水印
最近项目中需要对图片(包括静态图和动图GIF)进行一些自定义的操作,比如添加文本,图片,或是其他页面元素。就此把所学分享出来。
Quartz2D
Quartz2D是苹果公司提供的二维绘图引擎,可以实现绘图,绘制文字,绘制图片,截图,裁剪图片等功能。
静态图:即把当前View上的所有东西保存成一个新的图片
func screenCapture(view: UIView)-> UIImage {
//创建一个位图的上下文
UIGraphicsBeginImageContextWithOptions(view.frame.size, false, 0)
//将view layer层上的东西渲染到当前上下文
view.layer.render(in: UIGraphicsGetCurrentContext()!)
//获取新图片
let image = UIGraphicsGetImageFromCurrentImageContext()
//关闭上下文
UIGraphicsEndImageContext()
return image!
}
这样我们通过将图片加载到UIImageView上,再在UIImageView添加子View(图片或是文本),
然后调用上面方法即可得到一张新的图片。
动态图:如果按照上述方法调用,只会得到一帧的图片,不是我们想要的效果。然后,动态图是由一张张静态图组成,
因此可以通过拆分图片,在每张图片添加自定义内容,然后再重新组成新的GIF图片。
func gifScreenCapture(rootView: UIImageView)-> UIImage {
//1.将rootview的子节点subview先变成image(这里假定只有一个子View)
let label = rootView.viewWithTag(1231) as! UILabel
let labelImage = screenCapture(view: label)
//2.将动图的每帧拆分,并在上面绘制其他图片
let image = rootView.image!
//获取图片相对于ImageView的比例,作为绘制其他内容的参照
let ratioX = image.size.width * 1.0 / rootView.frame.size.width
let ratioY = image.size.height * 1.0 / rootView.frame.size.height
//以image的实际尺寸设置位图上下文
UIGraphicsBeginImageContextWithOptions(image.size, false, 0)
var resultImages: [UIImage] = []
//设定子View相对于Image的坐标系
let newFrame = CGRect(x: label.frame.origin.x * ratioX,
y: label.frame.origin.y * ratioY,
width: label.frame.width * ratioX,
height: label.frame.height * ratioY)
image.images?.forEach({ (_image) in
let drawFrame = CGRect(x: 0,
y: 0,
width: image.size.width,
height: image.size.height)
//这里设置上下文(画布)的背景颜色为白色(可选)
//因为项目中GIF素材的每帧是没有背景的,所以最后拼成新图的时候有重影(这个问题困扰了很久,直到在xcode中看了下预览图才明白问题所在)
//如果有碰到重影的同学,这里可以检查下
let context = UIGraphicsGetCurrentContext()!
UIColor.white.setFill()
context.fill(drawFrame)
//将每帧图片重新绘制在画布上
_image.draw(in: drawFrame)
//将子View生成的image绘制在画布上
labelImage.draw(in: newFrame)
//重新绘制新的每帧图片
let imageSlice = UIGraphicsGetImageFromCurrentImageContext()
resultImages.append(imageSlice!)
})
UIGraphicsEndImageContext()
//3.将每帧图片重新合成动图
return UIImage.animatedImage(with: resultImages, duration: image.duration)!
}