How to generate creatives with rich colours on the web
Our experiments in generating images with a wide gamut of colours through a web-based image editor.
The problem
For a recent campaign, one of our customers wanted to use creatives with bright colours. While making these creatives on our web-based editor, it looked bright, but the generated output looked faded.
What the customer wanted vs what we generated
Our findings
When we analyzed the metadata of the output images, we realized that the colour profile was getting set to sRGB IEC61966-2.1.
A little intro on digital colours
Let’s try to understand colours and how they are displayed digitally.
Colour models - A colour model is a way to represent and describe colours. It defines how colours are created by combining different components. The most common colour models are RGB (Red, Green, Blue) and CMYK (Cyan, Magenta, Yellow, and Black).
Colour spaces define the number of colours available (sRGB, Display P3).
And colour profile instructs how to accurately display those colours on specific devices or applications.
The following animation shows the colours available in different colour spaces. Gray denotes the colour range most human eyes can see. The colours in the triangle are what is supported by digital screens. sRGB (the smaller triangle) used to be standard on the internet. But a lot has changed in the past few years, which becomes evident from this article. (Courtesy: wigglepixel.nl)
New learnings
We realized that since Chrome 94, display-p3 support was available for the canvas element.
opts = {colorSpace:'display-p3'};
const ctx = canvas.getContext('2d', opts);
Even though Chrome started support for display-p3 for users, an option to take screenshots with ‘display-p3’ colour profile via the Chrome Developer Protocol was missing at the time of writing this article:
How to retain the original colours?
The original colours used to generate the creation were in Display P3 (containing more expansive colours than sRGB). When we take the final screenshot using Puppeteer, Chrome takes the screenshots in sRGB. As Puppeteer took the screenshot in a headless Chrome instance (both in a lambda or a VM instance), no physical monitor was involved. A few of the approaches we took are the following:
Tweak the virtual display to render in a display-p3 colour profile.
Force chrome to render in display-p3 profile using experimental tags.
We started working on this issue around mid-April. We took time to break down different parts of our infrastructure, create standalone experiments, tweak, and test the results. Red lines show failed experiments, green shows successful experiments, and grey are pending experiments.
A significant shift in finding the solution happened when we took a step back and asked fundamental questions about the approaches taken.
Instead of tweaking the colour profiles of the virtual display, we thought of attaching the desired colour profile to the generated image. To quickly check our approach, we used the Assign Profile feature in the Preview tool on Mac to assign a Display P3 profile. The results were very close to the desired output.
An interim solution
The solution, for now, was to programmatically attach the Display-P3 colour profile after an image was generated.
With this knowledge, we were able to:
Bring support for a broader range of colours in our output.
Fix the fade-out issue during the import of PSD files.
Improve our colours in video output.
Drawbacks of the current approach
We still lose some details of the images even if we can retain the colours.
Resources
Oklab - A perceptual colour space for image processing
The author, after running and documenting the experiments.
Updates
With the latest release of Chrome 114, we have access to more colours on the web:
A deeper article about colours and colour-profiles on the web by Adam Argyle from the Chrome Dev Rel team.