出于美观的原因,现在很多地方只要需要显示用户头像时都可能显示成圆形的,这时候就需要我们自己来处理,
说到把图片裁剪成圆角,首先想到的方法应该是设置图片layer的圆角半径
UIImageView *imageView = [[UIImageView alloc]init];
imageView.layer.cornerRadius = 10; imageView.layer.masksToBounds = YES;
但是稍微有点经验的都知道这种做法对性能特别不好,
所以就需要使用裁剪的方式把图片绘制到圆形区域,为了更好地使用,可以做成一个简单的工具类,UIImage的分类.
先说一下具体的步骤:
这里有两种方法,不过原理都基本相同,
第一种:
1>开启图形上下文
UIGraphicsBeginImageContextWithOptions(self.size, NO, 0.0);
2>获取到图形上下文
CGContextRef ctxref = UIGraphicsGetCurrentContext();
3>绘制一个圆形
CGRect rect = CGRectMake(0, 0, self.size.width, self.size.height);
CGContextAddEllipseInRect(ctxref, rect);
4>裁剪
CGContextClip(ctxref);
5>将图片画到圆形区域
[self drawInRect:rect];
6>获得他需要绘制的图片
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
7>关闭上下文
UIGraphicsEndImageContext();
第二种方法是利用贝塞尔曲线画圆
1>开启图形上下文
UIGraphicsBeginImageContextWithOptions(self.size, NO, 0.0);
2>绘制一个圆形
CGRect rect = CGRectMake(0, 0, self.size.width, self.size.height);
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:rect];
3>裁剪
[path addClip];
4>将图片画到圆形区域
[self drawInRect:rect];
5>获得需要绘制的图片
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
6>关闭上下文
UIGraphicsEndImageContext();
这两种基本上差不多,最后给他一个返回值Image,都可以实现想要的效果,
不过做到这里你可能认为已经OK了,但是我测试了一下,裁剪绘制大约需要0.1s,其实还是挺影响性能的,所以为了更好地优化,需要将他们放到子线程中去执行,
开启一个异步线程dispatch_async(dispatch_get_global_queue(0, 0),这样就可以把耗时操作放到子线程去做了,但是这样我们就不能确定什么时候才能获取到图片,使用image返回值就不可行了,需要在拿到image那一刻通知图片给他赋值,那么怎么办呢?
这时候就需要用到block,在方法中传入一个block参数,作为完成时的回调,
- (void)scricleImageCompleted:(void (^)(UIImage *image))complete;
当在上面 获得需要绘制图片 的那一步之后,调用block,
注意:调用前一定要先判断
if (complete != nil){
complete(image);
}
这样既可以获得圆形图片了,同时又可以保证性能,
写的不够好的地方望大神多指正,可以互相学习.
网友评论