iOS Quart2D繪圖之UIGraphicsBeginImageContextWithOptions基礎
阿新 • • 發佈:2019-01-26
主要是看看圖形上下文
如果你看到了這裡
內容不多,包括
- 水印:給圖片新增水印(文字和圖片水印)
- 裁剪:裁剪圓形圖片(帶邊框或者不帶)
- 截圖:擷取當前螢幕
- 擦除:這個不知道怎麼描述....
不知怎麼描述擦除
.
.
OK,為了方便使用,我都寫在Image的分類中了,拿出來就可以使用!
.
.
.
.
.
.
1、圖形上下文:主要是對圖片進行處理,操作步驟基本如下,可在 2 之前或者之後對上下文進行處理
- 1 開啟一個圖形上下文
- 2 繪製圖片
- 3 從當前上下文獲取新的圖片
- 4 關閉上下文
+ (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.關閉圖形上下文
UIGraphicsEndImageContext();
//返回圖片
return newImage;
}
3.png
.
.
.
.
2、給圖片新增文字水印:
- 1 開啟一個圖形上下文
- 2 繪製圖片
- 3 把文字繪製到當前上下文
- 4 從當前上下文獲取新的圖片
- 5 關閉上下文
+ (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.關閉圖形上下文
UIGraphicsEndImageContext();
//返回圖片
return newImage;
}
4.png
.
.
.
.
3、給圖片新增圖片水印:
- 1 開啟一個圖形上下文
- 2 繪製圖片
- 3 把水印圖片繪製到當前上下文
- 4 從當前上下文獲取新的圖片
- 5 關閉上下文
+ (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)];
//繪製水印圖片到當前上下文
[waterImage drawInRect:rect];
//4.從上下文中獲取新圖片
UIImage * newImage = UIGraphicsGetImageFromCurrentImageContext();
//5.關閉圖形上下文
UIGraphicsEndImageContext();
//返回圖片
return newImage;
}
5.png
.
.
.
.
4、裁剪圓形圖片:
- 1 開啟一個圖形上下文
- 2 設定裁剪區域
- 3 把圖片繪製到當前上下文
- 4 從當前上下文獲取新的圖片
- 5 關閉上下文
+ (nullable UIImage *)pq_ClipCircleImageWithImage:(nullable UIImage *)image circleRect:(CGRect)rect{
//1、開啟上下文
UIGraphicsBeginImageContextWithOptions(image.size, NO, 0);
//2、設定裁剪區域
UIBezierPath * path = [UIBezierPath bezierPathWithOvalInRect:rect];
[path addClip];
//3、繪製圖片
[image drawAtPoint:CGPointZero];
//4、獲取新圖片
UIImage * newImage = UIGraphicsGetImageFromCurrentImageContext();
//5、關閉上下文
UIGraphicsEndImageContext();
//6、返回新圖片
return newImage;
}
6.png
.
.
.
.
5、裁剪帶邊框的圓形圖片:
- 1 開啟一個圖形上下文
- 2 設定邊框
- 3 設定裁剪區域
- 4 把圖片繪製到當前上下文
- 5 從當前上下文獲取新的圖片
- 6 關閉上下文
+ (nullable UIImage *)pq_ClipCircleImageWithImage:(nullable UIImage *)image circleRect:(CGRect)rect borderWidth:(CGFloat)borderW borderColor:(nullable UIColor *)borderColor{
//1、開啟上下文
UIGraphicsBeginImageContext(image.size);
//2、設定邊框
UIBezierPath * path = [UIBezierPath bezierPathWithOvalInRect:rect];
[borderColor setFill];
[path fill];
//3、設定裁剪區域
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、關閉上下文
UIGraphicsEndImageContext();
//6、返回新圖片
return newImage;
}
7.png
.
.
.
.
6、截圖:
- 1 開啟一個圖形上下文
- 2 獲取當前上下文
- 3 截圖,渲染到當前上下文中,這裡使用繪製無效,可自行測試
- 4 從當前上下文獲取新的圖片
- 5 把圖片轉化成為NSData型別
- 6 關閉上下文
- 7 把新的圖片和NSData型別直接放回,便於顯示和儲存截圖
+ (void)pq_cutScreenWithView:(nullable UIView *)view successBlock:(nullable void(^)(UIImage * _Nullable image,NSData * _Nullable imagedata))block{
//1、開啟上下文
UIGraphicsBeginImageContext(view.bounds.size);
//2.獲取當前上下文
CGContextRef ctx = UIGraphicsGetCurrentContext();
//3.截圖
[view.layer renderInContext:ctx];
//4、獲取新圖片
UIImage * newImage = UIGraphicsGetImageFromCurrentImageContext();
//5.轉化成為Data
//compressionQuality:表示壓縮比 0 - 1的取值範圍
NSData * data = UIImageJPEGRepresentation(newImage, 1);
//6、關閉上下文
UIGraphicsEndImageContext();
//7.回撥
block(newImage,data);
}
8.png
9.png
.
.
.
.
7、擦除:
10.png
1 計算當前擦除區域的大小位置:
11.png2 開啟上下文
3 獲取當前上下文
4 把圖片繪製到當前上下文
5 裁剪出透明區域
6 得到當前上下文的圖片
7 關閉上下文
8 把圖片設定給前景ImageView
- (void)wipePanGestureEvent:(UIPanGestureRecognizer * )pan{
//計算位置
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);
//獲取當前的上下文
CGContextRef ctx = UIGraphicsGetCurrentContext();
//把圖片繪製上去
[self.wipeImageV.layer renderInContext:ctx];
//把這一塊設定為透明
CGContextClearRect(ctx, clipRect);
//獲取新的圖片
UIImage * newImage = UIGraphicsGetImageFromCurrentImageContext();
//關閉上下文
UIGraphicsEndImageContext();
//重新賦值圖片
self.wipeImageV.image = newImage;
}
為了程式碼能複用,作者再次把這個程式碼封裝到了Image類別中:
- (nullable UIImage *)pq_wipeImageWithView:(nullable UIView *)view currentPoint:(CGPoint)nowPoint size:(CGSize)size{
//計算位置
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);
//獲取當前的上下文
CGContextRef ctx = UIGraphicsGetCurrentContext();
//把圖片繪製上去
[view.layer renderInContext:ctx];
//把這一塊設定為透明
CGContextClearRect(ctx, clipRect);
//獲取新的圖片
UIImage * newImage = UIGraphicsGetImageFromCurrentImageContext();
//關閉上下文
UIGraphicsEndImageContext();
//重新賦值圖片
return newImage;
}
外面直接呼叫
//封裝後如下
self.wipeImageV.image = [self.wipeImageV.image pq_wipeImageWithView:self.wipeImageV currentPoint:[pan locationInView:self.wipeImageV] size:CGSizeMake(20, 20)];
效果圖如下:
沒擦除之前:
擦除之前
擦除之後:
擦除之後
效果圖
.
.
.
.
8、圖片裁剪:
之前都是固定區域、固定形狀的裁剪,現在我們做一個自己選擇大小,範圍的裁剪。
- 走一遍思想(個人想法,如果你有更好的,歡迎指正):
思路
然後因為這個區域是自己控制大小的!
所以要建立一個View
移動:思路就是獲取當前的點加上偏移量
圖片
實現方法有兩種,一種是新增Pan事件,一種直接重寫touches系列方法
我採用後者。
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
UITouch * touch = [touches anyObject];
//得到按下去的點
_startP = [touch locationInView:self];
}
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
UITouch * touch = [touches anyObject];
CGPoint curP = [touch locationInView:self];
//計算偏移量
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{
//先把裁剪區域上面顯示的層隱藏掉
for (PQWipeView * wipe in view.subviews) {
[wipe setHidden:YES];
}
// ************************ 進行第一次裁剪 ********************
//1.開啟上下文
UIGraphicsBeginImageContext(view.frame.size);
//2、獲取當前的上下文
CGContextRef ctx = UIGraphicsGetCurrentContext();
//3、新增裁剪區域
UIBezierPath * path = [UIBezierPath bezierPathWithRect:frame];
[path addClip];
//4、渲染
[view.layer renderInContext:ctx];
//5、從上下文中獲取
UIImage * newImage = UIGraphicsGetImageFromCurrentImageContext();
//7、關閉上下文
UIGraphicsEndImageContext();
//8、進行完第一次裁剪之後,我們就已經拿到了沒有半透明層的圖片,這個時候可以恢復顯示
for (PQWipeView * wipe in view.subviews) {
[wipe setHidden:NO];
}
// ************************ 進行第二次裁剪 ********************
//9、開啟上下文,這個時候的大小就是我們最終要顯示圖片的大小
UIGraphicsBeginImageContextWithOptions(frame.size, NO, 0);
//10、這裡把x y 座標向左、上移動
[newImage drawAtPoint:CGPointMake(- frame.origin.x, - frame.origin.y)];
//11、得到要顯示區域的圖片
UIImage * fImage = UIGraphicsGetImageFromCurrentImageContext();
//12、得到data型別 便於儲存
NSData * data2 = UIImageJPEGRepresentation(fImage, 1);
//13、關閉上下文
UIGraphicsEndImageContext();
//14、回撥
block(fImage,data2);
}
這裡在說說二次裁剪吧:
二次裁剪
效果圖:
原始大小:
18.png
改變之後
19.png
點選裁剪:
20.png
裁減之後:
效果圖
沙河路徑:
終於寫完啦!!!!