Android Color Management: What Developers and Designers Need to Know
In the recent Oreo release, Android gained initial support for color management — which helps match color outputs across devices. With the update, Android devices can now display colors outside of the sRGB color gamut. If you’re not familiar with color profiles or what wide color gamuts are, then I highly recommend this video from Google I/O on understanding color:
tl;dw; color management ensures that colors look the same on different displays. For example the color
#ff0000 (pure red for those that don’t read hex codes) may appear differently depending upon the screen technology showing it — some screens are capable of showing more saturated or intense colors than others. Saying
#ff0000 in sRGB specifies a specific shade of red (in the sRGB color space) so color managed displays can produce the exact desired color.
In this post I’d like to outline what Android app designers and developers need to know about these changes.
Displaying wide color gamut images
Images can embed a color profile, declaring the color space of their color information. Similarly many cameras are capable of capturing wide color gamuts and embedding an appropriate color profile. This lets them display colors beyond the standard sRGB gamut. To display images with wide color profiles in your app you need to opt-in per
Activity. To do this, set the
colorMode attribute in the activity’s declaration in your application’s manifest:
You can also set this programmatically but you need to do so during
onCreate before your
Window is created. Wide color gamut support is opt-in as it requires more system resources (which might result in a performance decrease in your app):
“When wide color gamut mode is enabled, the activity’s window uses more memory and GPU processing for screen composition. Before enabling wide color gamut mode, you should carefully consider if the activity truly benefits from it. For example, an activity that displays photos in fullscreen is a good candidate for wide color gamut mode, but an activity that shows small thumbnails is not.” — developer documentation
Note that if you are using a single
Activityarchitecture then it may make sense to break out wide color gamut image display into a new
Here’s an example showing two activities displaying the same wide color gamut test image (a PNG with the Display P3 color profile embedded), the top activity declares a wide color gamut color mode, the bottom does not.
Color accurate rendering
Many Android devices have had screens capable of displaying wider color gamuts for some time. Prior to Android 8.0’s color management, all content was assumed to be sRGB but wide color displays would reinterpret the color values into their gamut and effectively “stretch” the colors. This makes reds more red, greens more green, etc. leading to a more saturated appearance. This stretching however is imprecise and there is no way to calculate the stretching effect, hence the rendered colors are not accurate.
Many applications have desaturated their assets to compensate for this stretching. As a consequence, colors may appear muted when displayed on devices with calibrated displays. That is on color-accurate devices, such as the Pixel 2, desaturated assets will appear less vivid than on non-accurate displays. Once color-accurate rendering is widespread, app makers can stop altering assets and be confident that their content displays as intended. Until then however, there are some steps that you can take to ensure that your content looks great on both color accurate displays, and on non-color-managed devices.
Android 8.0 adds a new
widecg resource qualifier which you can use to alter colors on devices whose screen has a wide color gamut and wide color gamut rendering is supported (also
nowidecg for the inverse).
Note that wide color gamut support is distinct from whether the current activity is running in
wideColorGamutcolor mode. That is this qualifier will apply if the device supports color accurate rendering, irrespective of whether the activity is running in wide color mode.
For example an application may declare a base palette of colors in
<!-— desaturated colors used on non color accurate displays -->
…and an alternate set in
<!-— desired colors as rendered on color accurate displays -->
You can use the same technique with raster assets (e.g.
res/drawable-widecg-mdpi/foo.png) but this will require shipping near-duplicate assets so it may not be worth the trade-off of increasing the size of your app. Consider moving to vector assets which can be colored dynamically.
Wider support coming
While we recently announced plans to add a new ‘saturated’ color mode letting users choose to opt out of color-accurate rendering (i.e. act like a
nowidecg devices), I still believe it’s important to update your apps for a color-managed world. By updating your apps to better support color accurate rendering fewer users will feel the need to opt out of this mode. We plan to continue investing in wide-color support; adding more API surface for working with wide color gamuts in future releases (such as updated
Canvas APIs accepting colors with greater bit precision).
The reality of modern displays is that designers and developers now need to have an understanding of color management and how to apply it within their app. As more devices ship with wide gamut displays and color-accurate rendering, it’s important to get ahead of the wave and update your apps to provide the best experience. We consider this the best way to deliver a great experience to your users where the colors they see are those you intended.