iOS --- CoreGraphics中三种绘图context切换方式的区别
来源:互联网 发布:qq三国张飞和关羽js 编辑:程序博客网 时间:2024/06/06 16:31
CoreGraphics的使用过程中,经常会遇到绘图context切换的操作,一般使用用到CGContextSaveGState/CGContextRestoreGState,UIGraphicsPushContext/UIGraphicsPopContext,UIGraphicsBeginImageContext/UIGraphicsEndImageContext这三对方法。
它们的区别如下:
CGContextSaveGState/CGContextRestoreGState
CGContextSaveGState/CGContextRestoreGState用于记录和恢复已存储的绘图context。
[[UIColor redColor] setStroke]; //画笔红色CGContextSaveGState(UIGraphicsGetCurrentContext()); //记录上下文的当前状态[[UIColor blackColor] setStroke]; //画笔黑色CGContextRestoreGState(UIGraphicsGetCurrentContext()); //恢复之前记录的上下文状态UIRectFill(CGRectMake(10, 10, 100, 100)); //绘制红色矩形
UIGraphicsPushContext/UIGraphicsPopContext
UIGraphicsPushContext/UIGraphicsPopContext的作用就完全不同了,而是完全地切换绘图context。使用场景是:
- 当前正在使用CoreGraphics绘制图形A,想要使用UIKit绘制完全不同的图形B,此时就希望保存当前绘图context及已绘制内容。
- 使用UIGraphicsPushContext切换到一个全新的绘图context。
- 使用UIKit绘制图形B。
- 使用UIGraphicsPopContext恢复之前的绘图context,继续使用CoreGraphics绘制图形A。
先看一段代码:
const CGFloat Scale = [UIScreen mainScreen].scale;GLsizei width = view.layer.bounds.size.width * Scale;GLsizei height = view.layer.bounds.size.height * Scale;GLubyte *imageData = (GLubyte *)calloc(width * height * 4, sizeof(GLubyte));CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();CGContextRef context = CGBitmapContextCreate(imageData, width, height, 8, width * 4, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);CGContextScaleCTM(context, Scale, Scale);UIGraphicsPushContext(context);{[view drawViewHierarchyInRect:view.layer.bounds afterScreenUpdates:NO];}UIGraphicsPopContext();CGContextRelease(context);CGColorSpaceRelease(colorSpace); free(texturePixelBuffer);
以上代码的步骤为:
- 初始化一块内存区域,用于存储图像纹理texture。建立绘图context。
- 因此时未能获取到所需要的图像UIImage,所以只能采用UIKit的截图方式,调用UIView的drawViewHierarchyInRect:afterScreenUpdates:从该view中截取图像。
- 截图完毕后,恢复到之前的绘图context。
注意步骤2,因为必须调用UIKit中的绘图方法,所以才需要用到UIGraphicsPushContext/UIGraphicsPopContext。类似的UIKit方法还有
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()]; // 将当前layer渲染到image context中// 绘制贝塞尔曲线UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, 100, 100));[[UIColor blueColor] setFill];[p fill];
这两种方法也是iOS中常见的截屏方法,但截取的图像有时未必足够清晰。
UIGraphicsBeginImageContext/UIGraphicsEndImageContext
如果想在切换绘图context后,继续使用CoreGraphics绘图(而非UIKit),则不需要使用UIGraphicsPushContext/UIGraphicsPopContext。因为CoreGraphics已将绘图context视为参数。使用场景是:
- 当前正在绘制图形A。
- 使用UIGraphicsBeginImageContext将旧的绘图context入栈,创建新的绘图context并使用。
- 绘制图形B。
- 结束绘制图形B之后,使用UIGraphicsEndImageContext恢复到之前的绘图context,继续绘制图形A。
例如,使用如下方法即可在一个绘图步骤中,切换到一个新的绘图context,完成截取view中图像的操作,然后再恢复之前的绘图步骤。
因新的绘图操作是使用UIGraphicsGetImageFromCurrentImageContext()截图,所以仍是CoreGraphics操作,因此不需要使用UIGraphicsPushContext/UIGraphicsPopContext。
// 绘图中UIGraphicsBeginImageContext(CGSizeMake(200, 200));[self.view drawViewHierarchyInRect:self.view.bounds afterScreenUpdates:YES];UIImage *snapshot = UIGraphicsGetImageFromCurrentImageContext();UIGraphicsEndImageContext();imageView.image = snapshot;// 继续绘图
类似的使用方法还有:
// 绘图中UIGraphicsBeginImageContext(CGSizeMake(200, 200));CGContextRef newContext = UIGraphicsGetCurrentContext();CGContextAddEllipseInRect(newContext, CGRectMake(0, 0, 100, 100));CGContextSetFillColorWithColor(newContext, [UIColor blueColor].CGColor);CGContextFillPath(newContext);UIGraphicsEndImageContext();// 继续绘图
注意,绘图context切换的关键是:要看切换新的绘图context后,是要继续使用CoreGraphics绘制图形,还是要使用UIKit。
- iOS --- CoreGraphics中三种绘图context切换方式的区别
- 【iOS】CoreGraphics简单绘图
- IOS开发:CoreGraphics简单绘图
- iOS绘图框架CoreGraphics分析
- iOS绘图框架CoreGraphics分析
- iOS绘图框架CoreGraphics分析
- iOS中 CoreGraphics快速绘图(详解) 韩俊强的博客
- iOS学习6:CoreGraphics简单绘图
- CoreGraphics之CGContext绘图 - iOS开发
- iOS学习6:CoreGraphics简单绘图
- iOS学习——CoreGraphics简单绘图
- iOS中 CoreGraphics快速绘图(详解)
- coreGraphics绘图
- ios-绘图的方式
- iOS绘图教程--Quartz 2D(CoreGraphics.framework) 详解
- iOS CoreAnimation(三)CoreGraphics绘图,drawRect,CALayerDelegate,displayLayer
- 关于CoreGraphics绘图
- CoreGraphics简单绘图
- Service#onStartCommand返回值解析
- LeetCode Find Minimum in Rotated Sorted Array II
- 记录一点开发经验
- 管理数据库和表
- Gson java对象和Json互转
- iOS --- CoreGraphics中三种绘图context切换方式的区别
- 数据结构(期末小结)——开始
- python中关于处理汉字乱码的问题
- System进程的启动过程
- 67.FMDB代码示例
- Android创建桌面快捷方式
- 关于Java.Lang.Spring.split()
- hdoj Reverse Number 1266 (字符串)水
- coreApp="true";android:sharedUserId="android.uid.system";android:process="system"