Améliorer les graphiques avec du contenu à large gamme de couleurs

Android 8.0 (niveau d'API 26) offre la prise en charge de la gestion des couleurs pour des espaces de couleur, et le standard RVB (sRVB) pour le rendu graphique sur les appareils dotés d'écrans compatibles Grâce à ce soutien, votre application peut afficher des bitmaps avec des profils de couleur larges intégrés, chargés à partir de fichiers PNG, JPEG et WebP. via Java ou du code natif. Les applications qui utilisent OpenGL ou Vulkan peuvent générer directement du contenu à large gamme de couleurs (avec Display P3 et scRGB). Cette fonctionnalité est utile pour créer des applications impliquant une reproduction des couleurs haute fidélité, telles que les applications de retouche d'images et de vidéos.

Comprendre le mode large gamme de couleurs

Les profils de couleurs étendus sont des profils ICC, tels que Adobe RVB, Pro Photo RVB et DCI-P3, qui peuvent représenter une gamme de couleurs plus large que sRVB. Les écrans compatibles avec les profils de couleurs étendus peuvent afficher des images avec des couleurs primaires plus profondes (rouges, verts et bleus) ainsi que des couleurs secondaires plus riches (comme les magentas, les cyans et les jaunes).

Sur les appareils Android équipés d'Android 8.0 (niveau d'API 26) ou version ultérieure compatibles, votre application peut activer le mode couleur large gamme de couleurs pour une activité, ce qui permet au système de reconnaître et de traiter correctement les images bitmap avec des profils de couleurs larges intégrés. La La classe ColorSpace.Named énumère une liste partielle des types de fichiers couramment utilisés des espaces colorimétriques compatibles avec Android.

Remarque:Lorsque le mode large gamme de couleurs est activé, l'état utilise davantage de mémoire et de processeurs GPU pour la composition de l'écran. Avant d'activer le mode plage de couleurs étendue, vous devez bien réfléchir à l'utilité de cette fonctionnalité pour l'activité. Par exemple, une activité qui affiche des photos en plein écran est un bon candidat pour le mode large gamme de couleurs, mais ce n'est pas le cas d'une activité qui affiche de petites miniatures.

Activer le mode large gamme de couleurs

Utilisez l'attribut colorMode pour demander l'affichage de l'activité. en mode large gamme de couleurs sur les appareils compatibles. En mode large gamme de couleurs, une fenêtre en dehors de la gamme sRVB pour afficher des couleurs plus vives. Si l'appareil n'est pas compatible avec l'affichage en mode large gamme de couleurs, cet attribut n'a aucun effet. Si votre application doit déterminer si un écran donné est compatible avec la large gamme de couleurs, appelez la méthode isWideColorGamut(). Votre application peut aussi appeler isScreenWideColorGamut(), qui renvoie true Uniquement si l'écran offre une large gamme de couleurs et si l'appareil est compatible avec cette fonctionnalité le rendu des couleurs.

Un écran peut utiliser une large gamme de couleurs, mais ne pas gérer les couleurs. Dans ce cas, n'accordera pas à une application le mode large gamme de couleurs. Lorsqu'un écran n'est pas géré par les couleurs (comme c'était le cas pour toutes les versions d'Android antérieures à la version 8.0), le système remappe les couleurs dessinées par l'application sur la gamme de l'écran.

Pour activer la large gamme de couleurs dans votre activité, définissez l'attribut colorMode sur wideColorGamut dans votre fichier AndroidManifest.xml. Vous devez le faire pour chaque activité pour laquelle vous souhaitez activer le mode large gamme de couleurs.

android:colorMode="wideColorGamut"

Vous pouvez également définir le mode couleur par programmation dans votre activité en appelant la méthode la méthode setColorMode(int) et en transmettant COLOR_MODE_WIDE_COLOR_GAMUT

Afficher du contenu à large gamme de couleurs

Figure 1. Espaces de couleurs P3 (orange) ou sRVB (blanc) sur l'écran

Pour afficher du contenu à large gamme de couleurs, votre application doit charger un bitmap à larges couleurs, c'est-à-dire un bitmap avec un profil de couleur contenant un espace colorimétrique plus large que sRVB. Les profils de couleurs larges courants incluent Adobe RVB, DCI-P3 et Display P3.

Votre application peut interroger l'espace de couleurs d'un bitmap en appelant getColorSpace(). Pour déterminer si le système reconnaît un espace colorimétrique spécifique à une large gamme, vous pouvez appeler isWideGamut().

La classe Color vous permet de représenter une couleur avec quatre composants empaquetés dans une valeur de 64 bits, au lieu de la représentation la plus courante qui utilise une valeur entière. En utilisant des valeurs longues, vous pouvez définir des couleurs avec plus de précision que les valeurs entières. Si vous devez créer ou encoder une couleur en tant que valeur longue, utilisez l'une des méthodes pack() de la classe Color.

Vous pouvez vérifier si votre application a bien demandé le mode large gamme de couleurs en vérifiant que la méthode getColorMode() renvoie COLOR_MODE_WIDE_COLOR_GAMUT (cette méthode n'indique pas, mais si le mode large gamme de couleurs a été accordé).

Utiliser la compatibilité avec la large gamme de couleurs en code natif

Cette section explique comment activer le mode large gamme de couleurs avec la OpenGL et API Vulkan si votre application utilise du code natif.

OpenGL

Pour utiliser le mode plage de couleurs étendue dans OpenGL, votre application doit inclure la bibliothèque EGL 1.4 avec l'une des extensions suivantes :

Pour activer cette fonctionnalité, vous devez d'abord créer un contexte GL via eglChooseConfig, avec l'un des trois formats de tampon de couleur compatibles pour la couleur étendue dans les attributs. Le format de tampon de couleur pour la couleur étendue doit être l'un des ensembles de valeurs RVBA suivants :

  • 8, 8, 8, 8
  • 10, 10, 10, 2
  • FP16, FP16, FP16, FP16

Ensuite, demandez l'extension d'espace colorimétrique P3 lors de la création de votre cibles de rendu, comme indiqué dans l'extrait de code suivant:

std::vector<EGLint> attributes;
attributes.push_back(EGL_GL_COLORSPACE_KHR);
attributes.push_back(EGL_GL_COLORSPACE_DISPLAY_P3_EXT);
attributes.push_back(EGL_NONE);
engine->surface_ = eglCreateWindowSurface(
    engine->display_, config, engine->app->window, attributes.data());

Vulkan

La prise en charge de la large gamme de couleurs par Vulkan est assurée par l'extension VK_EXT_swapchain_colorspace.

Avant d'activer la prise en charge étendue des couleurs dans votre code Vulkan, vérifiez d'abord que est compatible avec vkEnumerateInstanceExtensionProperties Si l'extension est disponible, vous devez l'activer pendant vkCreateInstance avant de créer les images de la chaîne d'échange qui utiliser les espaces de couleur supplémentaires définis par l'extension.

Avant de créer la chaîne de permutation, vous devez choisir l'espace colorimétrique souhaité, puis lire en boucle les sur les surfaces physiques disponibles et choisissez un format de couleur valide espace colorimétrique.

Sur les appareils Android, Vulkan est compatible avec la large gamme de couleurs avec les espaces de couleurs et les formats de couleurs VkSurfaceFormatKHR suivants :

  • Espaces colorimétriques Vulkan à large gamme de couleurs :
    • VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT
    • VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT
  • Formats de couleurs Vulkan compatibles avec une large gamme de couleurs:
    • VK_FORMAT_R16G16B16A16_SFLOAT
    • VK_FORMAT_A2R10G10B10_UNORM_PACK32
    • VK_FORMAT_R8G8B8A8_UNORM

L'extrait de code suivant montre comment vérifier que l'appareil est compatible avec l'espace colorimétrique Display P3 :

uint32_t formatCount = 0;
vkGetPhysicalDeviceSurfaceFormatsKHR(
       vkPhysicalDev,
       vkSurface,
       &formatCount,
       nullptr);
VkSurfaceFormatKHR *formats = new VkSurfaceFormatKHR[formatCount];
vkGetPhysicalDeviceSurfaceFormatsKHR(
       vkPhysicalDev,
       vkSurface,
       &formatCount,
       formats);

uint32_t displayP3Index = formatCount;
for (uint32_t idx = 0; idx < formatCount; idx++) {
 if (formats[idx].format == requiredSwapChainFmt &&
     formats[idx].colorSpace==VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT)
 {
   displayP3Index = idx;
   break;
 }
}
if (displayP3Index == formatCount) {
    // Display P3 is not supported on the platform
    // choose other format
}

L'extrait de code suivant montre comment demander une chaîne d'échange Vulkan avec VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT:

uint32_t queueFamily = 0;
VkSwapchainCreateInfoKHR swapchainCreate {
   .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
   .pNext = nullptr,
   .surface = AndroidVkSurface_,
   .minImageCount = surfaceCapabilities.minImageCount,
   .imageFormat = requiredSwapChainFmt,
   .imageColorSpace = VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT,
   .imageExtent = surfaceCapabilities.currentExtent,
   .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
   .preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR,
   .imageArrayLayers = 1,
   .imageSharingMode = VK_SHARING_MODE_EXCLUSIVE,
   .queueFamilyIndexCount = 1,
   .pQueueFamilyIndices = &queueFamily,
   .presentMode = VK_PRESENT_MODE_FIFO_KHR,
   .oldSwapchain = VK_NULL_HANDLE,
   .clipped = VK_FALSE,
};
VkRresult status = vkCreateSwapchainKHR(
                       vkDevice,
                       &swapchainCreate,
                       nullptr,
                       &vkSwapchain);
if (status != VK_SUCCESS) {
    // Display P3 is not supported
    return false;
}