Search Docs
Loading...
Skip to content

Color Basics

Understand the three color spaces in CE.SDK and when to use each for screen or print workflows.

Color Basics example showing three colored blocks representing sRGB, CMYK, and Spot color spaces

18 mins
estimated time
Download
StackBlitz
GitHub

CE.SDK supports three color spaces: sRGB for screen display, CMYK for print workflows, and Spot Color for specialized printing. Each color space serves different output types and has its own object format for the setColor() API.

This guide covers how to choose the correct color space, define and apply colors using the unified setColor() API, and configure spot colors with screen preview approximations. It also shows how CE.SDK converts colors, how to set the document CMYK profile, the rendering intent and black point compensation, the difference between Managed and Legacy scenes, and what each export format writes.

Color Spaces Overview#

CE.SDK represents colors as objects with different properties depending on the color space. Use engine.block.setColor() to apply any color type to supported properties.

Supported color properties:

  • 'fill/color/value' - Fill color of a block
  • 'stroke/color' - Stroke/outline color
  • 'dropShadow/color' - Drop shadow color
  • 'backgroundColor/color' - Background color
  • 'camera/clearColor' - Canvas clear color

sRGB Colors#

sRGB is the default color space for screen display. Pass an RGBAColor object with r, g, b, a components, each in the range 0.0 to 1.0. The a (alpha) component controls transparency.

// Block 1: sRGB color (for screen display)
const srgbBlock = engine.block.create('//ly.img.ubq/graphic');
engine.block.setShape(
srgbBlock,
engine.block.createShape('//ly.img.ubq/shape/rect')
);
const srgbFill = engine.block.createFill('//ly.img.ubq/fill/color');
// Set fill color using RGBAColor object (values 0.0-1.0)
engine.block.setColor(srgbFill, 'fill/color/value', {
r: 0.2,
g: 0.4,
b: 0.9,
a: 1.0
});
engine.block.setFill(srgbBlock, srgbFill);
engine.block.setWidth(srgbBlock, blockWidth);
engine.block.setHeight(srgbBlock, blockHeight);
engine.block.appendChild(page, srgbBlock);

sRGB colors are ideal for web and digital content where the output is displayed on screens.

CMYK Colors#

CMYK is the color space for print workflows. Pass a CMYKColor object with c, m, y, k components (0.0 to 1.0) plus a tint value that scales the ink amounts (1.0 is full ink, 0.0 is no ink).

// Block 2: CMYK color (for print workflows)
const cmykBlock = engine.block.create('//ly.img.ubq/graphic');
engine.block.setShape(
cmykBlock,
engine.block.createShape('//ly.img.ubq/shape/rect')
);
const cmykFill = engine.block.createFill('//ly.img.ubq/fill/color');
// Set fill color using CMYKColor object (values 0.0-1.0, tint scales ink)
engine.block.setColor(cmykFill, 'fill/color/value', {
c: 0.0,
m: 0.8,
y: 0.95,
k: 0.0,
tint: 1.0
});
engine.block.setFill(cmykBlock, cmykFill);
engine.block.setWidth(cmykBlock, blockWidth);
engine.block.setHeight(cmykBlock, blockHeight);
engine.block.appendChild(page, cmykBlock);

On screen and in raster exports, CMYK colors convert to RGB through the document CMYK profile. A key-only black and a rich black look different, as they do on press. The tint value (0.0 to 1.0) scales the ink amounts before the conversion, so a lower tint gives a lighter color that stays opaque. A scene saved before CE.SDK 1.83 loads as Legacy and keeps the earlier formula. The sections below explain the profile and both modes.

Spot Colors#

Spot colors are named colors used for specialized printing. Before using a spot color, you must define it with an RGB or CMYK approximation for screen preview.

Defining Spot Colors#

Use engine.editor.setSpotColorRGB() or engine.editor.setSpotColorCMYK() to register a spot color with its screen preview approximation.

// Define a spot color with RGB approximation for screen preview
engine.editor.setSpotColorRGB('MyBrand Red', 0.95, 0.25, 0.21);

Applying Spot Colors#

Reference a defined spot color using a SpotColor object with the name, tint, and externalReference properties.

// Block 3: Spot color (for specialized printing)
const spotBlock = engine.block.create('//ly.img.ubq/graphic');
engine.block.setShape(
spotBlock,
engine.block.createShape('//ly.img.ubq/shape/rect')
);
const spotFill = engine.block.createFill('//ly.img.ubq/fill/color');
// Set fill color using SpotColor object (references the defined spot color)
engine.block.setColor(spotFill, 'fill/color/value', {
name: 'MyBrand Red',
tint: 1.0,
externalReference: ''
});
engine.block.setFill(spotBlock, spotFill);
engine.block.setWidth(spotBlock, blockWidth);
engine.block.setHeight(spotBlock, blockHeight);
engine.block.appendChild(page, spotBlock);

When rendered on screen, the spot color uses its RGB approximation. It uses the CMYK approximation only when no RGB approximation is set. During PDF export, spot colors are saved as a Separation Color Space that preserves print information.

Applying Stroke Colors#

Strokes support all three color spaces. Enable the stroke, set its width, then apply a color using the 'stroke/color' property.

// Add strokes to demonstrate stroke color property
engine.block.setStrokeEnabled(srgbBlock, true);
engine.block.setStrokeWidth(srgbBlock, 4);
engine.block.setColor(srgbBlock, 'stroke/color', {
r: 0.1,
g: 0.2,
b: 0.5,
a: 1.0
});
engine.block.setStrokeEnabled(cmykBlock, true);
engine.block.setStrokeWidth(cmykBlock, 4);
engine.block.setColor(cmykBlock, 'stroke/color', {
c: 0.0,
m: 0.5,
y: 0.6,
k: 0.2,
tint: 1.0
});
engine.block.setStrokeEnabled(spotBlock, true);
engine.block.setStrokeWidth(spotBlock, 4);
engine.block.setColor(spotBlock, 'stroke/color', {
name: 'MyBrand Red',
tint: 0.7,
externalReference: ''
});

Reading Color Values#

Use engine.block.getColor() to retrieve the current color value from a property. The returned object’s shape indicates the color space (RGBAColor, CMYKColor, or SpotColor).

// Retrieve and log color values to demonstrate getColor()
const srgbColor = engine.block.getColor(srgbFill, 'fill/color/value');
const cmykColor = engine.block.getColor(cmykFill, 'fill/color/value');
const spotColor = engine.block.getColor(spotFill, 'fill/color/value');
console.log('sRGB Color:', srgbColor);
console.log('CMYK Color:', cmykColor);
console.log('Spot Color:', spotColor);

How CE.SDK Converts Colors#

To show a CMYK color on screen, CE.SDK converts it through an ICC profile, the document CMYK profile.

The engine converts a color in these steps:

  • The document CMYK profile. Each scene can name one CMYK ICC profile. The profile converts CMYK colors, the CMYK approximation of a spot color, and CMYK images that have no profile of their own.
  • Profile priority. The engine uses the document profile when the document names one. Otherwise, it uses the profile in the fallbackCMYKProfileUri setting.
  • A profile that does not load. When a loaded scene names a profile that does not load, the engine logs a warning and uses the fallback profile. When the fallback profile does not load, the engine does not use the bundled profile instead. CMYK colors then show with the unmanaged formula, and loadCMYKProfile() and a conversion that needs the profile fail with COLOR.PROFILE_MISSING.
  • Rendering intent and black point compensation. Both apply to every conversion through the document profile. The defaults are relative colorimetric and black point compensation on.
  • What changes on screen. A key-only black and a rich black are two different blacks, as they are on press. A tinted CMYK color scales its inks. It does not fade toward white.
  • Images. An image with an embedded ICC profile, RGB or CMYK, uses its own profile. The document profile does not change it. A CMYK or YCCK JPEG without a profile decodes through the document CMYK profile.

Converting Colors in Code#

engine.editor.convertColorToColorSpace(color, 'sRGB' | 'CMYK') converts through the same profile as the canvas, so a swatch that you show matches what the user sees. The call is synchronous. You cannot convert to 'SpotColor'.

A scene that you create with engine.scene.create() is Managed, which means that it converts through the profile. Applying a template or loading a scene takes the mode stored in that file. A template or scene saved before CE.SDK 1.83 is Legacy, and this includes the templates of the demo asset library. The section “Managed and Legacy Scenes” below explains the other mode. In a Managed scene, a conversion that needs the profile fails with COLOR.PROFILE_NOT_LOADED while the profile loads. The call starts the load.

Await engine.editor.loadCMYKProfile() before you convert. Await it again after each change to the profile source: removeCMYKProfile(), a change of fallbackCMYKProfileUri, or a scene load.

The example awaits the profile and defines a logConversions helper, which logs the sRGB value of each swatch. The later steps call the helper again.

await engine.editor.loadCMYKProfile();
const logConversions = (step: string) => {
const values = swatches.map(({ label, color }) => {
const { r, g, b } = engine.editor.convertColorToColorSpace(
color,
'sRGB'
);
return { label, r: +r.toFixed(3), g: +g.toFixed(3), b: +b.toFixed(3) };
});
console.log(step);
console.table(values);
};
logConversions('Bundled default profile');
  • sRGB to CMYK uses the reverse tables of the profile. A profile that has no reverse tables uses a simple formula.
  • A spot color converts to CMYK through its CMYK approximation, when it has one.

The logged values change when the profile, the intent, black point compensation or the mode changes. The Color Conversion guide has more conversion examples.

Setting the Document CMYK Profile#

Set the document CMYK profile to the profile of your press and paper.

  • engine.scene.setCMYKProfile(uri) loads a profile from a URI. The call is async and atomic: the previous profile stays in effect while the new one loads, and a failure keeps it.
  • engine.scene.setCMYKProfileFromData(bytes) sets the profile from bytes that you already have. The change is in effect when the call returns.
  • engine.scene.getCMYKProfileInfo() returns the contentHash of the profile that the document names, also when that profile did not load. To learn if the profile is usable, await engine.editor.loadCMYKProfile(). The getter fails with COLOR.DOCUMENT_PROFILE_NOT_SET when the document names no profile. It never reports the fallback profile.
  • engine.scene.removeCMYKProfile() goes back to the fallback profile. While fallbackCMYKProfileUri is not set, that is the bundled profile. Color management stays on.
  • The fallbackCMYKProfileUri setting changes the profile for every document that names none. Set it with engine.editor.setSetting('fallbackCMYKProfileUri', uri).

The example loads ISOcoated_v2_eci.icc from its own assets and logs the content hash. await engine.scene.setCMYKProfile() waits for the new profile, so the example converts right after it.

await engine.scene.setCMYKProfile(
new URL(profileUrl, document.baseURI).href
);
const { contentHash } = engine.scene.getCMYKProfileInfo();
console.log('Document profile hash:', contentHash);
logConversions('ISOcoated_v2_eci.icc');

Rendering Intent and Black Point Compensation#

The rendering intent selects how the profile maps colors into the destination, for example from the press to the screen:

  • Perceptual compresses the full gamut, so the relations between colors stay the same.
  • RelativeColorimetric, the default, keeps the colors inside the gamut and clips the others. It maps the paper white of the profile to the white of the screen.
  • Saturation keeps colors saturated. Use it for charts and graphics, not for photos.
  • AbsoluteColorimetric does not map the paper white to the white of the screen. The screen shows the paper tint of the profile, so the preview simulates the paper color.

Black point compensation maps the darkest black of the profile to the darkest black of the screen. It is on by default. With the relative colorimetric intent, turning it off leaves the press black as a dark gray, so dark areas look lighter. The absolute colorimetric intent does not use black point compensation.

The example sets the Perceptual intent, turns black point compensation off and logs the conversions again. With the example profile, the perceptual intent gives the same values with black point compensation on or off.

engine.scene.setColorRenderingIntent(ColorRenderingIntent.Perceptual);
engine.scene.setBlackPointCompensationEnabled(false);
logConversions('Perceptual intent, black point compensation off');

Both settings are document state. CE.SDK saves them with the scene, and undo does not change them.

Managed and Legacy Scenes#

The scene/colorConversionMode property selects how the scene converts CMYK colors.

  • A scene that you create with engine.scene.create() is Managed and converts through the profile.
  • Applying a template or loading a scene takes the mode stored in that file. A template or scene saved before CE.SDK 1.83 is Legacy, and this includes the templates of the demo asset library.
  • A Legacy scene keeps the old CMYK conversion, which inverts the ink channels and blends a tint toward white. It also keeps the old decode of untagged CMYK JPEGs. So its CMYK colors and untagged CMYK JPEGs look as they did when you saved them.
  • A Legacy scene never needs a profile and never fails a conversion for a missing profile. A profile that you set on a Legacy scene has no effect until the scene becomes Managed.
  • Spot colors use the corrected approximation and tint in both modes. A CMYK spot approximation follows the mode. So spot gradient stops and tinted spot drop shadows can look different from the saved design, also in a Legacy scene.

Read the mode with engine.block.getEnum().

const scene = engine.scene.get()!;
const mode = engine.block.getEnum(scene, 'scene/colorConversionMode');
console.log('Color conversion mode:', mode);

To move a saved design to accurate colors, set the mode to Managed with engine.block.setEnum(). Its CMYK colors then change on screen and in raster exports, so review the design after the switch. The example switches to Legacy to show the old values, then back to Managed.

engine.block.setEnum(scene, 'scene/colorConversionMode', 'Legacy');
logConversions('Legacy mode');
engine.block.setEnum(scene, 'scene/colorConversionMode', 'Managed');

What Each Export Writes#

Output sRGB colors CMYK colors Spot colors Images
PNG, JPEG, WebP sRGB Converted through the profile, the same as the preview Approximation RGB
PDF (default) DeviceRGB DeviceRGB, converted through the profile Separation with a DeviceRGB alternate RGB
PDF with exportPdfWithDeviceCMYK: true DeviceRGB Solid colors: DeviceCMYK, ink values unchanged, tint multiplied in Named Separation. Its alternate is DeviceCMYK when the spot has a CMYK approximation, otherwise DeviceRGB RGB
  • A Legacy scene uses the earlier formula for these outputs, not the profile.
  • Gradient stops are always converted to RGB, also in a device-CMYK PDF. This includes CMYK and spot color stops.
  • The engine PDF embeds no OutputIntent and no ICC profile.
  • Overprint (setFillOverprint(), setStrokeOverprint()) applies to spot colors in a PDF only.

Export for Print#

To keep the print inks in a PDF:

  1. Set the document CMYK profile to your press condition, keep the scene Managed, and use CMYK or spot colors.
  2. Export the PDF with exportPdfWithDeviceCMYK: true, so the inks of solid colors reach the file. The ink values are unchanged, except that a tint below 1 scales them.
const png = await engine.block.export(page, { mimeType: 'image/png' });
const pdf = await engine.block.export(page, {
mimeType: 'application/pdf',
exportPdfWithDeviceCMYK: true
});
console.log('PNG bytes:', png.size, 'PDF bytes:', pdf.size);

The engine PDF has no OutputIntent and keeps images in RGB. The Export for Printing guide shows the next steps.

Troubleshooting#

The Error Catalog lists every COLOR.* error.

Symptom or error Cause Fix
The CMYK colors of an old design look the same after the upgrade It loaded as Legacy Set scene/colorConversionMode to Managed
The profile, intent or black point compensation has no effect after you apply a template The template was saved before 1.83, so the scene is Legacy Set scene/colorConversionMode to Managed
Black areas look lighter than before A key-only black now shows as it prints Use a rich black, or keep the accurate preview
COLOR.PROFILE_NOT_LOADED A conversion ran before the profile loaded Await engine.editor.loadCMYKProfile()
COLOR.PROFILE_MISSING from setCMYKProfile() The engine cannot load the URI Check the URI and CORS. The previous profile stays in effect
COLOR.PROFILE_MISSING from loadCMYKProfile() or a conversion The fallback profile does not load, so no profile is ready Check the URI in the error and the fallbackCMYKProfileUri setting
COLOR.PROFILE_SPACE_MISMATCH, COLOR.PROFILE_DATA_SPACE_MISMATCH The profile is not a CMYK profile Use a CMYK output profile
COLOR.PROFILE_INVALID, COLOR.PROFILE_UNSUPPORTED_SPACE The bytes are not a usable ICC profile Check the file
COLOR.PROFILE_ASSIGNMENT_SUPERSEDED A later set, remove or scene load replaced a pending set Expected. Await the latest call
COLOR.DOCUMENT_PROFILE_NOT_SET getCMYKProfileInfo() ran when the document names no profile Set a profile, or treat it as “the document uses the fallback”
COLOR.RENDERING_INTENT_INVALID The intent value is not 0 to 3 Use the ColorRenderingIntent enum
COLOR.IMAGE_DECODE_FAILED, COLOR.IMAGE_TRANSFORM_FAILED The engine cannot read a CMYK image or its profile The image loads unmanaged. Replace the file
A profile set from bytes is lost after a reload The scene was saved with saveToString() Save an archive

API Reference#

Method Description
engine.block.setColor(id, property, value) Set a color property on a block. Pass an RGBAColor, CMYKColor, or SpotColor object.
engine.block.getColor(id, property) Get the current color value from a property. Returns an RGBAColor, CMYKColor, or SpotColor object.
engine.editor.setSpotColorRGB(name, r, g, b) Define a spot color with an RGB approximation for screen preview. Components range from 0.0 to 1.0.
engine.editor.setSpotColorCMYK(name, c, m, y, k) Define a spot color with a CMYK approximation for screen preview. Components range from 0.0 to 1.0.
engine.scene.setCMYKProfile() Load the document CMYK profile from a URI
engine.scene.setCMYKProfileFromData() Set the document CMYK profile from bytes
engine.scene.getCMYKProfileInfo() Read the content hash of the document profile
engine.scene.removeCMYKProfile() Go back to the fallback profile
engine.scene.getColorRenderingIntent() Read the rendering intent
engine.scene.setColorRenderingIntent() Set the rendering intent
engine.scene.isBlackPointCompensationEnabled() Read black point compensation
engine.scene.setBlackPointCompensationEnabled() Turn black point compensation on or off
engine.editor.loadCMYKProfile() Wait until a CMYK profile is ready
engine.editor.convertColorToColorSpace() Convert a color through the document profile
engine.editor.setSetting('fallbackCMYKProfileUri', uri) Set the profile for documents that name none
engine.block.getEnum() / setEnum() with scene/colorConversionMode Read or switch Managed and Legacy
engine.block.export() with exportPdfWithDeviceCMYK Write CMYK inks to a PDF
Type Properties Description
RGBAColor r, g, b, a (0.0-1.0) sRGB color for screen display. Alpha controls transparency.
CMYKColor c, m, y, k, tint (0.0-1.0) CMYK color for print. Tint scales the ink amounts.
SpotColor name, tint, externalReference Named color for specialized printing.

Next Steps#

  • Apply Colors - Apply colors to design elements programmatically
  • CMYK Colors - Work with CMYK for print workflows
  • Spot Colors - Define and manage spot colors for specialized printing