Color correct with look-up tables (LUTs)
Stay organized with collections
Save and categorize content based on your preferences.
Varying HDR capabilities across Android devices can lead to fragmented HDR
display outputs. A look-up table (LUT) is a new color correction solution
designed to resolve this inconsistency. This inconsistency is resolved by
prescribing a way to color correct, rather than delegating to an undefined
per-device color correction mechanism.
SDK prerequisites
To implement LUTs, your SDK version must 36 or higher.
Implement a LUT
Follow these steps to apply a LUT to a SurfaceControl
:
- Create a
DisplayLuts
instance.
- Create
DisplayLuts.Entry
instance(s) with the LUT data buffer,
LUT dimension, and the sampling key of the LUT. For more information,
see LutProperties
documentation.
- Call
DisplayLuts#set(DisplayLuts.Entry luts)
or
DisplayLuts#set(DisplayLuts.Entry first, DisplayLuts.Entry second)
to set LUT entries. The framework supports 1D LUT, 3D LUT, or a combination of
1D and 3D LUTs.
- Call
SurfaceControl.Transaction#setLuts
to apply the LUTs to the layer.
Kotlin
val sc = SurfaceControl.Builder().build()
val luts = DisplayLuts()
val entry = DisplayLuts.Entry(
floatArrayOf(0.5f, 0.5f, 0.5f, 0.5f),
LutProperties.ONE_DIMENSION,
LutProperties.SAMPLING_KEY_MAX_RGB
)
luts.set(entry)
SurfaceControl.Transaction().setLuts(sc, luts).apply()
Java
SurfaceControl sc = new SurfaceControl.Builder().build();
DisplayLuts luts = new DisplayLuts();
DisplayLuts.Entry entry = new DisplayLuts.Entry(
new float[]{0.5f, 0.5f, 0.5f, 0.5f},
LutProperties.ONE_DIMENSION,
LutProperties.SAMPLING_KEY_MAX_RGB
);
luts.set(entry);
new SurfaceControl.Transaction().setLuts(sc, luts).apply();
You can also use OverlayProperties.getLutProperties()
to understand the
LUT properties of the device, and determine if the Hardware Composer can handle
the selected LUT.
Content and code samples on this page are subject to the licenses described in the Content License. Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.
Last updated 2025-08-26 UTC.
[[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Missing the information I need","missingTheInformationINeed","thumb-down"],["Too complicated / too many steps","tooComplicatedTooManySteps","thumb-down"],["Out of date","outOfDate","thumb-down"],["Samples / code issue","samplesCodeIssue","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2025-08-26 UTC."],[],[],null,["# Color correct with look-up tables (LUTs)\n\nVarying HDR capabilities across Android devices can lead to fragmented HDR\ndisplay outputs. A look-up table (LUT) is a new color correction solution\ndesigned to resolve this inconsistency. This inconsistency is resolved by\n*prescribing* a way to color correct, rather than delegating to an undefined\nper-device color correction mechanism.\n\nSDK prerequisites\n-----------------\n\nTo implement LUTs, your SDK version must 36 or higher.\n\nImplement a LUT\n---------------\n\nFollow these steps to apply a LUT to a [`SurfaceControl`](/reference/android/view/SurfaceControl):\n\n1. Create a [`DisplayLuts`](/reference/android/hardware/DisplayLuts) instance.\n2. Create [`DisplayLuts.Entry`](/reference/android/hardware/DisplayLuts.Entry) instance(s) with the LUT data buffer, LUT dimension, and the sampling key of the LUT. For more information, see [`LutProperties`](/reference/android/hardware/LutProperties) documentation.\n3. Call [`DisplayLuts#set(DisplayLuts.Entry luts)`](/reference/android/hardware/DisplayLuts#set(android.hardware.DisplayLuts.Entry)) or [`DisplayLuts#set(DisplayLuts.Entry first, DisplayLuts.Entry second)`](/reference/android/hardware/DisplayLuts#set(android.hardware.DisplayLuts.Entry,%20android.hardware.DisplayLuts.Entry)) to set LUT entries. The framework supports 1D LUT, 3D LUT, or a combination of 1D and 3D LUTs.\n4. Call [`SurfaceControl.Transaction#setLuts`](/reference/android/view/SurfaceControl.Transaction#setLuts(android.view.SurfaceControl,%20android.hardware.DisplayLuts)) to apply the LUTs to the layer.\n\n### Kotlin\n\n val sc = SurfaceControl.Builder().build()\n val luts = DisplayLuts()\n val entry = DisplayLuts.Entry(\n floatArrayOf(0.5f, 0.5f, 0.5f, 0.5f),\n LutProperties.ONE_DIMENSION,\n LutProperties.SAMPLING_KEY_MAX_RGB\n )\n luts.set(entry)\n SurfaceControl.Transaction().setLuts(sc, luts).apply()\n\n### Java\n\n SurfaceControl sc = new SurfaceControl.Builder().build();\n DisplayLuts luts = new DisplayLuts();\n DisplayLuts.Entry entry = new DisplayLuts.Entry(\n new float[]{0.5f, 0.5f, 0.5f, 0.5f},\n LutProperties.ONE_DIMENSION,\n LutProperties.SAMPLING_KEY_MAX_RGB\n );\n luts.set(entry);\n new SurfaceControl.Transaction().setLuts(sc, luts).apply();\n\nYou can also use [`OverlayProperties.getLutProperties()`](/reference/android/hardware/OverlayProperties#getLutProperties()) to understand the\nLUT properties of the device, and determine if the Hardware Composer can handle\nthe selected LUT."]]