Core Graphics 中的颜色处理围绕着两个相互关联的实体构建——CGColor 和 CGColorSpace。CGColor 表示带有组件的具体颜色,而 CGColorSpace 定义了这些组件的解释模型。根据 Apple Documentation (2026),Core Graphics 支持 20 多种标准色彩空间,包括 sRGB、Generic Gray 和 Generic CMYK。理解 CGColor 和 CGColorSpace 之间的区别对于在 iOS 和 macOS 上正确绘制图形是必要的。
要点
CGColor — 是 Core Graphics 中表示颜色的基本对象。在 CGColor 结构中存储了颜色组件的数值和对 CGColorSpace 的引用——解释这些组件的色彩空间。如果没有绑定到色彩空间,组件的数值就没有意义:在 RGB 中值 (1.0, 0.0, 0.0) 是红色,但在 CMYK 中是青色。
CGColorSpace — 是定义颜色模型和可表示值范围(色域)的对象。色彩空间规定了数值组件在特定输出设备上转换为可见颜色的规则。Core Graphics 既支持标准的 ICC 配置文件空间,也支持通过带有自定义转换表的 CGColorSpace 创建的自定义空间。
颜色和色彩空间分离的架构——Core Graphics 的关键特性,使其区别于颜色存储为简单数字集合的 API。这种方法允许 Core Graphics 执行独立于硬件的色彩管理:同一个 CGColor 对象可以通过 CGColorSpace 配置文件自动转换组件,从而在不同的显示器上正确显示。
Core Graphics 通过基于 ICC 配置文件(International Color Consortium)的模型来实现颜色。每个 CGColorSpace 包含对 ICC 配置文件的引用——颜色组件如何转换为 CIE XYZ(独立于硬件的色彩空间)的标准化描述。这使得 Core Graphics 能够在不同显示器之间执行自动色度补偿。
当通过 CGColorCreate 函数创建 CGColor 时,会从传递的数组中获取组件并绑定到指定的 CGColorSpace。Core Graphics 将组件复制到内部表示中,并创建与色彩空间的关联。之后,颜色就可以在任何图形操作中使用了——填充、描边、渐变、阴影。
在 macOS 上,色彩管理通过集成到 Core Graphics 中的 ColorSync 框架进行。ColorSync 跟踪显示器的校准,并自动将组件从源色彩空间转换到目标设备的空间。在 iOS 上,色彩管理通过 Quartz Core 实现,从 iPhone 7 开始支持宽色域(Display P3)。
CGColorSpace 支持四种基本颜色模型:RGB(DeviceRGB、sRGB、Display P3)、Gray(DeviceGray)、CMYK(DeviceCMYK)和 Lab。每个模型决定了颜色组件的数量和含义。RGB 使用三个通道——红色、绿色、蓝色;Gray——一个亮度通道;CMYK——四个打印通道;Lab——三个通道:亮度和两个色差分量。
| 颜色模型 | 组件 | 应用 | CGColorSpace 类型 |
|---|---|---|---|
| RGB | Red, Green, Blue | 屏幕,iOS/macOS 图形 | kCGColorSpaceSRGB |
| Gray | White(单通道) | 黑白图形,阴影 | kCGColorSpaceGenericGray |
| CMYK | Cyan, Magenta, Yellow, Black | 印刷产品,PDF | kCGColorSpaceGenericCMYK |
| Display P3 | R, G, B(宽色域) | 现代 iOS 设备 | kCGColorSpaceDisplayP3 |
DeviceRGB — 是 Core Graphics 最常见的默认色彩空间。它使用标准 LCD 显示器的色域,没有 ICC 配置文件。在创建 UIView 或 NSView 的图形上下文时,Core Graphics 会自动分配 DeviceRGB 作为默认色彩空间。sRGB——带有 ICC 配置文件的版本,具有固定的色域和伽马值,推荐用于 Web 内容。
Display P3 — 基于 DCI-P3 标准的色彩空间,用于具有宽色域显示器的现代 iOS 设备。它覆盖的可��颜色比 sRGB 多大约 25%,特别是在光谱的绿色和红色区域。要在 iOS 上使用 Display P3,需要使用常量 kCGColorSpaceDisplayP3,从 iOS 9.3 开始可用。
CGColor 通过 CGColorCreate 函数创建,该函数接受 CGColorSpace 和 CGFloat 类型的组件数组。组件的数量取决于颜色模型:Gray 为 1,RGB 为 3,CMYK 为 4。创建后,CGColor 是一个不可变对象——不能更改其组件,只能创建新的颜色。
Core Graphics 还提供了 CGColorCreateGenericRGB、CGColorCreateGenericGray 和 CGColorCreateGenericCMYK 函数,用于在标准(通用)色彩空间中创建颜色。这些函数简化了代码,无需显式创建 CGColorSpace。此外,在 Quartz 2D 中定义了基本颜色的常量:kCGColorWhite、kCGColorBlack、kCGColorClear。
在创建颜色时,组件的指定顺序很重要——必须严格符合色彩空间模型定义的通道顺序。RGB:红色 (0.0–1.0)、绿色、蓝色、透明度 (0.0–1.0)。Gray:亮度、透明度。CMYK:青色、品红色、黄色、黑色、透明度。组件顺序错误会导致颜色显示不正确,而不会出现编译错误。
透明度通道——控制颜色透明度的第四个组件(或 Gray 的第二个组件)。值 1.0 表示完全不透明,0.0 表示完全透明。CGColor 中的透明度通道是可选的:CGColorGetAlpha 函数返回当前的透明度值,通过基本函数创建时默认为 1.0。在颜色混合时,Core Graphics 根据 Porter-Duff Source Over 规则使用透明度合成。
CGColorSpace 通过 Core Graphics 的工厂函数创建:CGColorSpaceCreateDeviceRGB、CGColorSpaceCreateDeviceGray、CGColorSpaceCreateDeviceCMYK 或用于命名空间的 CGColorSpaceCreateWithName(sRGB、Display P3、Generic Gray)。CGColorSpace 对象是不可变且线程安全的——同一个对象可以在多个图形上下文中使用。
Core Graphics 通过命名的常量提供了几个预定义的色彩空间:kCGColorSpaceSRGB、kCGColorSpaceDisplayP3、kCGColorSpaceGenericGrayGamma2_2。这些常量被传递给 CGColorSpaceCreateWithName。对于具有宽色域的 iOS 设备,建议使用 Display P3,因为 sRGB 可能无法充分利用显示器的能力。
ICC 配置文件——是描述设备颜色特性的标准化文件。Core Graphics 允许通过 CGColorSpaceCreateWithICCProfile 基于任意 ICC 配置文件创建 CGColorSpace。这在专业照片打印和印前应用中使用,需要与特定的打印机或显示器精确匹配。
Core Graphics 在通过 CGContextSetFillColorWithColor 或 CGContextSetStrokeColorWithColor 函数绘制时自动执行色彩空间之间的转换。如果图形上下文的色彩空间与传入的 CGColor 的色彩空间不同,Quartz 2D 会使用两个空间的 ICC 配置文件执行转换。
对于显式的颜色转换,使用 CGColorCreateCopyByMatchingToColorSpace——该函数创建一个新的 CGColor,其组件从源空间重新计算到目标空间。根据 Apple Technical Note TN2313 (2024),从 Display P3 转换到 sRGB 时,色域外的颜色会被裁剪,导致饱和度损失。这在鲜艳的绿色和红色色调中尤为明显。
ColorSync 在 macOS 上提供图形堆栈级别的系统色彩管理。如果应用程序没有显式指定色彩空间,Core Graphics 会使用从 ColorSync 获取的显示空间。这保证了即使显示器使用不同的颜色配置文件,颜色也会看起来相同。
让我们来看一下在 iOS 应用程序中创建和使用 CGColor 和 CGColorSpace 的 实际示例。代码使用 Swift 编写,使用 Core Graphics 函数。
此示例展示了在三种不同色彩空间中创建红色。尽管 RGB 组件相同,但颜色会根据 CGColorSpace 的色域而不同。
import CoreGraphics
// 在 DeviceRGB 中创建颜色
let rgbSpace = CGColorSpaceCreateDeviceRGB()
let redColor = CGColorCreate(rgbSpace, [1.0, 0.0, 0.0, 1.0])
// 在 Display P3 中创建颜色
let p3Space = CGColorSpaceCreateWithName(kCGColorSpaceDisplayP3)
let p3RedColor = CGColorCreate(p3Space, [1.0, 0.0, 0.0, 1.0])
// 创建灰色
let graySpace = CGColorSpaceCreateDeviceGray()
let grayColor = CGColorCreate(graySpace, [0.5, 1.0])
示例中将 亮绿色 从 Display P3 转换到 sRGB。在这种转换中,sRGB 色域外的颜色将被调整,可能会改变色调。
let p3Space = CGColorSpaceCreateWithName(kCGColorSpaceDisplayP3)
let sRGBSpace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB)
// Display P3 中的亮绿色(sRGB 色域外)
let p3Green = CGColorCreate(p3Space, [0.0, 1.0, 0.0, 1.0])
// 转换为 sRGB
let srgbGreen = CGColorCreateCopyByMatchingToColorSpace(
sRGBSpace, p3Green, kCGRenderingIntentDefault
)
此示例演示了在自定义 UIView 中使用 CGColor 绘制填充圆。draw 方法获取当前图形上下文 UIGraphicsGetCurrentContext,在其中设置填充颜色。
class ColorView: UIView {
override func draw(rect: CGRect) {
guard let ctx = UIGraphicsGetCurrentContext()
else { return }
let rgbSpace = CGColorSpaceCreateDeviceRGB()
let blueColor = CGColorCreate(
rgbSpace,
[0.2, 0.4, 1.0, 1.0]
)
ctx.setFillColor(blueColor)
ctx.fillEllipse(in: CGRect(x: 50, y: 50,
width: 200, height: 200))
}
}
常见问题
CGColor — 是来自 Core Graphics 的低级颜色表示,用于 C 风格的 API。UIColor — 是 UIKit 的高级包装器,内部存储 CGColor 并添加了对暗模式差异(traitCollection)的支持。UIColor 可以通过 .cgColor 属性转换为 CGColor。
色彩空间 决定了数值组件如何被解释为可见颜色。相同的数字集合(1.0, 0.0, 0.0)在 RGB 中是红色,但在 CMYK 中是青色。没有 CGColorSpace,Core Graphics 无法在具有独特显示器特性的特定设备上正确显示颜色。
在 iOS 上,UIView 的图形上下文默认使用 DeviceRGB 色彩空间创建。在具有宽色域显示器的设备上(iPad Pro 9.7 英寸及更新型号,iPhone 7 及更新型号),还可以使用 Display P3,它比标准 sRGB 多支持 25% 的颜色。
不能,CGColor 是一个不可变对象。要获得具有不同组件的颜色,需要通过 CGColorCreate 创建新的 CGColor。这符合 Core Graphics 的设计,其中大多数对象都是不可变的,以确保线程安全性和绘制的可预测性。
要进行转换,请使用带有目标 CMYK 空间的 CGColorCreateCopyByMatchingToColorSpace。Core Graphics 将通过 ICC 配置文件考虑渲染意图执行转换。打印时选择 kCGRenderingIntentRelativeColorimetric,照片级图像选择 kCGRenderingIntentPerceptual。
总结
CGColorCreateCopyByMatchingToColorSpace 显式进行我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。