Working with color in Core Graphics is built around two interrelated entities — CGColor and CGColorSpace. CGColor represents a specific color with components, while CGColorSpace defines the model for interpreting those components. According to Apple Documentation (2026), Core Graphics supports over 20 standard color spaces, including sRGB, Generic Gray, and Generic CMYK. Understanding the difference between CGColor and CGColorSpace is essential for correct graphics rendering on iOS and macOS.
Key Takeaways
CGColor is a fundamental Core Graphics object representing a color. The CGColor structure stores numeric values of color components and a reference to CGColorSpace — the color space in which these components are interpreted. Without being tied to a color space, numeric component values have no meaning: the value (1.0, 0.0, 0.0) in RGB is red, but in CMYK it is cyan.
CGColorSpace is an object that defines a color model and the range of representable values (gamut). The color space sets the rules by which numeric components are turned into a visible color on a specific output device. Core Graphics supports both standard ICC-profiled spaces and custom spaces created via CGColorSpace with custom transformation tables.
The architecture separating color and color space is a key feature of Core Graphics that distinguishes it from APIs where color is stored as a simple set of numbers. This approach allows Core Graphics to perform device-independent color management: the same CGColor object can be correctly displayed on different displays thanks to automatic component conversion through the CGColorSpace profile.
Core Graphics implements color through a model based on ICC profiles (International Color Consortium). Each CGColorSpace contains a reference to an ICC profile — a standardized description of how color components are converted to CIE XYZ — a device-independent color space. This allows Core Graphics to perform automatic colorimetric compensation between different screens.
When creating a CGColor via the CGColorCreate function, components are captured from the passed array and bound to the specified CGColorSpace. Core Graphics copies the components into an internal representation and creates an association with the color space. After that, the color is ready for use in any graphics operation — fill, stroke, gradient, shadow.
On macOS, color management is handled through the ColorSync framework, integrated into Core Graphics. ColorSync tracks display calibration and automatically converts components from the source color space to the target device space. On iOS, color management is implemented via Quartz Core with support for a wide color gamut (Display P3), starting with iPhone 7.
CGColorSpace supports four basic color models: RGB (DeviceRGB, sRGB, Display P3), Gray (DeviceGray), CMYK (DeviceCMYK), and Lab. Each model defines the number and meaning of color components. RGB uses three channels — red, green, blue; Gray uses one luminance channel; CMYK uses four channels for printing; Lab uses three channels: luminance and two color-difference components.
| Color Model | Components | Usage | CGColorSpace Type |
|---|---|---|---|
| RGB | Red, Green, Blue | Screens, iOS/macOS graphics | kCGColorSpaceSRGB |
| Gray | White (single channel) | Black-and-white graphics, shadows | kCGColorSpaceGenericGray |
| CMYK | Cyan, Magenta, Yellow, Black | Print products, PDF | kCGColorSpaceGenericCMYK |
| Display P3 | R, G, B (wide gamut) | Modern iOS devices | kCGColorSpaceDisplayP3 |
DeviceRGB is the most common default Core Graphics color space. It uses the color gamut of a standard LCD display without ICC profiling. When creating a UIView or NSView graphics context, Core Graphics automatically assigns DeviceRGB as the default color space. sRGB is an ICC-profiled version with a fixed gamut and gamma, recommended for web content.
Display P3 is a color space based on the DCI-P3 standard, used in modern iOS devices with wide-color displays. It covers approximately 25% more visible colors than sRGB, especially in the green and red areas of the spectrum. To work with Display P3 on iOS, use the constant kCGColorSpaceDisplayP3, available since iOS 9.3.
CGColor is created via the CGColorCreate function, which takes a CGColorSpace and an array of CGFloat components. The number of components depends on the color model: 1 for Gray, 3 for RGB, 4 for CMYK. Once created, CGColor is an immutable object — you cannot change its components, only create a new color.
Core Graphics also provides the CGColorCreateGenericRGB, CGColorCreateGenericGray, and CGColorCreateGenericCMYK functions for creating colors in standard (generic) color spaces. These functions simplify code by eliminating the need to explicitly create a CGColorSpace. Additionally, Quartz 2D defines constants for basic colors: kCGColorWhite, kCGColorBlack, kCGColorClear.
When creating a color, the order of specifying components is important — it must strictly match the channel order defined by the color space model. RGB: red (0.0–1.0), green, blue, alpha (0.0–1.0). Gray: luminance, alpha. CMYK: cyan, magenta, yellow, black, alpha. Violating component order leads to incorrect color display without a compilation error.
Alpha channel is the fourth component (or second for Gray) that controls color transparency. A value of 1.0 corresponds to full opacity, 0.0 to full transparency. The alpha channel in CGColor is optional: the CGColorGetAlpha function returns the current alpha value, which defaults to 1.0 when created through basic functions. When blending colors, Core Graphics uses alpha compositing according to the Porter-Duff Source Over rule.
CGColorSpace is created via Core Graphics factory functions: CGColorSpaceCreateDeviceRGB, CGColorSpaceCreateDeviceGray, CGColorSpaceCreateDeviceCMYK, or CGColorSpaceCreateWithName for named spaces (sRGB, Display P3, Generic Gray). The CGColorSpace object is immutable and thread-safe — the same object can be used in multiple graphics contexts.
Core Graphics provides several predefined color spaces through named constants: kCGColorSpaceSRGB, kCGColorSpaceDisplayP3, kCGColorSpaceGenericGrayGamma2_2. These constants are passed to CGColorSpaceCreateWithName. For iOS devices with a wide color gamut, Display P3 is recommended, as sRGB may not fully utilize the display capabilities.
ICC profiles are standardized files describing the color characteristics of a device. Core Graphics allows creating a CGColorSpace based on an arbitrary ICC profile via CGColorSpaceCreateWithICCProfile. This is used in professional applications for photo printing and prepress where precise matching to a specific printer or monitor is required.
Core Graphics performs conversion between color spaces automatically during rendering via the CGContextSetFillColorWithColor or CGContextSetStrokeColorWithColor functions. If the graphics context's color space differs from the passed CGColor's color space, Quartz 2D performs conversion using the ICC profiles of both spaces.
For explicit color conversion, use CGColorCreateCopyByMatchingToColorSpace — a function that creates a new CGColor whose components are recalculated from the source space to the target space. According to Apple Technical Note TN2313 (2024), when converting from Display P3 to sRGB, colors outside the sRGB gamut are clipped, resulting in loss of saturation. This is especially noticeable in bright green and red shades.
ColorSync on macOS provides system-level color management at the graphics stack level. If an application does not specify an explicit color space, Core Graphics uses the display space obtained from ColorSync. This ensures that colors look the same on different monitors, even if they use different color profiles.
Let's look at practical examples of creating and using CGColor and CGColorSpace in an iOS application. The code is written in Swift using Core Graphics functions.
This example shows creating a red color in three different color spaces. Despite having the same RGB components, the color will look different depending on the CGColorSpace gamut.
import CoreGraphics
// Creating color in DeviceRGB
let rgbSpace = CGColorSpaceCreateDeviceRGB()
let redColor = CGColorCreate(rgbSpace, [1.0, 0.0, 0.0, 1.0])
// Creating color in Display P3
let p3Space = CGColorSpaceCreateWithName(kCGColorSpaceDisplayP3)
let p3RedColor = CGColorCreate(p3Space, [1.0, 0.0, 0.0, 1.0])
// Creating gray color
let graySpace = CGColorSpaceCreateDeviceGray()
let grayColor = CGColorCreate(graySpace, [0.5, 1.0])
This example converts a bright green color from Display P3 to sRGB. During such conversion, colors outside the sRGB gamut will be adapted, which may change the hue.
let p3Space = CGColorSpaceCreateWithName(kCGColorSpaceDisplayP3)
let sRGBSpace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB)
// Bright green in Display P3 (outside sRGB gamut)
let p3Green = CGColorCreate(p3Space, [0.0, 1.0, 0.0, 1.0])
// Converting to sRGB
let srgbGreen = CGColorCreateCopyByMatchingToColorSpace(
sRGBSpace, p3Green, kCGRenderingIntentDefault
)
This example demonstrates drawing a filled circle using CGColor in a custom UIView. The draw method obtains the current graphics context UIGraphicsGetCurrentContext, in which the fill color is set.
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))
}
}
Frequently Asked Questions
CGColor is a low-level color representation from Core Graphics used in C-style APIs. UIColor is a high-level UIKit wrapper that internally stores CGColor and adds support for dark mode differences (traitCollection). UIColor can be converted to CGColor via the .cgColor property.
Color space determines how numeric components are interpreted as a visible color. The same set of numbers (1.0, 0.0, 0.0) means red in RGB but cyan in CMYK. Without CGColorSpace, Core Graphics cannot correctly display the color on a specific device with its unique display characteristics.
On iOS, the UIView graphics context is created by default with the DeviceRGB color space. On devices with wide-color displays (iPad Pro 9.7-inch and later, iPhone 7 and later), Display P3 is also available, which supports 25% more colors than standard sRGB.
No, CGColor is an immutable object. To get a color with different components, you must create a new CGColor via CGColorCreate. This follows Core Graphics design where most objects are immutable to ensure thread safety and rendering predictability.
For conversion, use CGColorCreateCopyByMatchingToColorSpace with the target CMYK space. Core Graphics will perform the conversion through ICC profiles taking into account the rendering intent. Choose kCGRenderingIntentRelativeColorimetric for printing or kCGRenderingIntentPerceptual for photorealistic images.
Summary
CGColorCreateCopyByMatchingToColorSpaceWe will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.
Read also