CoreGraphics(Quartz 2D) | 基础概念篇:概览、图形上下文、颜色与颜色空间

图片发自简书App

CoreGraphics是"艺名",学名是Quartz 2D,是二维图形绘制引擎,支持 iOS 和 OS X。

Quartz 2D的API使用简单,提供了很多强大的特性,如:透明层,基于路径绘图,离屏渲染,先进的色彩管理,防锯齿渲染,以及PDF文件的创建、展示和解析。

关于CG,工作用到的并不是非常多,但是作为开发者们耳熟能详的框架、其优秀的特性,奈何不了手痒痒。一直关于CG限于阅读博客、官文(官方文档),但“纸上得来终觉浅,绝知此事要躬行”啊。

此文是对于官文的总结和应用。

简介

哪些场景下会用到CoreGraphics

  • 1.绘制图形。

  • 2.需要提供图像编辑功能。

  • 3.创建或者展示bitmap图片。

  • 4.与PDF相关的操作。

概览

Page(画布)

Quartz 2D在图像中使用了绘画者模型(painter’s model)。在绘画者模型中,简单说,当前的图层A,在上面添加图层B,A被B遮盖的地方将不会显示出来,而只显示A未被覆盖的地方和B层。

Page可以是一张纸(如果输出设备是打印机),也可以是虚拟的纸张(如果输出设备是PDF文件),还可以是bitmap图像。这根据实际使用的graphics context而定。

Graphics Context(图形上下文)

Graphics Context 是一种不透明数据类型,它封装了Quartz绘制图像到输出设备上所用到的信息,输出设备可以是PDF文件,bitmap内存或者显示器。同一张图片可以通过指定不同的Context,即可输出到不同的设备上。

Quartz提供了以下几种类型的Graphics Context,详细的介绍将在后续章节说明:

  • Bitmap Graphics Context
  • PDF Graphics Context
  • Window Graphics Context
  • Layer Context
  • Post Graphics Context

其他的图形上下文

除了上面几种Context,Quartz还提供下面这些上下文,他们都以CG开头,Quartz 2D在这些context上创建对象操作对象,从而获得某一特定的输出(大白话这么说,根据你要创建的东西不一样,可以是路径、图片、layer等等,而创建不同的context,从而输出你要的结果,比如一张美美的图片啦)。

常用的

  • CGPathRef:用于向量图,可创建路径,并进行填充或描画(stroke)
  • CGImageRef:用于表示bitmap图像和基于采样数据的bitmap图像遮罩。
  • CGLayerRef:用于表示可用于重复绘制(如背景)和幕后(offscreen)绘制的绘画层
  • CGPatternRef:用于重绘图
  • CGShadingRef、CGGradientRef:用于绘制渐变

不常用的 详细说明链接

  • CGFunctionRef; CGColorRef, CGColorSpaceRef; CGImageSourceRef,CGImageDestinationRef; CGFontRef; CGPDFDictionaryRef, CGPDFObjectRef, CGPDFPageRef; CGPDFStream, CGPDFStringRef, and CGPDFArrayRef;
    CGPDFScannerRef, CGPDFContentStreamRef;
    CGPSConverterRef;

Quartz 2D 坐标系统

在iOS 3.2以后的版本,当创建一个绘图上下文时,UIKit对上下文进行了额外的修改以匹配UIKit坐标习惯。但,patterns和shadows(不被CTM影响)单独进行调整以匹配UIKit坐标系统。因为需要理解在哪种上下文中进行绘制,并调整行为以匹配上下文的预期。

内存管理

通常,以”Create”或“Copy”单词的函数获取一个对象,当使用完后必须释放,否则将导致内存泄露。如果不是用上面的两种“关键字”定义的,你将不会拥有对象的引用,不需要释放它。
如果你对一个对象没有拥有权却想要引用它,你必须retain它,并在不需要的时候手动释放它,相应的方法。

例如:创建了一个CGColorspace对象,则使用函数CGColorSpaceRetain和CGColorSpaceRelease来retain和release对象。同样,可以使用Core Foundation的CFRetain和CFRelease,但是注意不能传递NULL值给这些函数。

图形上下文(Graphics Contexts)

获取上下文的方式有:Quartz提供的创建函数、Mac OS X框架或IOS的UIKit框架提供的函数。Quartz提供了多种Graphics Context的创建函数,包括bitmap和PDF。

iOS,在View Graphics Context绘制

在iOS应用中,视图显示在屏幕上及它的内容需要更新时会调用被调用drawRect:方法。你只需要实现drawRect:方法,并在其中获取上下文(视图对象会配置一个上下文给你),绘制你想要的图像。

调用UIGraphicsGetCurrentContext获取当前的上下文。

样例代码

CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetRGBFillColor(context, 1, 0, 0.5, 1); CGContextFillRect(context, CGRectMake (0, 0, 250, 150));

在Mac OS X中创建一个窗口Graphics Context

内容不多,关于Mac开发,不多占用篇幅了,见参考文档吧。

创建 PDF Graphics Context

Quartz2D API 提供了两个函数来创建 PDF Graphics Context。

  • CGPDFContextCreateWithURL。当你需要用 Core Foundation URL 指定 PDF 输出的位置时使用该函数。

  • CGPDFContextCreate 当需要将pdf输出发送给数据用户时使用该方法。

创建 Bitmap Graphics Context

一个位图Graphics Context接受一个指向内存缓存(包含位图存储空间)的指针,当我们绘制一个位图Graphics Context时,该缓存被更新。在释放Graphics Context后,我们将得到一个我们指定像素格式的全新的位图。

注:位图Graphics Context有时用于后台绘制。CGLayer对象优化了后台绘制,因为Quartz在显卡上缓存了层。

UIGraphicsBeginImageContext([UIScreen mainScreen].bounds.size);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetRGBFillColor(context, 1, 0.5, 0.5, 1);
    CGContextFillRect(context, CGRectMake (0, 0, 100, 150));

->接下来,获取图片

UIImage *imageOne = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

<->或者

CGImageRef myImage = CGBitmapContextCreateImage(context);
    CGContextDrawImage(context, CGRectMake(0, 0, 300, 300), myImage);
    char *bitmapData = CGBitmapContextGetData(context);
    CGContextRelease (context);
    if (bitmapData) free(bitmapData);
    CGImageRelease(myImage);

支持的像素格式

位图 Graphics Context支持的像素格式,相关的颜色空间及像素格式支持的Mac OS X最早版本。像素格式用bpp(每像素的位数)和bpc(每个组件的位数)来表示,详细格式表格

iOS 共支持 8 种像素格式。

  • Null 8 bpp, 8 bpc, kCGImageAlphaOnly
  • Gray 8 bpp, 8 bpc, kCGImageAlphaNone
  • Gray 8 bpp, 8 bpc, kCGImageAlphaOnly
  • RGB 16 bpp, 5 bpc, kCGImageAlphaNoneSkipFirst
  • RGB 32 bpp, 8 bpc, kCGImageAlphaNoneSkipFirst
  • RGB 32 bpp, 8 bpc, kCGImageAlphaNoneSkipLast
  • RGB 32 bpp, 8 bpc, kCGImageAlphaPremultipliedFirst
  • RGB 32 bpp, 8 bpc, kCGImageAlphaPremultipliedLast

反锯齿

位图 Graphics Context支持反锯齿,当位图的分辩率明显低于人眼的分辩率时就会产生锯齿。使形状看起来更平滑。

我们可以通过调用CGContextSetShouldAntialias来关闭位图Graphics Context的反锯齿效果。反锯齿设置是图形状态的一部分。
可以调用函数CGContextSetAllowsAntialiasing来控制一个特定Graphics Context是否支持反锯齿;

CGContextRef context1 =UIGraphicsGetCurrentContext();
    CGContextSetShouldAntialias(context1, YES);
    CGContextSetAllowsAntialiasing(context1, YES);

颜色与颜色空间

什么是颜色与颜色空间

Quartz中的颜色是用一组值来表示。而颜色空间用于解析这些颜色信息。例如,下表列出了在全亮度下蓝色值在不同颜色空间下的值。如果不知道颜色空间及颜色空间所能接受的值,我们没有办法知道一组值所表示的颜色。

Values(值) Color Space(颜色空间) Components(组件)
240 degrees 100% 100% HSB Hue, saturation, britness
0, 0, 1 RGB Red, green, blue
1, 1, 0, 0 CMYK Cyan ,magenta, yellow, black
1, 0, 0 BGR Blue, green, red

alpha值(透明度)

使用 CGContextSetAlpha(context, 0.2) 设置透明度。

使用 CGContextClearRect 清除上下文的 alpha 通道。

创建设备依赖颜色空间

创建设备依赖灰度颜色空间。

CGColorSpaceCreateDeviceGray()

创建设备依赖RGB颜色空间。

CGColorSpaceCreateDeviceRGB()

创建设备依赖CMYK颜色空间。

CGColorSpaceCreateDeviceCMYK()

设置颜色空间。

CGContextSetFillColorSpace(context, colorSpace)CGContextSetStrokeColorSpace(context, colorSpace)

样例代码:

//Device RGB. 设置设备依赖RGB颜色空间并设置颜色值。
CGContextSetRGBStrokeColor(context, 1, 0, 0, 1);
CGContextSetRGBFillColor(context, 1, 0, 0, 1);

//Device CMYK. 设置设备依赖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);

//使用 CGColor 设置颜色值并使用 CGColor 指定的颜色空间。
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);
调用如下函数来便捷的设置颜色值并使用正在使用的颜色空间。
CGContextSetStrokeColor(context, colors);
CGContextSetFillColor(context, colors);

设置和创建颜色

通过如下函数设置和创建颜色。

CGContextSetFillColorWithColor(context, [UIColor redColor].CGColor);
CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor));

设置再现意图(Rending Intent)

每个设备都有固定的可复制的颜色范围(gamut),这是设备的物理性质决定的。当图像从一个颜色空间向另一个颜色空间转换时,有些源设备颜色空间中呈现的颜色,不能在目标设备颜色空间中复制出来,这些不能复制的颜色叫色域外(out-of-gamut)颜色。比如 RGB 颜色空间比 CMYK 的颜色空间要大,有些在显示器上能显示的颜色不能在打印机上同样打印出来。因为我们不能在目标设备颜色空间中复制出色域外颜色,我们必须用一些其他颜色来替代他们。颜色空间转换时颜色替换调整的规则就是再现意图。你也可以查阅这里关于“再现意图”(Rendering intent Understanding rendering intents: Which one and why?
再现意图用于指定如何将源颜色空间的颜色映射到图形上下文的目标颜色空间的颜色范围内。

引用自:关于“再现意图”(Rendering intent)

如果不显式的指定再现意图,Quartz 使用“相对色度再现意图”应用于所有绘制(不包含位图图像)。

对于位图图像,Quartz默认使用“感知再现意图”。

调用 CGContextSetRenderingIntent(context, kCGRenderingIntentDefault) 来设置再现意图。

再现意图共有以下 5 种。

typedef CF_ENUM (int32_t, CGColorRenderingIntent) {
    kCGRenderingIntentDefault,//默认
    kCGRenderingIntentAbsoluteColorimetric,//绝对色度再现意图
    kCGRenderingIntentRelativeColorimetric,//相对色度再现意图
    kCGRenderingIntentPerceptual,//感知再现意图
    kCGRenderingIntentSaturation//饱和度再现意图
};

详细查看官文文档
这是CoreGraphic第一篇,基础概念篇,接下来会进入实战阶段,如果你感兴趣,来个关注。我们下期见。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容