iOS-创建位图上下文(Bitmap Graphics Cont
2019-11-11 本文已影响0人
Imkata
在CoreGraphics图形库里面说过,CoreGraphics提供了以下几种类型的图形上下文:
- 位图图形上下文:Bitmap Graphics Context
- PDF图形上下文:PDF Graphics Context
- window图形上下文:Window Graphics Context
- layer层图形上下文:Layer Graphics Context
- 打印图形上下文:Printer Graphics Context
在CoreGraphics图形库这一章,我们都是通过自定义View,在它的drawRect方法里面获取当前的上下文(Layer Graphics Context)来进行操作的,所以绘制的东西会显示到layer上面。
只要上下文不同,绘制的地方就不同。
下面我们介绍如何创建位图上下文(Bitmap Graphics Context),位图上下文其实可以理解为一个图片,我们获取到位图上下文可以进行好多图片相关的操作。
1. 创建位图上下文的方法
UIGraphicsBeginImageContext(<#CGSize size#>);
UIGraphicsBeginImageContextWithOptions(CGSize size, BOOL opaque, CGFloat scale)
//CGSize size:指定将来创建出来的bitmap的大小
//BOOL opaque:默认为YES,不透明,位图中没有绘制的区域会以黑色显示;NO代表透明,位图中没有绘制的区域会以透明显示;主要是用于绘图时进行性能优化的开关。
//CGFloat scale:代表缩放,0代表系统会自动设置根据当前设备的屏幕因数设置缩放因数
- 使用这两个方法同样都可以创建,但是使用第二个方法创建的图片清晰度和质量比较高。
- 创建出来的bitmap就对应一个UIImage对象。
简单举例,下面我们创建一个位图上下文,然后在这个位图上下文上画一个圆圈,然后把图片保存到本地桌面,代码如下:
- (void)viewDidLoad {
[super viewDidLoad];
//创建一个Bitmap上下文
//C语言的方法
//CGBitmapContextCreate(<#void *data#>, <#size_t width#>, <#size_t height#>, <#size_t bitsPerComponent#>, <#size_t bytesPerRow#>, <#CGColorSpaceRef space#>, <#CGBitmapInfo bitmapInfo#>)
//OC中封装的方法:
//方法1
//UIGraphicsBeginImageContext(<#CGSize size#>);
//方法2
UIGraphicsBeginImageContextWithOptions( CGSizeMake(200, 200), NO, 0);
//1.获取bitmap上下文
CGContextRef ctx = UIGraphicsGetCurrentContext();
//2.绘图(画一个圆)
CGContextAddEllipseInRect(ctx, CGRectMake(0, 0, 100, 100));
//3.渲染
CGContextStrokePath(ctx);
//4.获取生成的图片
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
//5.显示生成的图片到imageview
self.iv.image=image;
//6.保存绘制好的图片到文件中
// 先将图片转换为二进制数据,然后再将图片写到文件中
// UIImageJPEGRepresentation(image, 1); //第二个参数为保存的图片的效果
NSData *data = UIImagePNGRepresentation(image);
[data writeToFile:@"/Users/xujincheng/Desktop/abc.png" atomically:YES];
}
效果图如下:
图片.png
下面我们就通过创建位图上下文做一些其他有用的操作。
2. 图片裁剪圆形
给UIImage添加分类,实现传入一个图片,处理后,图片变成圆形有边框。
代码:
+(UIImage *)circleImageWithImageName:(NSString *)imageName borderColor:(UIColor *)borderColor borderWidth:(CGFloat)borderWidth{
//需求:从位图上下文,裁剪图片[裁剪成圆形,也添加圆形的边框],生成一张图片
// 获取要裁剪的图片
UIImage *img = [UIImage imageNamed:imageName];
CGRect imgRect = CGRectMake(0, 0, img.size.width, img.size.height);
// 1.创建位图上下文
UIGraphicsBeginImageContextWithOptions(img.size, NO, 0.0);
#warning 在自定义的view的drawRect方法里,调用UIGraphicsGetCurrentContext获取的上下文,是图层上下文(Layer Graphics Context)
// 1.1 获取位图上下文
CGContextRef bitmapContext = UIGraphicsGetCurrentContext();
// 2.往位图上下裁剪图片
// 2.1 指定一个圆形的路径,把圆形之外的剪切掉
CGContextAddEllipseInRect(bitmapContext, imgRect);
CGContextClip(bitmapContext);
// 2.2 添加图片
[img drawInRect:imgRect];
// 2.3 添加边框
// 设置边框的宽度
CGContextSetLineWidth(bitmapContext, borderWidth);
// 设置边框的颜色
[borderColor set];
CGContextAddEllipseInRect(bitmapContext, imgRect);
CGContextStrokePath(bitmapContext);
// 3.获取当前位图上下文的图片
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
// 4.结束位图编辑
UIGraphicsEndImageContext();
return newImage;
}
效果图:
圆形.png
3. 截屏
//屏幕截图
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
//截取当前vie成为一张图片
// 使用位图上下文
// 1.创建位图上下文
UIGraphicsBeginImageContext(self.view.bounds.size);
// 2.当前控制器的view画在位图上下文
// render 渲染
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
// 3.获取图片
UIImage *captureImg = UIGraphicsGetImageFromCurrentImageContext();
// 4.结束位图编辑
UIGraphicsEndImageContext();
//保存图片
NSData *imgData = UIImagePNGRepresentation(captureImg);
#warning 平时开发过程,图片保存是沙盒
[imgData writeToFile:@"/Users/xujincheng/Desktop/capture.png" atomically:YES];
}
4. 图片裁剪
#import "CircleImageController1.h"
@interface CircleImageController1 ()
@property (strong, nonatomic) UIImageView *imageV;
//开始时手指的点
@property (nonatomic, assign) CGPoint startP;
//覆盖上面灰色的View
@property (nonatomic, weak) UIView *coverV;
@end
@implementation CircleImageController1
- (void)viewDidLoad {
[super viewDidLoad];
self.title = @"图片裁剪";
self.imageV = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height)];
self.imageV.userInteractionEnabled = YES;
self.imageV.image = [UIImage imageNamed:@"haha.png"];
[self.view addSubview:self.imageV];
UIPanGestureRecognizer *ges = [[UIPanGestureRecognizer alloc] init];
[ges addTarget:self action:@selector(panAction:)];
[self.imageV addGestureRecognizer:ges];
}
//添加手势之后调用的方法
- (void)panAction:(UIPanGestureRecognizer *)pan {
//判断手势的状态
CGPoint curP = [pan locationInView:self.imageV];
if(pan.state == UIGestureRecognizerStateBegan) {
self.startP = curP;
} else if(pan.state == UIGestureRecognizerStateChanged) {
CGFloat x = self.startP.x;
CGFloat y = self.startP.y;
CGFloat w = curP.x - self.startP.x;
CGFloat h = curP.y - self.startP.y;
CGRect rect = CGRectMake(x, y, w, h);
//添加一个UIView
self.coverV.frame = rect;
} else if (pan.state == UIGestureRecognizerStateEnded) {
//把超过coverV的frame以外的内容裁剪掉
//生成了一张图片,把原来的图片给替换掉.
UIGraphicsBeginImageContextWithOptions(self.imageV.bounds.size, NO, 0);
//把ImageV绘制到上下文之前,设置一个裁剪区域
UIBezierPath *clipPath = [UIBezierPath bezierPathWithRect:self.coverV.frame];
[clipPath addClip];
//把当前的ImageView渲染到上下文当中
CGContextRef ctx = UIGraphicsGetCurrentContext();
[self.imageV.layer renderInContext:ctx];
//.从上下文当中生成 一张图片
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
//关闭上下文
UIGraphicsEndImageContext();
self.imageV.image = newImage;
[self.coverV removeFromSuperview];
}
}
/**
* 懒加载coverV
* 1.能够保证超始至终只有一份
* 2.什么时候用到什么时候才去加载
*/
-(UIView *)coverV {
if (_coverV == nil) {
//添加一个UIView
UIView *coverV = [[UIView alloc] init];
coverV.backgroundColor = [UIColor blackColor];
coverV.alpha = 0.7;
_coverV = coverV;
[self.view addSubview:coverV];
}
return _coverV;
}
@end
效果图:
图片裁剪.png
5. 图片擦除
- (void)viewDidLoad {
[super viewDidLoad];
self.title = @"图片擦除";
self.imageV = [[UIImageView alloc] initWithFrame:CGRectMake(50, 100, 300, 300)];
self.imageV.image = [UIImage imageNamed:@"papa.png"];
self.imageV.userInteractionEnabled = YES;
[self.view addSubview:self.imageV];
//添加手势
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];
[self.imageV addGestureRecognizer:pan];
}
- (void)pan:(UIGestureRecognizer *)pan {
//获取当前手指的点
CGPoint curP = [pan locationInView:self.imageV];
//确定擦除区域
CGFloat rectWH = 30;
CGFloat x = curP.x - rectWH * 0.5;
CGFloat y = curP.y - rectWH * 0.5;
CGRect rect = CGRectMake(x, y, rectWH, rectWH);
//生成一张带有透明擦除区域的图片
//1.开启图片上下文
UIGraphicsBeginImageContextWithOptions(self.imageV.bounds.size, NO, 0);
//2.把UIImageV内容渲染到当前的上下文当中
CGContextRef ctx = UIGraphicsGetCurrentContext();
[self.imageV.layer renderInContext:ctx];
//3.擦除上下文当中的指定的区域
CGContextClearRect(ctx, rect);
//4.从上下文当中取出图片
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
//替换之前ImageView的图片
self.imageV.image = newImage;
}
效果图:
图片擦除.png
Demo地址:创建位图上下文