iOS 生成一张半透明图片
最近遇到一个需求,需要添加一个个性签名,而且在签名之后,还需要沿着签名生成一张透明背景的图片。也就是说,透明背景的图片完全沿着签名的边缘进行裁切的。
基于懒的原则,还是先看看其他人怎么做的吧,然而从网上游荡了一圈,仍然没有看到有人有类似的操作。实在没办法了,只能自己动手了。
本人的想法就是基于贝塞尔曲线来进行完成,毕竟用户能够随意画图,那就贝塞尔曲线来吧。经过查看API,发现UIBezierPath的有一个bounds属性,对应CGRect,应该是能正好获取边缘裁切。
OK,一切准备就绪,直接开始撸代码。
// 声明一个绘制
UIGraphicsBeginImageContext(path.bounds.size);
// 获取上下文对象
CGContextRef context = UIGraphicsGetCurrentContext();
// 绘制
CGContextAddPath(context, path.CGPath);
// 设置填充颜色
CGContextSetFillColorWithColor(context, [UIColor colorWithWhite:0 alpha:0].CGColor);
CGContextFillRect(context, path.bounds);
// [[UIColor redColor] setStroke];
[path stroke];
// 声明UIImage对象
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
喜滋滋的去查看效果,然后……嗯?怎么效果差别那么远?说好的透明背景图片呢?说好的内切图呢?没办法,只能继续想办法解决。
首先先看透明背景,没想到会是白色??具体没有深入去想,不过,好在解决起来也不是十分复杂。至于网上一些说修改图片的背景颜色什么的,想想还是算了,为什么不直接就生成一张透明颜色的背景图呢?他们都是同样的Color对象嘛。
//设置一个透明的颜色
UIColor * color = [UIColor clearColor];
//使用上面设置的颜色进行填充.
[color setFill];
这样就可以把我们的背景颜色改成透明色了,当然,保存到相册的时候,看到的底是白色,不过不要慌,你本身就没有背景颜色,看到的白色只是相册展示的背景颜色。
OK,美滋滋,第一个问题解决了,那么第二个问题来了,怎么得到内切的透明背景签名呢?仔细看的话,大概也有点思路,贝塞尔曲线在我图片上展示的和我在图上画的位置完全就是一样的嘛。打印一下bounds属性,发现人家直接就是有偏移的,也就是说类似于你一个View的frame属性。
到了这里,基本上就不用多说什么了,直接修改bounds属性吧。不过系统给的是只读,别慌,那我们试试KVC吧。结果……现实还是很残忍的,直接说找不到属性!特意去API文档和用runtime获取了一下属性列表,确实是存在的。
那没办法了,到了这里,我的想法就是直接先画一个从(0, 0)坐标到签名(maxX, maxY)坐标点那么大的一张图,然后再根据bounds属性提供的大小,裁切第二次获取新的图片了。
//开启一个图片上下文.设置较大背景(苹果不允许修改bounds属性)
CGSize tsize = CGSizeMake(CGRectGetMaxX(path.bounds), CGRectGetMaxY(path.bounds));
UIGraphicsBeginImageContext(tsize);
//设置一个透明的颜色
UIColor * color = [UIColor clearColor];
//使用上面设置的颜色进行填充.
[color setFill];
// 获取上下文对象
CGContextRef context = UIGraphicsGetCurrentContext();
// 绘制
CGContextAddPath(context, path.CGPath);
[[UIColor redColor] setStroke];
[self.signView.bezier stroke];
//从图片上下文中获取图片.
UIImage * image = UIGraphicsGetImageFromCurrentImageContext();
CGImageRef subImageRef = CGImageCreateWithImageInRect(image.CGImage, path.bounds);
UIGraphicsBeginImageContext(path.bounds.size);
CGContextRef context2 = UIGraphicsGetCurrentContext();
CGContextDrawImage(context2, path.bounds, subImageRef);
image = [UIImage imageWithCGImage:subImageRef];
UIGraphicsEndImageContext();
CGImageRelease(subImageRef);
//设置图片的存储路径.
// NSString * filepath = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/1.png"];
//将图片转换为png格式的数据,并且写入到后面的路径内.
// [UIImagePNGRepresentation(image) writeToFile:filepath atomically:YES];
//关闭图片上下文,否则会造成内存泄露.
UIGraphicsEndImageContext();
OK,查看效果,非常棒。探索就到这里了,完工。
传送门