标签:
本篇博客主要是对官方文档的总结与补充。翻译部分参考了南峰子的博客。你可以在参考资料中查看。
Quartz 通过修改当前图形状态(current graphics state)来修改绘制操作的结果。图形状态包含用于绘制程序的参数。绘制程序根据这些绘图状态来决定如何渲染结果。
可使用函数CGContextSaveGState来保存图形状态,CGContextRestoreGState来还原图形状态。
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
CGContextRestoreGState(context);
Quartz 的坐标系与 UIKit 坐标系 Y 轴相反。
Quartz 通过使用当前转换矩阵(current transformation matrix, CTM)将一个独立的坐标系统(user space)映射到输出设备的坐标系统(device space),以此来解决设备依赖问题。
使用 UIGraphicsBeginImageContextWithOptions 返回的绘图上下文与UIKit 的坐标系统相同。
在 iOS 中,如果使用 UIImage 对象来包裹创建的 CGImage 对象,可以不需要修改 CTM。UIImage 将自动进行补偿以适用 UIKit 的坐标系统。
在 iOS 3.2 后,当 UIKit 为你的应用程序创建一个绘图上下文时,也对上下文进行了额外的修改以匹配 UIKit 的约定。
如果创建或拷贝一个对象,你将拥有它,因此你必须释放它。通常,如果使用含有”Create”或“Copy”单词的函数获取一个对象,当使用完后必须释放,否则将导致内存泄露。
如果使用不含有”Create”或“Copy”单词的函数获取一个对象,你将不会拥有对象的引用,不需要释放它。
如果你不拥有一个对象而打算保持它,则必须 retain 它并且在不需要时 release 掉。可以使用 Quartz2D 的函数来指定 retain 和 release 一个对象。例如,如果创建了一个 CGColorspace 对象,则使用函数 CGColorSpaceRetain 和 CGColorSpaceRelease 来 retain 和 release 对象。同样,可以使用 Core Foundation 的 CFRetain 和 CFRelease,但是注意不能传递 NULL 值给这些函数。
我们可以通过两种方式来获取 Graphics Context:Quartz提供的创建函数、OS X 框架或 iOS 的 UIKit 框架提供的函数。
在 iOS 应用程序中,如果要在屏幕上进行绘制,需要创建一个 UIView 对象,并实现它的 drawRect: 方法。
drawRect: 方法中视图对象将为当前的绘图环境创建一个 Graphics Context。我们可以通过调用 UIGraphicsGetCurrentContext 函数来获取这个 Graphics Context。
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetRGBFillColor(context, 1, 0, 0, 1);
CGContextFillRect(context, CGRectMake (0, 0, 200, 100));
CGContextSetRGBFillColor(context, 0, 0, 1, .5);
CGContextFillRect(context, CGRectMake (0, 0, 100, 200));
Quartz2D API 提供了两个函数来创建 PDF Graphics Context。
CGPDFContextCreateWithURL。当你需要用 Core Foundation URL 指定 PDF 输出的位置时使用该函数。
CGPDFContextCreate 当需要将pdf输出发送给数据用户时使用该方法。
UIGraphicsBeginImageContext([UIScreen mainScreen].bounds.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetRGBFillColor(context, 1, 0, 0, 1);
CGContextFillRect(context, CGRectMake (0, 0, 200, 100));
CGContextSetRGBFillColor(context, 0, 0, 1, .5);
CGContextFillRect(context, CGRectMake (0, 0, 100, 200));
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();//CGBitmapContextCreateImage(context)
UIGraphicsEndImageContext();
像素格式是在使用 CGBitmapContextCreate 创建 Bitmap Graphics Context 时需要指定的参数。
像素格式用 bpp(每像素的位数)和 bpc(每个组件的位数)来表示。
iOS 共支持 8 种像素格式。
我们可以通过调用 CGContextSetShouldAntialias 来关闭位图Graphics Context的反锯齿效果。反锯齿设置是图形状态的一部分。
可以调用函数CGContextSetAllowsAntialiasing来控制一个特定Graphics Context是否支持反锯齿;false表示不支持。该设置不是图形状态的一部分。当上下文及图形状态设置为true时,Quartz执行反锯齿。
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetShouldAntialias(context, YES);
CGContextSetAllowsAntialiasing(context, YES);
路径定义了一个或多个形状或者子路径。一个子路径可由直线,曲线,或者同时由两者构成。它可以是开放的,也可以是闭合的;可以是实线,可以是曲线;可以填充,也可以描边等等。
路径创建及路径绘制是两个独立的工作。首先我们创建路径。当我们需要渲染路径时,我们需要使用Quartz来绘制它。
调用 CGContextAddLineToPoint(context, 200, 200) 从起始点到指定点添加直线。
调用 CGContextAddLines(context, points, 3) 函数添加一系列相关的直线到子路径中。
调用 CGContextAddArc(context, 200, 200, 100, 0, M_PI_2, 0) 以指定圆心、半径、起始/终止角度、顺/逆时针画弧。
调用 CGContextAddArcToPoint(context, 200, 400, 400, 400, 100) 以当前点与指定的两个点连接的两条直线为切线画弧。
调用 CGContextAddQuadCurveToPoint(context, 0, 100, 200, 100) 以一个控制点画曲线。
调用 CGContextAddCurveToPoint(context, 100, 400, 200, 300, 100, 200) 以两个控制点画曲线。
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextMoveToPoint(context, 0, 0);
CGContextAddLineToPoint(context, 200, 200);
CGPoint point2 = CGPointMake(200, 200);
CGPoint point3 = CGPointMake(200, 400);
CGPoint point4 = CGPointMake(0, 200);
CGPoint points[3] = {point2, point3, point4};
CGContextAddLines(context, points, 3); // reset start point
CGContextAddArc(context, 200, 200, 100, 0, M_PI_2, 0);
CGContextAddArcToPoint(context, 200, 400, 400, 400, 100);
CGContextAddCurveToPoint(context, 100, 400, 200, 300, 100, 200);
CGContextAddQuadCurveToPoint(context, 0, 100, 200, 100);
CGContextClosePath(context);
CGContextAddEllipseInRect(context, CGRectMake(0, 0, 100, 200));
CGContextAddRect(context, CGRectMake(200, 400, 100, 200));
CGContextDrawPath(context, kCGPathStroke);
在开始绘制路径前,调用 CGContextBeginPath 或 UI。
直线、弧、曲线开始于当前点。空路径没有当前点;我们必须调用CGContextMoveToPoint来设置第一个子路径的起始点,或者调用一个便利函数来隐式地完成该任务。
如果要闭合当前子路径,调用函数 CGContextClosePath。随后路径将开始一个新的子路径,即使我们不显示设置一个新的起始点。
当绘制弧时,Quartz 将在当前点与弧的起始点间绘制一条直线。
添加椭圆和矩形的 Quartz 程序将在路径中添加新的闭合子路径。
我们必须调用绘制函数来填充或者描边一条路径,因为创建路径时并不会绘制路径。
Quartz 提供了两个数据类型来创建可复用路径 CGPathRef 和 CGMutablePathRef。
Quartz 提供了一个类似于操作图形上下文的 CGPath 的函数集合。这些路径函数操作 CGPath 对象,而不是图形上下文。
填充规则有两种:非零缠绕数规则(nonzero winding number rule)、偶数-奇数规则(even-odd rule)。
默认的填充规则为非零缠绕数规则。方法或枚举带有“EO”的为偶数-奇数规则。
非零缠绕数的填充规则与绘制的方向有关、偶数-奇数规则则与方向无关。如图。
调用 CGContextDrawPath(context, kCGPathFill) 填充路径。
调用 CGContextDrawPath(context, kCGPathEOFill) 使用奇偶规则填充路径。
调用 CGContextDrawPath(context, kCGPathStroke) 描边路径。
调用 CGContextDrawPath(context, kCGPathFillStroke) 填充并描边路径。
调用 CGContextDrawPath(context, kCGPathEOFillStroke) 使用奇偶规则填充并描边路径。
调用快捷方法 CGContextStrokePath(context) 来描边路径。
调用如下函数来快捷的创建形状路径并描边。
CGContextStrokeRect(context, CGRectMake(200, 400, 100, 200));
CGContextStrokeRectWithWidth(context, CGRectMake(200, 400, 100, 200), 2);
CGContextStrokeEllipseInRect(context, CGRectMake(200, 400, 100, 200));
CGPoint point2 = CGPointMake(200, 200);
CGPoint point3 = CGPointMake(200, 400);
CGPoint point4 = CGPointMake(100, 300);
CGPoint point5 = CGPointMake(300, 300);
CGPoint points[4] = {point2, point3, point4, point5};
CGContextStrokeLineSegments(context, points, 4);
调用快捷方法 CGContextFillPath(context) 或 CGContextEOFillPath(context) 填充路径。
CGContextStrokePath(context) 和 CGContextFillPath(context) 不能同时使用。
调用如下函数来快捷的创建形状路径并填充。
CGContextFillRect(context, CGRectMake(100, 100, 100, 200));
CGRect rects[2] = {CGRectMake(100, 100, 100, 200), CGRectMake(200, 300, 100, 200)};
CGContextFillRects(context, rects, 2);
CGContextFillEllipseInRect(context, CGRectMake(100, 100, 100, 200));
调用 CGContextSetBlendMode(context, kCGBlendModeNormal) 设置回合模式。
常用的混合模式:
原图
正片叠底
滤色
Quartz 中的颜色是用一组数值来表示。而颜色空间用于解析这些颜色信息,常用颜色空间有 RGB 、CMYK等。
Quartz 支持通用颜色空间、设备独立颜色空间、设备依赖颜色空间、索引颜色空间和模式(Pattern)颜色空间。
iOS不支持设备独立颜色空间和通用颜色空间。iOS应用程序必须使用设备颜色空间。
使用 CGContextSetAlpha(context, 0.2) 设置透明度。
使用 CGContextClearRect 清除上下文的 alpha 通道。
CGColorSpaceCreateDeviceGray() 创建设备依赖灰度颜色空间。
CGColorSpaceCreateDeviceRGB() 创建设备依赖RGB颜色空间。
CGColorSpaceCreateDeviceCMYK() 创建设备依赖CMYK颜色空间。
调用 CGContextSetFillColorSpace(context, colorSpace) 或 CGContextSetStrokeColorSpace(context, colorSpace) 设置颜色空间。
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextSetFillColorSpace(context, colorSpace);
CGContextSetStrokeColorSpace(context, colorSpace);
//Device RGB.
CGContextSetRGBStrokeColor(context, 1, 0, 0, 1);
CGContextSetRGBFillColor(context, 1, 0, 0, 1);
//Device CMYK.
CGContextSetCMYKStrokeColor(context, 1, 0, 0, 0, 1);
CGContextSetCMYKFillColor(context, 1, 0, 0, 0, 1);
//Device Gray.
CGContextSetGrayStrokeColor(context, 0.5, 1);
CGContextSetGrayFillColor(context, 0.5, 1);
//Any color space; you supply a CGColor object that specifies the color space. Use these functions for colors you need repeatedly.
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
CGFloat colors[4] = {1.0, 0.0, 0.0, 1.0};
CGColorRef color = CGColorCreate(colorSpace, colors);
CGContextSetStrokeColorWithColor(context, color);
CGContextSetFillColorWithColor(context, color);
//The current color space. Not recommended. Instead, set color using a CGColor object and the functions CGContextSetStrokeColorWithColor and CGContextSetFillColorWithColor.
CGContextSetStrokeColor(context, colors);
CGContextSetFillColor(context, colors);
CGContextSetFillColorWithColor(context, [UIColor redColor].CGColor);
CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor));
每个设备都有固定的可复制的颜色范围(gamut),这是设备的物理性质决定的。当图像从一个颜色空间向另一个颜色空间转换时,有些源设备颜色空间中呈现的颜色,不能在目标设备颜色空间中复制出来,这些不能复制的颜色叫色域外(out-of-gamut)颜色。比如 RGB 颜色空间比 CMYK 的颜色空间要大,有些在显示器上能显示的颜色不能在打印机上同样打印出来。因为我们不能在目标设备颜色空间中复制出色域外颜色,我们必须用一些其他颜色来替代他们。颜色空间转换时颜色替换调整的规则就是再现意图。更详细的说明可以查看 这里 和 这里
再现意图用于指定如何将源颜色空间的颜色映射到图形上下文的目标颜色空间的颜色范围内。
如果不显式的指定再现意图,Quartz 使用“相对色度再现意图”应用于所有绘制(不包含位图图像)。
对于位图图像,Quartz默认使用“感知再现意图”。
调用 CGContextSetRenderingIntent(context, kCGRenderingIntentDefault) 来设置再现意图。
再现意图共有以下 5 种。
typedef CF_ENUM (int32_t, CGColorRenderingIntent) {
kCGRenderingIntentDefault,
kCGRenderingIntentAbsoluteColorimetric,
kCGRenderingIntentRelativeColorimetric,
kCGRenderingIntentPerceptual,
kCGRenderingIntentSaturation
};
原文:http://xuyafei.cn/post/cocoatouch/quartz2d-bian-cheng-zhi-nan-gai-lan-tu-xing-shang-xia-wen-lu-jing-yan-se-yu-yan-se-kong-jian
Quartz2D 编程指南(一)概览、图形上下文、路径、颜色与颜色空间
标签:
原文地址:http://www.cnblogs.com/weiboyuan/p/5514843.html