本文翻译自苹果官方文档:原文地址
颜色与色域
不同设备(显示器、打印机、扫描仪、照相机)对颜色的表现并不是相同的,每个设备都拥有它自己能够产生的的颜色范围。在某个设备上能够显示的颜色未必能够在另一不同设备上显示。
想要有效的与颜色打交道或者想要明白Quartz 2D
中使用颜色和色域的函数,你应当熟悉一下颜色管理综述。该文档讨论了颜色的概念、色值、设备独立和设备色域、颜色匹配问题、渲染意图、颜色管理模块、以及颜色同步(ColorSync)。
在本章中,你会学习到Quartz
如何表示颜色和色域、alpha
是啥。本章也讨论:
- 创建色域
- 创建和设置颜色
- 设置渲染意图
关于颜色和色域
Quartz
用一系列的值代表一个颜色。这些值离开了色域是毫无意义的;色域描述了如何解释颜色信息。表4-1
均表示纯强度下的蓝色;如果不知道色域和每个色域允许的范围值,我们就没有办法知道这些值代表什么颜色。
表4-1
Values | Color space | Components |
---|---|---|
240, 100%, 100% | HSB | Hue,saturation, brightness |
0,0,1 | RGB | Red, green, blue |
1,1,0,0 | CMYK | Cyan, magenta, yellow, blank |
1,0,0 | BGR | Blue, green, red |
如图4-1
所示,如果提供了错误的色域,那么可能得到相当戏剧性的结果。虽然在BGR
和RGB
中绿色的位置相同,但是红色和蓝色的的位置却相反。
图4-1 对同一张图片使用BGR和RGB色域
不同色域可以拥有不同的分量值,正如表4-1
所示,其中的三个色域拥有三个分量,而CMYK
拥有4个分量;与此同时其分量的取值范围也和色域相关。Quartz
中大多数的色域取值范围在0.0~1.0
之间;1.0
意味着全强度。例如Quartz
中全强度的蓝色在RGB
色域下的值为:(0.0, 0.0, 1.0)
。同时,Quartz
中颜色拥有一个alpha
值,该值表示其透明度,表4-1
中没有展示alpha
值。
Alpha值
Alpha
被Quartz
用来决定如何向已经存在的页上绘制新的物体,它是一个图形状态参数(graphics state)。图4-2
展示了用1.0、0.75、0.5、0.1和0.0这5个alpha
值绘制一个大矩形到一个不透明的小矩形上。
图4-2一系列透明度的绘制
你可以在绘制前,设置全局图形上下文alpha
参数来同时改变页和页上物体的透明度。图4-3
展示了全局设置为0.5和默认的1.0绘制的区别。
图4-3全局alpha参数对比
在普通混色模式中(默认的图形状态)Quartz
通过如下的公式结合源颜色分量和目的颜色分量达到透明度混合。
destination = (alpha * source) + (1 - alpha) * destination
其中源是指将要绘制新颜色的一个分量;目的是指背景色的一个分量;这个公式在每次绘制新图形或者图片时都会执行。
对于物体的透明度来说设置成1.0
表示完全不透明,设置成0.0
表示完全透明,在0.0~1.0
之间的值则表示半透明。你可以为接受颜色的操作指定alpha
值为颜色的最后一个分量;也可以通过函数CGContextSetAlpha
来设置全局alpha
值。如果你设置了两个值,那么在计算的时候Quartz
会将他们相乘。
当图形上下文是一个窗口或者bitmap时,如果你想允许这个页自身完全透明,可以显示的调用CGContextClearRect
,来清除图形上下文中的alpha
通道。在你想为一个图标做遮罩或想让窗口的背景透明时可能会用到这种操作。
创建色域
Quartz
不仅支持标准色域(被颜色管理系统用于设备独立的色域),还支持通用、索引、样章色域。设备独立的色域使用了一种可以移植的表示方法来表达颜色,它被用于从一个设备上的原生颜色到另一个设备上的原生颜色的转换。设备独立色域中的颜色,在不同的设备上表现是一致的(设备允许的误差范围内),因此设备独立色域是我们表示颜色最好的选择。
对于有精确颜色要求的应用来说,应当使用设备独立的色域。自定义的设备独立色域是通用颜色色域。 通用色域会让操作系统为应用提供最适合的颜色空间(色域);在显示器上绘制的效果就像打印一样。
注: iOS不支持设备独立色域和通用色域。iOS应用必须使用设备相关色域(device color spaces)。
创建设备独立色域
要创建设备独立色域,需要向Quartz
提供参考白点
、参考黑点
以及特定设备的伽马值(gamma values)
。Quartz
使用这些信息将颜色从源色域转换到输出设备的色域。
Quartz
支持设备独立色域,创建的函数是:
- L*a*b* 是一个非线性的孟塞尔颜色标记系统(一个使用色调、值、和饱和度来表示颜色的系统)的转换。这种色域空间使得颜色的差异与色域中的量化距离相匹配。L*分量亮度,a*分量表示从绿色到红色的值,b*分量表示从蓝色到黄色的值。该色域在设计时效仿了人脑解读颜色的过程。使用函数
CGColorSpaceCreateLab
创建。 - ICC是由国际颜色联合定义在ICC颜色描述文件中的色域。ICC描述文件中定义了一个设备与另一个特殊的设备能够支持的颜色总量,其目的是这个信息能够被用于从一个设备的色域准确的转换到另一个设备的色域。设备的制造者通常会提供一个ICC描述文件;有些显示器和打印机甚至内嵌了ICC描述文件,一些位图格式(如TIFF)也是如此。使用函数
CGColorSpaceCreateICCBased
创建。 - 校准RGB是一个设备独立的RGB色域,它表示相对于参考白点的颜色,参考白点是基于输出设备所能产生的最白光。使用函数
CGColorSpaceCreateCalibratedRGB
创建。 - 校准的灰是一个设备独立的灰度色域,这个色域表示相对于参考白点的颜色,参考白点是基于输出设备所能产生的最白光。使用函数
CGColorSpaceCreateCalibratedGray
创建。
创建通用色域
通用色域将颜色匹配交给了系统,大多数情况下,结果是能够接受的。虽然通用这个名字有所暗示,但是每个带有“通用”的色域:通用灰、通用RGB、通用CMYK都是具体的设备独立色域。
通用色域使用时很简单,不需要提供任何参考点;可以通过函数CGColorSpaceCreateWithName
传入如下的常量来创建通用色域:
- kCGColorSpaceGenericGray,表示通用灰,它是一个单调的色域,使用一个简单的值来描述纯黑(0.0)到纯白(1.0)。
- kCGColorSpaceGenericRGB,表示通用RGB,由三个分量组成(red, green, blue),其模拟了显示器独立的像素组成,每个分量都由0.0(零强度)~1.0(满强度)。
- kCGColorSpaceGenericCMYK,表示通用CMYK,由4个分量组成(cyan, magenta, yellow, black),其模拟了打印时幽默的生成,每个分量从0.0(不溶解颜色)~1.0(完全溶解颜色)。
创建设备相关颜色
设备相关色域主要用于iOS应用程序,因为其他选择是不可用的。在大多数情况下,Mac OS X 应用应当使用通用色域而不是设备相关色域;但是有些Quartz
操作需要用到设备相关色域,例如使用CGImageCreateWithMask
指定一个图片为遮罩时,图片必须被定义在设备相关灰色域中。
使用如下函数创建设备相关色域:
-
CGColorSpaceCreateDeviceGray
,创建设备相关的灰度色域。 -
CGColorSpaceCreateDeviceRGB
,创建设备相关的RGB色域。 -
CGColorSpaceCreateDeviceCMYK
,创建设备相关的CMYK色域。
创建索引和样章色域
索引色域包含一个至多含有256个实体的颜色表和一个与各个实体映射的基础色域;每一个实体在该色域中代表一种颜色。使用CGColorSpaceCreateIndexed
创建。
样章色域主要在Patterns中讨论;通常在我们使用样章的时候会用到,函数CGColorSpaceCreatePattern
可以创建这种色域。
设置和创建颜色
Quartz
提供了一系列的方法来设置填充色、描边色、色域以及alpha。对每个参数的设置都会保存到图形状态中,这也就意味着,你在设置一个值之后会一直有效(除非你新设置另一个值)。
颜色必须和色域关联,否则Quartz
不知道怎么去解析颜色;为要绘制的目的也要提恰当的色域。比较图4-4
中蓝色填充色的差别,左边是CMYK下的填充色,右边是RGB下的填充色,如果你使用的是显示器查看这个图片,那么你能看到很大的差别。这两个颜色从理论上来说是相同的,只有当CMYK色域下的图片显示到CMYK设备且RGB色域下的图片显示到RGB设备时才会看起来一样。
图4-4 CMYK填充色和RGB填充色
你可以使用CGContextSetFillColorSpace
和CGContextSetStrokeColorSpace
来设置填充和描边的色域;你也可以使用下表(4-2)中的函数来方便的设置一个设备相关色域中的颜色。
表4-2 颜色设置函数
函数 | 色域与描述 |
---|---|
CGContextSetRGBStrokeColor CGContextSetRGBFillColor
|
设备相关RGB色域;在PDF生成时Quartz 取相应的通用色域中的颜色来绘制。 |
CGContextSetCMYKStrokeColor CGContextSetCMYKFillColor
|
设备相关RGB色域;在PDF生成时保留这个色域。 |
CGContextSetGrayStrokeColor CGContextSetGrayFillColor
|
设备相关的灰色域;在PDF生成时Quartz 取相应的通用色域中的颜色来绘制。 |
CGContextSetStrokeColorWithColor CGContextSetFillColorWithColor
|
任意色域;需要提供一个包含色域信息的CGColor 对象,通常在需要重复使用某一颜色时使用。 |
CGContextSetStrokeColor CGContextSetFillColor
|
当前色域,不推荐。建议使用CGContextSetStrokeColorWithColor 和CGContextSetFillColorWithColor
|
指定描边和填充颜色时,就像是取相应色域中的某个值。例如,一个完全浸透的红色在RGB色域下由一个含有4个数字的数组构成:(1.0, 0.0, 0.0, 1.0);前三个分量表示全强度的红以及没有绿和蓝,第四个参数是alpha
值,它用来表示这个颜色的透明度。
如果应用中复用颜色,通常利用CGColor
对象来设置填充色和秒变色,相关的函数是:CGContextSetFillColorWithColor
、CGContextSetStrokeColorWithColor
。使用这种方法能够保留CGColor
对象到适当的时候;直接使用CGColor
能够提高性能。
通过调用函数CGColorCreate
传入适当的色域参数和浮点的数组分量值来创建指定的颜色;浮点数组中最后一个分量是alpha
值。
设置渲染意图
渲染意图指明了Quartz
如何从源色域映射到一个图形上下文的目的色域范围。如果没指明渲染意图,Quartz
为所有了绘制(位图图片除外)使用相关的比色渲染意图;对于位图图片则使用感知渲染意图。
调用CGContextSetRenderingIntent
函数并传入如下的常量之一来设置渲染意图:
-
kCGRenderingIntentDefault
,对图形上下文使用默认的渲染意图。 -
kCGRenderingIntentAbsoluteColorimetric
,将输出设备的色域外的颜色映射到输出设备的色域内最匹配的颜色。当图形上下文色域中的两个不同颜色值映射到输出设备色域中为相同的颜色时,会产生剪切效果。当图形中使用的颜色在源和目标的色域内时,这是最好的选择;通常用于logo和点色使用。 -
kCGRenderingIntentRelativeColorimetric
,相对比色改变了所有的颜色(包括色域范围内的颜色),这么做是为了协调图形上下文和输出设备的白点值。 -
kCGRenderingIntentPerceptual
,通过压缩图形上下文的色域以适应输出设备的色域,保持了颜色之间的视觉关系;对于照片和其他复杂、游戏界的图像是有好处的。 -
kCGRenderingIntentSaturation
,当转换成输出设备的色域时,保留颜色的相对饱和度值;使图像具有明亮、饱和的颜色;该意图有利于展示低细节的图像,如表示图表和图形。