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 qui impliquent une reproduction haute fidélité des couleurs, comme des images et des vidéos des applications de retouche.

Comprendre le mode large gamme de couleurs

Les profils de couleur larges sont Profils ICC, tels que Adobe RVB, <ph type="x-smartling-placeholder"></ph> Pro Photo RVB et DCI-P3, qui sont capable de représenter une gamme de couleurs plus large que sRVB. Écrans compatibles avec les profils de couleurs larges peut afficher des images avec des couleurs primaires plus intenses (rouge, vert et bleu) et des couleurs secondaires plus riches (magentas, cyans et jaunes, par exemple).

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 en palette de couleurs sur une large gamme de couleurs pour une activité au cours de laquelle le système reconnaît et 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 la large gamme de couleurs , vous devez déterminer avec soin si l'activité en est réellement bénéfique. Par exemple, un qui affiche des photos en plein écran est adaptée au mode large gamme de couleurs, une activité affichant de petites vignettes ne l'est pas.

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 les couleurs larges dans la gamme, cet attribut n'a aucun effet. Si votre application doit déterminer si un élément donné est compatible avec une 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 des couleurs Comme c'était le cas pour toutes les versions d'Android antérieures à 8.0, le système remappe couleurs dessinées par l'application sur la gamme de l'écran.

Pour activer la large gamme de couleurs dans votre activité, définissez le colorMode à wideColorGamut dans votre fichier AndroidManifest.xml. Toi 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

<ph type="x-smartling-placeholder">
</ph>
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 couleur larges courants incluent Adobe RVB, DCI-P3 et Display P3.

Votre application peut interroger l'espace colorimétrique 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ée dans une valeur de 64 bits, au lieu de la représentation la plus courante qui utilise un nombre entier . 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 large gamme de couleurs 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'une des trois options formats de tampon de couleur pour l'utilisation de couleurs larges dans les attributs. Format du tampon de couleur pour les écrans larges La couleur doit correspondre à 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 compatibilité de Vulkan avec la large gamme de couleurs est fournie via le VK_EXT_swapchain_colorspace extension.

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 prend en charge une large gamme de couleurs avec les espaces de couleur et les VkSurfaceFormatKHR format de couleur:

  • Espaces de couleurs à large gamme de couleurs Vulkan: <ph type="x-smartling-placeholder">
      </ph>
    • 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: <ph type="x-smartling-placeholder">
      </ph>
    • 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'écran P3 espace colorimétrique:

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;
}