本文是
IOS Quart2D繪圖之UIGraphicsGetCurrentContext基礎(chǔ)的續(xù)集
主要是看看圖形上下文
內(nèi)容不多扣草,包括
- 水恿伺!:給圖片添加水印(文字和圖片水映矫睢)
- 裁剪:裁剪圓形圖片(帶邊框或者不帶)
- 截屏:截取當(dāng)前屏幕
- 擦除:這個(gè)不知道怎么描述....
OK鹰祸,為了方便使用,我都寫在Image的分類中了密浑,拿出來就可以使用蛙婴!
1、圖形上下文:主要是對(duì)圖片進(jìn)行處理尔破,操作步驟基本如下街图,可在 2 之前或者之后對(duì)上下文進(jìn)行處理
- 1 開啟一個(gè)圖形上下文
- 2 繪制圖片
- 3 從當(dāng)前上下文獲取新的圖片
- 4 關(guān)閉上下文
+ (UIImage *)pq_drawImageWithImageNamed:(NSString *)name{
//1.獲取圖片
UIImage *image = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:name ofType:nil]];
//2.開啟圖形上下文
UIGraphicsBeginImageContext(image.size);
//3.繪制到圖形上下文中
[image drawInRect:CGRectMake(0, 0, image.size.width, image.size.height)];
//4.從上下文中獲取圖片
UIImage * newImage = UIGraphicsGetImageFromCurrentImageContext();
//5.關(guān)閉圖形上下文
UIGraphicsEndImageContext();
//返回圖片
return newImage;
}
.
2、給圖片添加文字水永凉埂:
- 1 開啟一個(gè)圖形上下文
- 2 繪制圖片
- 3 把文字繪制到當(dāng)前上下文
- 4 從當(dāng)前上下文獲取新的圖片
- 5 關(guān)閉上下文
+ (UIImage *)pq_WaterImageWithImage:(UIImage *)image text:(NSString *)text textPoint:(CGPoint)point attributedString:(NSDictionary * )attributed{
//1.開啟上下文
UIGraphicsBeginImageContextWithOptions(image.size, NO, 0);
//2.繪制圖片
[image drawInRect:CGRectMake(0, 0, image.size.width, image.size.height)];
//添加水印文字
[text drawAtPoint:point withAttributes:attributed];
//3.從上下文中獲取新圖片
UIImage * newImage = UIGraphicsGetImageFromCurrentImageContext();
//4.關(guān)閉圖形上下文
UIGraphicsEndImageContext();
//返回圖片
return newImage;
}
3餐济、給圖片添加圖片水印:
- 1 開啟一個(gè)圖形上下文
- 2 繪制圖片
- 3 把水印圖片繪制到當(dāng)前上下文
- 4 從當(dāng)前上下文獲取新的圖片
- 5 關(guān)閉上下文
+ (UIImage *)pq_WaterImageWithImage:(UIImage *)image waterImage:(UIImage *)waterImage waterImageRect:(CGRect)rect{
//1.獲取圖片
//2.開啟上下文
UIGraphicsBeginImageContextWithOptions(image.size, NO, 0);
//3.繪制背景圖片
[image drawInRect:CGRectMake(0, 0, image.size.width, image.size.height)];
//繪制水印圖片到當(dāng)前上下文
[waterImage drawInRect:rect];
//4.從上下文中獲取新圖片
UIImage * newImage = UIGraphicsGetImageFromCurrentImageContext();
//5.關(guān)閉圖形上下文
UIGraphicsEndImageContext();
//返回圖片
return newImage;
}
4痴脾、裁剪圓形圖片:
- 1 開啟一個(gè)圖形上下文
- 2 設(shè)置裁剪區(qū)域
- 3 把圖片繪制到當(dāng)前上下文
- 4 從當(dāng)前上下文獲取新的圖片
- 5 關(guān)閉上下文
+ (nullable UIImage *)pq_ClipCircleImageWithImage:(nullable UIImage *)image circleRect:(CGRect)rect{
//1颤介、開啟上下文
UIGraphicsBeginImageContextWithOptions(image.size, NO, 0);
//2梳星、設(shè)置裁剪區(qū)域
UIBezierPath * path = [UIBezierPath bezierPathWithOvalInRect:rect];
[path addClip];
//3赞赖、繪制圖片
[image drawAtPoint:CGPointZero];
//4滚朵、獲取新圖片
UIImage * newImage = UIGraphicsGetImageFromCurrentImageContext();
//5、關(guān)閉上下文
UIGraphicsEndImageContext();
//6前域、返回新圖片
return newImage;
}
5辕近、裁剪帶邊框的圓形圖片:
- 1 開啟一個(gè)圖形上下文
- 2 設(shè)置邊框
- 3 設(shè)置裁剪區(qū)域
- 4 把圖片繪制到當(dāng)前上下文
- 5 從當(dāng)前上下文獲取新的圖片
- 6 關(guān)閉上下文
+ (nullable UIImage *)pq_ClipCircleImageWithImage:(nullable UIImage *)image circleRect:(CGRect)rect borderWidth:(CGFloat)borderW borderColor:(nullable UIColor *)borderColor{
//1、開啟上下文
UIGraphicsBeginImageContext(image.size);
//2匿垄、設(shè)置邊框
UIBezierPath * path = [UIBezierPath bezierPathWithOvalInRect:rect];
[borderColor setFill];
[path fill];
//3移宅、設(shè)置裁剪區(qū)域
UIBezierPath * clipPath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(rect.origin.x + borderW , rect.origin.x + borderW , rect.size.width - borderW * 2, rect.size.height - borderW *2)];
[clipPath addClip];
//3、繪制圖片
[image drawAtPoint:CGPointZero];
//4椿疗、獲取新圖片
UIImage * newImage = UIGraphicsGetImageFromCurrentImageContext();
//5漏峰、關(guān)閉上下文
UIGraphicsEndImageContext();
//6、返回新圖片
return newImage;
}
6届榄、截屏:
- 1 開啟一個(gè)圖形上下文
- 2 獲取當(dāng)前上下文
- 3 截屏浅乔,渲染到當(dāng)前上下文中,這里使用繪制無效铝条,可自行測(cè)試
- 4 從當(dāng)前上下文獲取新的圖片
- 5 把圖片轉(zhuǎn)化成為NSData類型
- 6 關(guān)閉上下文
- 7 把新的圖片和NSData類型直接放回靖苇,便于顯示和保存截屏
+ (void)pq_cutScreenWithView:(nullable UIView *)view successBlock:(nullable void(^)(UIImage * _Nullable image,NSData * _Nullable imagedata))block{
//1、開啟上下文
UIGraphicsBeginImageContext(view.bounds.size);
//2.獲取當(dāng)前上下文
CGContextRef ctx = UIGraphicsGetCurrentContext();
//3.截屏
[view.layer renderInContext:ctx];
//4班缰、獲取新圖片
UIImage * newImage = UIGraphicsGetImageFromCurrentImageContext();
//5.轉(zhuǎn)化成為Data
//compressionQuality:表示壓縮比 0 - 1的取值范圍
NSData * data = UIImageJPEGRepresentation(newImage, 1);
//6贤壁、關(guān)閉上下文
UIGraphicsEndImageContext();
//7.回調(diào)
block(newImage,data);
}
7、擦除:
-
1 計(jì)算當(dāng)前擦除區(qū)域的大小位置:
- 2 開啟上下文
- 3 獲取當(dāng)前上下文
- 4 把圖片繪制到當(dāng)前上下文
- 5 裁剪出透明區(qū)域
- 6 得到當(dāng)前上下文的圖片
- 7 關(guān)閉上下文
- 8 把圖片設(shè)置給前景ImageView
- (void)wipePanGestureEvent:(UIPanGestureRecognizer * )pan{
//計(jì)算位置
CGPoint nowPoint = [pan locationInView:self.wipeImageV];
CGFloat offsetX = nowPoint.x - 10;
CGFloat offsetY = nowPoint.y - 10;
CGRect clipRect = CGRectMake(offsetX, offsetY, 20, 20);
//開啟上下文
UIGraphicsBeginImageContextWithOptions(self.wipeImageV.bounds.size, NO, 1);
//獲取當(dāng)前的上下文
CGContextRef ctx = UIGraphicsGetCurrentContext();
//把圖片繪制上去
[self.wipeImageV.layer renderInContext:ctx];
//把這一塊設(shè)置為透明
CGContextClearRect(ctx, clipRect);
//獲取新的圖片
UIImage * newImage = UIGraphicsGetImageFromCurrentImageContext();
//關(guān)閉上下文
UIGraphicsEndImageContext();
//重新賦值圖片
self.wipeImageV.image = newImage;
}
為了代碼能復(fù)用埠忘,作者再次把這個(gè)代碼封裝到了Image類別中:
- (nullable UIImage *)pq_wipeImageWithView:(nullable UIView *)view currentPoint:(CGPoint)nowPoint size:(CGSize)size{
//計(jì)算位置
CGFloat offsetX = nowPoint.x - size.width * 0.5;
CGFloat offsetY = nowPoint.y - size.height * 0.5;
CGRect clipRect = CGRectMake(offsetX, offsetY, size.width, size.height);
//開啟上下文
UIGraphicsBeginImageContextWithOptions(view.bounds.size, NO, 1);
//獲取當(dāng)前的上下文
CGContextRef ctx = UIGraphicsGetCurrentContext();
//把圖片繪制上去
[view.layer renderInContext:ctx];
//把這一塊設(shè)置為透明
CGContextClearRect(ctx, clipRect);
//獲取新的圖片
UIImage * newImage = UIGraphicsGetImageFromCurrentImageContext();
//關(guān)閉上下文
UIGraphicsEndImageContext();
//重新賦值圖片
return newImage;
}
外面直接調(diào)用
//封裝后如下
self.wipeImageV.image = [self.wipeImageV.image pq_wipeImageWithView:self.wipeImageV currentPoint:[pan locationInView:self.wipeImageV] size:CGSizeMake(20, 20)];
效果圖如下:
沒擦除之前:
擦除之后:
8脾拆、圖片裁剪:
之前都是固定區(qū)域、固定形狀的裁剪莹妒,現(xiàn)在我們做一個(gè)自己選擇大小假丧,范圍的裁剪。
- 走一遍思想(個(gè)人想法动羽,如果你有更好的包帚,歡迎指正):
然后因?yàn)檫@個(gè)區(qū)域是自己控制大小的!
所以要建立一個(gè)View
移動(dòng):思路就是獲取當(dāng)前的點(diǎn)加上偏移量
實(shí)現(xiàn)方法有兩種运吓,一種是添加Pan事件渴邦,一種直接重寫touches系列方法
我采用后者。
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
UITouch * touch = [touches anyObject];
//得到按下去的點(diǎn)
_startP = [touch locationInView:self];
}
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
UITouch * touch = [touches anyObject];
CGPoint curP = [touch locationInView:self];
//計(jì)算偏移量
CGFloat x = curP.x - _startP.x;
CGFloat y = curP.y - _startP.y;
//限制范圍 不允許超出屏幕
self.x += x;
if (self.x <=0) {
self.x = 0;
}
self.y += y;
if (self.y <= 0) {
self.y = 0;
}
//范圍判斷
[self ifOut];
}
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
}
大小變換:
- (IBAction)sizePan:(UIPanGestureRecognizer *)sender {
switch (sender.state) {
case UIGestureRecognizerStateBegan:
_sizeStartP = [sender locationInView:self];
oldSize = self.size;
break;
case UIGestureRecognizerStateChanged:
{
CGPoint curP = [sender locationInView:self ];
CGFloat w = curP.x - _sizeStartP.x;
CGFloat h = curP.y - _sizeStartP.y;
self.width = oldSize.width + w;
self.height = oldSize.height + h;
[self ifOut];
}
break;
default:
break;
}
}
剪切過程:
+ (void)pq_cutScreenWithView:(nullable UIView *)view cutFrame:(CGRect)frame successBlock:(nullable void(^)(UIImage * _Nullable image,NSData * _Nullable imagedata))block{
//先把裁剪區(qū)域上面顯示的層隱藏掉
for (PQWipeView * wipe in view.subviews) {
[wipe setHidden:YES];
}
// ************************ 進(jìn)行第一次裁剪 ********************
//1.開啟上下文
UIGraphicsBeginImageContext(view.frame.size);
//2拘哨、獲取當(dāng)前的上下文
CGContextRef ctx = UIGraphicsGetCurrentContext();
//3谋梭、添加裁剪區(qū)域
UIBezierPath * path = [UIBezierPath bezierPathWithRect:frame];
[path addClip];
//4、渲染
[view.layer renderInContext:ctx];
//5倦青、從上下文中獲取
UIImage * newImage = UIGraphicsGetImageFromCurrentImageContext();
//7瓮床、關(guān)閉上下文
UIGraphicsEndImageContext();
//8、進(jìn)行完第一次裁剪之后,我們就已經(jīng)拿到了沒有半透明層的圖片隘庄,這個(gè)時(shí)候可以恢復(fù)顯示
for (PQWipeView * wipe in view.subviews) {
[wipe setHidden:NO];
}
// ************************ 進(jìn)行第二次裁剪 ********************
//9踢步、開啟上下文,這個(gè)時(shí)候的大小就是我們最終要顯示圖片的大小
UIGraphicsBeginImageContextWithOptions(frame.size, NO, 0);
//10丑掺、這里把x y 坐標(biāo)向左获印、上移動(dòng)
[newImage drawAtPoint:CGPointMake(- frame.origin.x, - frame.origin.y)];
//11、得到要顯示區(qū)域的圖片
UIImage * fImage = UIGraphicsGetImageFromCurrentImageContext();
//12街州、得到data類型 便于保存
NSData * data2 = UIImageJPEGRepresentation(fImage, 1);
//13兼丰、關(guān)閉上下文
UIGraphicsEndImageContext();
//14、回調(diào)
block(fImage,data2);
}
這里在說說二次裁剪吧:
效果圖:
原始大兴艚伞:
改變之后
點(diǎn)擊裁剪:
裁減之后:
沙河路徑: