在我们使用YYWebImage的过程中,常常会用到对图片的处理,其中圆角比较常用的,因此进一步了解这个是很有必要的。
[image yy_imageByRoundCornerRadius:5];
图片设置圆角
想想刚开始的时候,直接的是用:
imageView.layer.masksToBounds = YES;
imageView.layer.cornerRadius = 10.0;
后来开始我是使用贝塞尔曲线UIBezierPath和Core Graphics框架画出一个圆角的
// 使用贝塞尔曲线UIBezierPath和Core Graphics框架画出一个圆角
UIImageView *imageView = [[UIImageView alloc]initWithFrame:CGRectMake(100, 100, 100, 100)];
imageView.image =[ UIImage imageNamed:@"dog"];
UIGraphicsBeginImageContextWithOptions(imageView.frame.size, NO, 1.0);
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:imageView.bounds
cornerRadius:5];
[path addClip];
[imageView drawRect:imageView.bounds];
imageView.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[self.view addSubview:imageView];
后来也尝试用过CAShapeLayer和贝塞尔曲线UIBezierPath画圆角图片
// 使用CAShapeLayer和贝塞尔曲线UIBezierPath
UIImageView *imageView = [[UIImageView alloc]initWithFrame:CGRectMake(100, 300, 100, 100)];
imageView.image = [UIImage imageNamed:@"dog"];
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:imageView.bounds
byRoundingCorners:UIRectCornerAllCorners
cornerRadii:CGSizeMake(10, 1)];
CAShapeLayer *maskLayer = [[CAShapeLayer alloc]init];
maskLayer.frame = imageView.bounds;
maskLayer.path = maskPath.CGPath;
imageView.layer.mask = maskLayer;
[self.view addSubview:imageView];
然后再接着优化,UIImage 进行一个继承
@implementation UIImage (YSImage)
// 制作圆角
- (UIImage *)ys_imageByRoundCornerRadius:(CGFloat)cornerRadius {
// 防止圆角半径小于0,或者大于宽/高中较小值的一半。
if (cornerRadius < 0) {
cornerRadius = 0;
}
else if (cornerRadius > MIN(self.size.width, self.size.height)) {
cornerRadius = MIN(self.size.width, self.size.height) / 2;
}
CGRect imageFrame = CGRectMake(0, 0, self.size.width, self.size.height);
UIGraphicsBeginImageContextWithOptions(self.size, NO, self.scale);
[[UIBezierPath bezierPathWithRoundedRect:imageFrame cornerRadius:cornerRadius] addClip];
[self drawInRect:imageFrame];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
@end
此时再看看YYImage是怎样处理的呢?
- (UIImage *)yy_imageByRoundCornerRadius:(CGFloat)radius
corners:(UIRectCorner)corners
borderWidth:(CGFloat)borderWidth
borderColor:(UIColor *)borderColor
borderLineJoin:(CGLineJoin)borderLineJoin {
if (corners != UIRectCornerAllCorners) {
UIRectCorner tmp = 0;
if (corners & UIRectCornerTopLeft) tmp |= UIRectCornerBottomLeft;
if (corners & UIRectCornerTopRight) tmp |= UIRectCornerBottomRight;
if (corners & UIRectCornerBottomLeft) tmp |= UIRectCornerTopLeft;
if (corners & UIRectCornerBottomRight) tmp |= UIRectCornerTopRight;
corners = tmp;
}
UIGraphicsBeginImageContextWithOptions(self.size, NO, self.scale);
CGContextRef context = UIGraphicsGetCurrentContext();
CGRect rect = CGRectMake(0, 0, self.size.width, self.size.height);
CGContextScaleCTM(context, 1, -1);
CGContextTranslateCTM(context, 0, -rect.size.height);
CGFloat minSize = MIN(self.size.width, self.size.height);
if (borderWidth < minSize / 2) {
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectInset(rect, borderWidth, borderWidth) byRoundingCorners:corners cornerRadii:CGSizeMake(radius, borderWidth)];
[path closePath];
CGContextSaveGState(context);
[path addClip];
CGContextDrawImage(context, rect, self.CGImage);
CGContextRestoreGState(context);
}
if (borderColor && borderWidth < minSize / 2 && borderWidth > 0) {
CGFloat strokeInset = (floor(borderWidth * self.scale) + 0.5) / self.scale;
CGRect strokeRect = CGRectInset(rect, strokeInset, strokeInset);
CGFloat strokeRadius = radius > self.scale / 2 ? radius - self.scale / 2 : 0;
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:strokeRect byRoundingCorners:corners cornerRadii:CGSizeMake(strokeRadius, borderWidth)];
[path closePath];
path.lineWidth = borderWidth;
path.lineJoinStyle = borderLineJoin;
[borderColor setStroke];
[path stroke];
}
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
总的说来就是这边是考虑相当全面的,对 corners、borderWidth、 borderColor、borderLineJoin 都进行处理啦,另外对比了之前我个人没使用的方法:
* CGContextScaleCTM(context, 1, -1); // 用于缩放图像(传值)
* CGContextTranslateCTM(context, 0, -rect.size.height); //用于平移图像
由于Core Graphics默认使用 LLO(左下角为原点)的坐标系统的,所以用让 UIKit 适应 Core Graphics,则需要做上述处理。
- CGContextSaveGState(context); // 保存模式状态
- CGContextDrawImage(context, rect, self.CGImage); // 将图像绘制到指定的context
- CGContextRestoreGState(context); // 还原模式状态
另外需要添加颜色的时候,当然是直接划线啦。
总之,其实这是对Graphics Context的初步使用,需要直白的了解更多的zhi,可去读读iOS中的图形变换,同时我的UIBezierPath也可以顺便看看,哈哈。